From 5482dc3a88fce51307b5e1e19bdf72dea1562040 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 24 Apr 2012 20:39:49 +0000 Subject: [PATCH] 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 --- include/clang/AST/RecursiveASTVisitor.h | 6 +++-- unittests/Tooling/RecursiveASTVisitorTest.cpp | 23 +++++++++++++++---- 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()); }")); } -/* 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::f(); }")); } -*/ + +TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) { + CXXMemberCallVisitor Visitor; + Visitor.ExpectMatch("A::x", 5, 7); + EXPECT_TRUE(Visitor.runOver( + "template struct X {\n" + " template 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::Y())->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 - -- 2.40.0