I am reading this answer to generate a well-look call graph with clang++-13 and opt-13
❯ clang++-13 --version
Homebrew clang version 13.0.1
Target: x86_64-apple-darwin22.5.0
Thread model: posix
InstalledDir: /usr/local/bin
❯ opt-13 --version
Homebrew LLVM version 13.0.1
Optimized build.
Default target: x86_64-apple-darwin22.5.0
Host CPU: westmere
Here is an example code:
#include <vector>
struct A {
A(int);
void f(); // not defined, prevents inlining it!
};
int main() {
std::vector<A> v;
v.push_back(42);
v[0].f();
}
Here is the command I am using:
clang++-13 -S -emit-llvm main1.cpp -o - |
opt-13 -analyze -std-link-opts -dot-callgraph -enable-new-pm=0
Here comes a message but I don't understand it:
Writing '<stdin>.callgraph.dot'...
Printing analysis 'Print call graph to 'dot' file':
Pass::print not implemented for pass: 'Print call graph to 'dot' file'!
Since the dot file is still generated, I ran the following command:
cat \<stdin\>.callgraph.dot |
c++filt |
sed 's,>,\\>,g; s,-\\>,->,g; s,<,\\<,g' |
gawk '/external node/{id=$1} $1 != id' |
dot -Tpng -ocallgraph.png
And this is the result:
This is far way out what I expected:

I don't see any difference between the answer and mine, however the output is different. I understand what shown in my output are decorated function names, yet read and understand them is tormenting.
I wonder if there are ways to improve my output, or read and understand the output more efficiently?
Update
I have outlined the progress in my answer below. However, the question is not fully answered:
- Is there a way to parse decorated function names on MacOS?
- The generated graph is still huge, but we can wish it gets smaller, by omitting some too-detailed nodes. But, how?

The function name demangling problem is with LLVM's
c++filt. Here is a small demonstration:You can generate a dot file with
clangandopteither on MacOS or Linux. The specific instructions may vary due to the version of yourclangandopt, but generally they are the same. I usedclang++-13andopt-13in my original question, and here I useclang++-14andopt-14The decorated function names are like:
If we use LLVM's
c++filt, it can not parse it:However, if we use GNU's
c++filt:Things just work fine