Hi,
Using libclang, I’d like to visit that part of the AST which is connected to a class template instantiation.
I’m wondering if I could have the same behaviour with clang_visitChildern as with RecursiveASTVisitor with shouldVisitTemplateInstantiations() returning true.
Currently when I use clang_visitChildren, I can traverse only through the StructDecl and a TypeRef node , but the child nodes are not reachable.
Do I have any feasible option with libclang to recurse into the ClassTemplateSpecializationDecl part of the AST? Or must I use libtooling (and RecursiveASTVisitor or the matchers) rather?
Many thanks,
Gábor
Detailed explanation via an example:
struct A {
void foo() {}
};
template
struct X {
void f() {
T t;
t.foo();
}
};
template struct X;
Visitation with clang_visitChildren:
StructDecl c A def main.cpp:1:8
CXXMethod c foo() foo def main.cpp:2:10
CompoundStmt o
ClassTemplate c X X def main.cpp:5:8
TemplateTypeParameter c T def main.cpp:4:20
CXXMethod c f() f def main.cpp:6:10
CompoundStmt o
DeclStmt o
VarDecl c t def main.cpp:7:11
TypeRef r T main.cpp:7:9
CallExpr r main.cpp:8:9
MemberRefExpr r main.cpp:8:9
DeclRefExpr r t main.cpp:8:9
StructDecl c X X def main.cpp:11:17
TypeRef r struct A main.cpp:11:19
Visitation with RecursiveASTVisitor:
-CXXRecordDecl 0x1030316b0 <main.cpp:1:1, line:3:1> line:1:8 referenced struct A definition
-CXXRecordDecl 0x1030317c0 <col:1, col:8> col:8 implicit struct A
-CXXMethodDecl 0x1030318a0 <line:2:5, col:17> col:10 used foo ‘void (void)’
-CompoundStmt 0x103031978 <col:16, col:17> -CXXConstructorDecl 0x103079250 <line:1:8> col:8 implicit used A 'void (void) throw()' inline
-CompoundStmt 0x103079560 col:8
-CXXConstructorDecl 0x103079380 <col:8> col:8 implicit A 'void (const struct A &)' inline noexcept-unevaluated 0x103079380
-ParmVarDecl 0x1030794c0 col:8 col:8 ‘const struct A &’
-ClassTemplateDecl 0x1030788d0 <line:4:1, line:10:1> line:5:8 X
-TemplateTypeParmDecl 0x103031990 <line:4:11, col:20> col:20 referenced typename T
-CXXRecordDecl 0x103078840 <line:5:1, line:10:1> line:5:8 struct X definition-CXXRecordDecl 0x103078b50 <col:1, col:8> col:8 implicit struct X
-CXXMethodDecl 0x103078c00 <line:6:5, line:9:5> line:6:10 f 'void (void)'
-CompoundStmt 0x103078e10 <col:14, line:9:5>
-DeclStmt 0x103078d50 <line:7:9, col:12>
-VarDecl 0x103078cf0 <col:9, col:11> col:11 referenced t 'T'
-CallExpr 0x103078de8 <line:8:9, col:15> ‘’
-CXXDependentScopeMemberExpr 0x103078d90 <col:9, col:11> '<dependent type>' lvalue
-DeclRefExpr 0x103078d68 col:9 ‘T’ lvalue Var 0x103078cf0 ‘t’ ‘T’
-ClassTemplateSpecialization 0x103078e50 'X'
-ClassTemplateSpecializationDecl 0x103078e50 <line:11:1, col:20> col:17 struct X definition
-TemplateArgument type ‘struct A’
-CXXRecordDecl 0x103079040 prev 0x103078e50 <line:5:1, col:8> col:8 implicit struct X
-CXXMethodDecl 0x1030790d0 <line:6:5, line:9:5> line:6:10 f 'void (void)'
-CompoundStmt 0x103079640 <col:14, line:9:5>
-DeclStmt 0x1030795a8 <line:7:9, col:12>
-VarDecl 0x1030791d0 <col:9, col:11> col:11 used t 'struct A':'struct A' callinit
-CXXConstructExpr 0x103079578 col:11 ‘struct A’:‘struct A’ ‘void (void) throw()’
-CXXMemberCallExpr 0x103079618 <line:8:9, col:15> 'void'
-MemberExpr 0x1030795e8 <col:9, col:11> ‘’ .foo 0x1030318a0
`-DeclRefExpr 0x1030795c0 col:9 ‘struct A’:‘struct A’ lvalue Var 0x1030791d0 ‘t’ ‘struct A’:‘struct A’