diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-05 16:18:26 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-05 16:18:26 +0000 |
| commit | b34dc87826de1ebf7fc2cc01e9484835710fe86b (patch) | |
| tree | 78d45eb8f84c54efac2e39ae585465c64da26426 | |
| parent | 5bbf8290a790497a571f4717b1f18d1088fd61c3 (diff) | |
| download | bcm5719-llvm-b34dc87826de1ebf7fc2cc01e9484835710fe86b.tar.gz bcm5719-llvm-b34dc87826de1ebf7fc2cc01e9484835710fe86b.zip | |
RecursiveASTVisitor: add ability to visit implicit declarations. Patch by
James Dennett!
llvm-svn: 158002
| -rw-r--r-- | clang/include/clang/AST/RecursiveASTVisitor.h | 15 | ||||
| -rw-r--r-- | clang/unittests/Tooling/RecursiveASTVisitorTest.cpp | 27 |
2 files changed, 37 insertions, 5 deletions
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 72f24a09a58..b1db07af17d 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -148,6 +148,10 @@ public: /// TypeLocs. bool shouldWalkTypesOfTypeLocs() const { return true; } + /// \brief Return whether this visitor should recurse into implicit + /// declarations, e.g., implicit constructors and destructors. + bool shouldVisitImplicitDeclarations() const { return false; } + /// \brief Return whether \param S should be traversed using data recursion /// to avoid a stack overflow with extreme cases. bool shouldUseDataRecursionFor(Stmt *S) const { @@ -601,10 +605,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { if (!D) return true; - // As a syntax visitor, we want to ignore declarations for - // implicitly-defined declarations (ones not typed explicitly by the - // user). - if (D->isImplicit()) + // As a syntax visitor, by default we want to ignore declarations for + // implicit declarations (ones not typed explicitly by the user). + if (!getDerived().shouldVisitImplicitDeclarations() && D->isImplicit()) return true; switch (D->getKind()) { @@ -1697,7 +1700,9 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { // FunctionNoProtoType or FunctionProtoType, or a typedef. This // also covers the return type and the function parameters, // including exception specifications. - TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + if (clang::TypeSourceInfo *TSI = D->getTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + } if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { // Constructor initializers. diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp index 9ad825f8cf2..52b3987bc84 100644 --- a/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -448,4 +448,31 @@ TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) { "template<template <typename> class T> class Y {};\n")); } +// A visitor that visits implicit declarations and matches constructors. +class ImplicitCtorVisitor + : public ExpectedLocationVisitor<ImplicitCtorVisitor> { +public: + bool shouldVisitImplicitDeclarations() const { return true; } + + bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) { + if (Ctor->isImplicit()) { // Was not written in source code + if (const CXXRecordDecl* Class = Ctor->getParent()) { + Match(Class->getName(), Ctor->getLocation()); + } + } + return true; + } +}; + +TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) { + ImplicitCtorVisitor Visitor; + Visitor.ExpectMatch("Simple", 2, 8); + // Note: Clang lazily instantiates implicit declarations, so we need + // to use them in order to force them to appear in the AST. + EXPECT_TRUE(Visitor.runOver( + "struct WithCtor { WithCtor(); }; \n" + "struct Simple { Simple(); WithCtor w; }; \n" + "int main() { Simple s; Simple t(s); }\n")); +} + } // end namespace clang |

