[cfe-dev] How to get the location of a function that's instantiated before the template is defined?

Joshua Naismith fakju666 at o2.pl
Sun Sep 8 12:25:58 PDT 2013


Consider the following example:

>>>>>>>>>>>>>>>>>>
template <class T>
inline T foo (T a);

void test(){
  foo<int>(1);
}

template <class T>
inline T foo (T a) {};
<<<<<<<<<<<<<<<<<<

foo<int> is instantiated before it's defined. Due to this, Decl::getLocation() for the FunctionDecl node will return the location of the declaration (line 2, column 10). This is expected and works the same for regular functions. However, while 2 FunctionDecl nodes would be generated for a regular function -- 1 for the declaration and 1 for the definition -- there's only 1 FunctionDecl node for the function template instantiation, as seen in the AST (0x531e280):

|-FunctionTemplateDecl 0x52f13f0 <test-src/main.cpp:1:1, line:2:18> foo
| |-TemplateTypeParmDecl 0x52f1190 <line:1:11, col:17> class T
| |-FunctionDecl 0x52f1350 <line:2:1, col:18> foo 'T (T)' inline
| | `-ParmVarDecl 0x52f1250 <col:15, col:17> a 'T'
| `-FunctionDecl 0x531e280 <line:9:1, col:21> foo 'int (int)' inline
|   |-TemplateArgument type 'int'
|   |-ParmVarDecl 0x531e180 <line:2:15, col:17> a 'int':'int'
|   `-CompoundStmt 0x531e710 <line:9:20, col:21>
|-FunctionDecl 0x531de50 <line:4:1, line:6:1> test 'void (void)'
| `-CompoundStmt 0x531e4b0 <line:4:12, line:6:1>
|   `-CallExpr 0x531e480 <line:5:3, col:13> 'int':'int'
|     |-ImplicitCastExpr 0x531e468 <col:3, col:10> 'int (*)(int)' <FunctionToPointerDecay>
|     | `-DeclRefExpr 0x531e390 <col:3, col:10> 'int (int)' lvalue Function 0x531e280 'foo' 'int (int)' (FunctionTemplate 0x52f13f0 'foo')
|     `-IntegerLiteral 0x531dfa8 <col:12> 'int' 1
|-FunctionTemplateDecl 0x531e6c0 prev 0x52f13f0 <line:8:1, line:9:21> foo
| |-TemplateTypeParmDecl 0x531e4d0 <line:8:11, col:17> class T
| |-FunctionDecl 0x531e620 prev 0x52f1350 <line:9:1, col:21> foo 'T (T)' inline
| | |-ParmVarDecl 0x531e560 <col:15, col:17> a 'T'
| | `-CompoundStmt 0x531e710 <col:20, col:21>
| `-Function 0x531e280 'foo' 'int (int)'

The same goes for the parameter -- it references the location of the declaration. Also, FunctionDecl::isThisDeclarationADefinition() returns true, while FunctionDecl::isDefined returns self as the definition, even when the node is located where the declaration is.

How do I get the exact location of the function template (and its parameters) definition from the FunctionDecl 0x531e280? This is not a problem for regular functions, because I'd just record the function as a declaration when isThisDeclarationADefinition() returns false and get the actual definition location from the node returned from isDefined. Decl::getLocation() returns line 2 column 10, Decl::getLocStart() returns line 9 column 1, Decl::getLocEnd() returns line 9 column 21, and the actual location is line 9 column 10.




More information about the cfe-dev mailing list