This is an archive of the discontinued LLVM Phabricator instance.

Lost template argument information in DeclRefExprs
Needs ReviewPublic

Authored by stefanmoosbrugger on Jan 27 2015, 4:24 AM.

Details

Reviewers
None
Group Reviewers
Restricted Project
Summary

When calling a templated method in the body of another templated method
the template argument information of the call gets lost.

The example below shows this case. The templated test function calls the
templated foo function.

EXAMPLE:

template <typename U>
void foo() {
 //some body...
}

template <typename T>
void test() {
 foo<float>();
}

int main() {
 test<int>();
 return 0;
}

AST:

foo function AST
FunctionTemplateDecl 0x1618250 </tmp/test3.cpp:1:1, line:4:1> foo
|-TemplateTypeParmDecl 0x16180b0 <line:1:11, col:20> typename U
|-FunctionDecl 0x16181b0 <line:2:1, line:4:1> foo 'void (void)'
| `-CompoundStmt 0x1618298 <line:2:12, line:4:1>
`-FunctionDecl 0x1661680 <line:2:1, line:4:1> foo 'void (void)'
  |-TemplateArgument type 'float'
  `-CompoundStmt 0x1618298 <line:2:12, line:4:1>
test function AST
FunctionTemplateDecl 0x16614a0 <line:6:1, line:9:1> test
|-TemplateTypeParmDecl 0x16182b0 <line:6:11, col:20> typename T
|-FunctionDecl 0x1618350 <line:7:1, line:9:1> test 'void (void)'
| `-CompoundStmt 0x1661868 <line:7:13, line:9:1>
|   `-CallExpr 0x1661840 <line:8:2, col:13> 'void'
|     `-ImplicitCastExpr 0x1661828 <col:2, col:11> 'void (*)(void)' <FunctionToPointerDecay>
|       `-DeclRefExpr 0x1661780 <col:2, col:11> 'void (void)' lvalue Function 0x1661680 'foo' 'void (void)' (FunctionTemplate 0x1618250 'foo')
`-FunctionDecl 0x1661b70 <line:7:1, line:9:1> test 'void (void)'
  |-TemplateArgument type 'int'
  `-CompoundStmt 0x1661e40 <line:7:13, line:9:1>
    `-CallExpr 0x1661e18 <line:8:2, col:13> 'void'
      `-ImplicitCastExpr 0x1661e00 <col:2, col:11> 'void (*)(void)' <FunctionToPointerDecay>
        `-DeclRefExpr 0x1661d90 <col:2, col:11> 'void (void)' lvalue Function 0x1661680 'foo' 'void (void)'
main function AST
FunctionDecl 0x16618e0 <line:11:1, line:14:1> main 'int (void)'
`-CompoundStmt 0x1661d68 <line:11:12, line:14:1>
  |-CallExpr 0x1661d00 <line:12:2, col:12> 'void'
  | `-ImplicitCastExpr 0x1661ce8 <col:2, col:10> 'void (*)(void)' <FunctionToPointerDecay>
  |   `-DeclRefExpr 0x1661c70 <col:2, col:10> 'void (void)' lvalue Function 0x1661b70 'test' 'void (void)' (FunctionTemplate 0x16614a0 'test')
  `-ReturnStmt 0x1661d48 <line:13:2, col:9>
    `-IntegerLiteral 0x1661d28 <col:9> 'int' 0

In the AST we can see a template instantiation of test<int> (0x1661b70),
and this template instantiation contains a call to foo<float> (0x1661680).
This call is visible in the CallExpr (0x1661e18) that captures a
DeclRefExpr (0x1661d90). The problem occurs when checking this DeclRefExpr
for explicit template arguments. The call to declRef->hasExplicitTemplateArgs()
will always return false (even when it has explicit template arguments), because
the template argument information is not passed to the instances of the
templated function.

In TreeTransform.h method RebuildDeclRefExpr
we can find a FIXME comment that says: loses template args.
The following patch should solve this issue.
Unit tests have been executed like described in http://clang.llvm.org/hacking.html
and http://llvm.org/docs/TestingGuide.html#testsuiterun. I hope this is the correct
way to test that the patch doesn't break anything else?!

Cheers,
Stefan Moosbrugger

Diff Detail

Event Timeline

stefanmoosbrugger retitled this revision from to Lost template argument information in DeclRefExprs.
stefanmoosbrugger updated this object.
stefanmoosbrugger edited the test plan for this revision. (Show Details)
stefanmoosbrugger added a subscriber: Unknown Object (MLST).
stefanmoosbrugger updated this object.
stefanmoosbrugger updated this object.
stefanmoosbrugger updated this object.
stefanmoosbrugger updated this object.
stefanmoosbrugger updated this object.
stefanmoosbrugger added a reviewer: Restricted Project.Feb 18 2015, 11:17 PM