aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-24 20:39:49 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-24 20:39:49 +0000
commit5482dc3a88fce51307b5e1e19bdf72dea1562040 (patch)
tree528f3a6a73d93be6d4fa4b81e26aeeb9171de424
parent4fe261cb0a6420b103335acc1f6bcb7b72188184 (diff)
RecursiveASTVisitor: Visit instantiations of member templates of class
templates. In an implicit instantiation of a member class, any member templates don't get instantiated, so the existing check which only visited the instantiations of a defined template skipped these templates' instantiations. Since there is only a single declaration of a member template of a class template specialization, just use that to determine whether to visit the instantiations. This introduces a slight inconsistency in that we will visit the instantiations of such templates whether or not they are defined, but we never visit a declared-but-not-defined instantiation, so this turns out to not matter. Patch by Daniel Jasper! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155487 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h6
-rw-r--r--unittests/Tooling/RecursiveASTVisitorTest.cpp23
2 files changed, 23 insertions, 6 deletions
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 465ed12dae..e91b68cd42 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1436,7 +1436,8 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, {
if (getDerived().shouldVisitTemplateInstantiations()) {
// If this is the definition of the primary template, visit
// instantiations which were formed from this pattern.
- if (D->isThisDeclarationADefinition())
+ if (D->isThisDeclarationADefinition() ||
+ D->getInstantiatedFromMemberTemplate())
TRY_TO(TraverseClassInstantiations(D, D));
}
@@ -1489,7 +1490,8 @@ DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
//
// In addition, we only traverse the function instantiations when
// the function template is a function template definition.
- if (D->isThisDeclarationADefinition()) {
+ if (D->isThisDeclarationADefinition() ||
+ D->getInstantiatedFromMemberTemplate()) {
TRY_TO(TraverseFunctionInstantiations(D));
}
}
diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp
index 8ddae504a0..6ef2786210 100644
--- a/unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -208,8 +208,7 @@ TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
"void foo() { y<Y>(Y()); }"));
}
-/* FIXME:
-TEST(RecursiveASTVisitor, VisitsCallInNestedTemplateInstantiation) {
+TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
CXXMemberCallVisitor Visitor;
Visitor.ExpectMatch("Y::x", 4, 5);
EXPECT_TRUE(Visitor.runOver(
@@ -221,7 +220,24 @@ TEST(RecursiveASTVisitor, VisitsCallInNestedTemplateInstantiation) {
"};\n"
"void foo() { Z<Y>::f<int>(); }"));
}
-*/
+
+TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
+ CXXMemberCallVisitor Visitor;
+ Visitor.ExpectMatch("A::x", 5, 7);
+ EXPECT_TRUE(Visitor.runOver(
+ "template <typename T1> struct X {\n"
+ " template <typename T2> struct Y {\n"
+ " void f() {\n"
+ " T2 y;\n"
+ " y.x();\n"
+ " }\n"
+ " };\n"
+ "};\n"
+ "struct A { void x(); };\n"
+ "int main() {\n"
+ " (new X<A>::Y<A>())->f();\n"
+ "}"));
+}
/* FIXME: According to Richard Smith this is a bug in the AST.
TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
@@ -236,4 +252,3 @@ TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
*/
} // end namespace clang
-