72

Is there a way to see the compiler-instantiated code for a function template or a class template in C++?

Assume I have the following piece of code:

template <class T> T add(T a, T b) {
    return a + b;
}

When I call:

add<int>(10, 2); 

... I would like to see the function that the compiler creates for the int template specialization.

I am using g++, VC++, and need to know the compiler options to achieve this.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Vineel Kumar Reddy
  • 4,588
  • 9
  • 33
  • 37

8 Answers8

98

Clang (https://clang.llvm.org/) can pretty-print AST of instantiated template:

For your example:

test.cpp

template < class T> T add(T a, T b){
    return a+b;
}

void tmp() {
    add<int>(10,2); 
}

Command to pretty-print AST:

$ clang++ -Xclang -ast-print -fsyntax-only test.cpp

Clang-5.0/Clang 14.0 output:

template <class T> T add(T a, T b) {
    return a + b;
}
template<> int add<int>(int a, int b) {
    return a + b;
}
void tmp() {
    add<int>(10, 2);
}
prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42
random
  • 3,868
  • 3
  • 22
  • 39
  • 3
    I believe this is the best answer the OP is looking for (when compared with the other alternatives). – Anubis Aug 15 '19 at 19:49
40

If you want to see the assembly output, use this:

g++ -S file.cpp

If you want to see some (pseudo) C++ code that GCC generates, you can use this:

g++ -fdump-tree-original file.cpp

For your add function, this will output something like

;; Function T add(const T&, const T&) [with T = int] (null)
;; enabled by -tree-original

return <retval> = (int) *l + (int) *r;

(I passed the parameters by reference to make the output a little more interesting)

mtvec
  • 17,846
  • 5
  • 52
  • 83
23

You can definitely see the assembly code generated by the g++ using the "-S" option.

I don't think it is possible to display the "C++" equivalent template code - but I would still want a g++ developer to chime in why - I don't know the architecture of gcc.

When using assembly, you can review the resulting code looking for what resembles your function. As a result of running gcc -S -O1 {yourcode.cpp}, I got this (AMD64, gcc 4.4.4)

_Z3addIiET_S0_S0_:
.LFB2:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    leal    (%rsi,%rdi), %eax
    ret
    .cfi_endproc

Which really is just an int addition (leal).

Now, how to decode the c++ name mangler? there is a utility called c++filt, you paste the canonical (C-equivalent) name and you get the demangled c++ equivalent

qdot@nightfly /dev/shm $ c++filt 
_Z3addIiET_S0_S0_ 
int add<int>(int, int)
qdot
  • 6,195
  • 5
  • 44
  • 95
  • If people were allowed to see the generated template code, it would probably be too much to read anyway... in case of the STL – Johan Kotlinski Dec 16 '10 at 10:48
  • 6
    Well, people are allowed to see the generated assembly, it is quite a bit already, however, sometimes it is just what you need to gain valuable insight.. – qdot Dec 16 '10 at 19:22
  • 2
    @qdot it is completely different to see the assembly and the c++ generated code. Sometimes you want to generate the hierarchy of the classes by using the TypeLists then you probably will need to see the results as a c++ code just to be sure in your hierarchy. Assembly doesn't help at all in this case. – AlexTheo Jan 19 '13 at 14:00
23

Now there is an on-line tool which does this for you: https://cppinsights.io/ For example, this code

template<class X, class Y> auto add(X x, Y y) {
  return x + y;
}

int main()
{
  return add(10, 2.5);
}

Is translated to

template<class X, class Y> auto add(X x, Y y) {
  return x + y;
}

/* First instantiated from: insights.cpp:9 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
double add<int, double>(int x, double y)
{
  return static_cast<double>(x) + y;
}
#endif


int main()
{
  return static_cast<int>(add(10, 2.5));
}
SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • 1
    This should be the accepted answer. What a great find! In [the somewhat well-hidden About page](https://cppinsights.io/about.html), the author explains that C++ Insights is based on Clang but does a lot of its own work to produce more thorough and ideally C++-compilable 'intermediate' code than pretty-printed AST as in [this other answer](https://stackoverflow.com/a/46573566/2757035) would get. It also produces 'raw' versions of things like range-based `for` loops, too. Very exciting! – underscore_d Jan 02 '20 at 15:06
  • @underscore_d yes, I also think it is a fantastic tool, which can be extremely helpful in some cases. As for accepted answer - yeah, it would be nice for visibility, as while people can debate pretty-print AST, I am 100% sure it is better than currently accepted answer of ASM. – SergeyA Jan 02 '20 at 16:22
3

When the optimizer has done its deeds, you most likely have nothing left that looks like a function call. In your specific example, you'll definitely end up with an inlined addition, at worse. Other than that, you can always emit the generated assembler in a separate file during compilation, and there lies your answer.

Johann Gerell
  • 24,991
  • 10
  • 72
  • 122
2

The easiest is to inspect the generated assembly. You can get an assembly source by using -S flag for g++.

Johan Kotlinski
  • 25,185
  • 9
  • 78
  • 101
2

I think c++ Insights is what you want.

maidamai
  • 712
  • 9
  • 26
1

If your looking for the equivalent C++ code then no. The compiler never generates it. It's much faster for the compiler to generate it's intermediate representation straight off than to generate c++ first.

dan_waterworth
  • 6,261
  • 1
  • 30
  • 41