Author: krobelus Date: Wed Sep 6 06:11:13 2017 New Revision: 312631 URL: http://llvm.org/viewvc/llvm-project?rev=312631&view=rev Log: [AST] Traverse templates in LexicallyOrderedRecursiveASTVisitor
Summary: We need to specialize this because RecursiveASTVisitor visits template template parameters after the templated declaration, unlike the order in which they appear in the source code. Reviewers: arphaman Reviewed By: arphaman Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D36998 Modified: cfe/trunk/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp Modified: cfe/trunk/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h?rev=312631&r1=312630&r2=312631&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/LexicallyOrderedRecursiveASTVisitor.h Wed Sep 6 06:11:13 2017 @@ -111,6 +111,8 @@ public: return true; } + bool shouldTraverseTemplateArgumentsBeforeDecl() const { return true; } + private: bool TraverseAdditionalLexicallyNestedDeclarations() { // FIXME: Ideally the gathered declarations and the declarations in the Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=312631&r1=312630&r2=312631&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Sep 6 06:11:13 2017 @@ -535,6 +535,7 @@ private: bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); bool PostVisitStmt(Stmt *S); + bool shouldTraverseTemplateArgumentsBeforeDecl() const { return false; } }; template <typename Derived> @@ -1688,8 +1689,13 @@ bool RecursiveASTVisitor<Derived>::Trave // template declarations. #define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ - TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ + if (getDerived().shouldTraverseTemplateArgumentsBeforeDecl()) { \ + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ + TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ + } else { \ + TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ + } \ \ /* By default, we do not traverse the instantiations of \ class templates since they do not appear in the user code. The \ Modified: cfe/trunk/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp?rev=312631&r1=312630&r2=312631&view=diff ============================================================================== --- cfe/trunk/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp (original) +++ cfe/trunk/unittests/Tooling/LexicallyOrderedRecursiveASTVisitorTest.cpp Wed Sep 6 06:11:13 2017 @@ -21,8 +21,9 @@ class LexicallyOrderedDeclVisitor : public LexicallyOrderedRecursiveASTVisitor<LexicallyOrderedDeclVisitor> { public: LexicallyOrderedDeclVisitor(DummyMatchVisitor &Matcher, - const SourceManager &SM) - : LexicallyOrderedRecursiveASTVisitor(SM), Matcher(Matcher) {} + const SourceManager &SM, bool EmitIndices) + : LexicallyOrderedRecursiveASTVisitor(SM), Matcher(Matcher), + EmitIndices(EmitIndices) {} bool TraverseDecl(Decl *D) { TraversalStack.push_back(D); @@ -35,15 +36,20 @@ public: private: DummyMatchVisitor &Matcher; + bool EmitIndices; + unsigned Index = 0; llvm::SmallVector<Decl *, 8> TraversalStack; }; class DummyMatchVisitor : public ExpectedLocationVisitor<DummyMatchVisitor> { + bool EmitIndices; + public: + DummyMatchVisitor(bool EmitIndices = false) : EmitIndices(EmitIndices) {} bool VisitTranslationUnitDecl(TranslationUnitDecl *TU) { const ASTContext &Context = TU->getASTContext(); const SourceManager &SM = Context.getSourceManager(); - LexicallyOrderedDeclVisitor SubVisitor(*this, SM); + LexicallyOrderedDeclVisitor SubVisitor(*this, SM, EmitIndices); SubVisitor.TraverseDecl(TU); return false; } @@ -64,9 +70,11 @@ bool LexicallyOrderedDeclVisitor::VisitN OS << ND->getNameAsString(); else OS << "???"; - if (isa<DeclContext>(D)) + if (isa<DeclContext>(D) or isa<TemplateDecl>(D)) OS << "/"; } + if (EmitIndices) + OS << "@" << Index++; Matcher.match(OS.str(), D); return true; } @@ -138,4 +146,18 @@ MACRO_F(2) EXPECT_TRUE(Visitor.runOver(Source, DummyMatchVisitor::Lang_OBJC)); } +TEST(LexicallyOrderedRecursiveASTVisitor, VisitTemplateDecl) { + StringRef Source = R"( +template <class T> T f(); +template <class U, class = void> class Class {}; +)"; + DummyMatchVisitor Visitor(/*EmitIndices=*/true); + Visitor.ExpectMatch("/f/T@1", 2, 11); + Visitor.ExpectMatch("/f/f/@2", 2, 20); + Visitor.ExpectMatch("/Class/U@4", 3, 11); + Visitor.ExpectMatch("/Class/@5", 3, 20); + Visitor.ExpectMatch("/Class/Class/@6", 3, 34); + EXPECT_TRUE(Visitor.runOver(Source)); +} + } // end anonymous namespace _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits