From a384821bc33f8e8d6fcbf14a3048c11940f2a708 Mon Sep 17 00:00:00 2001 From: Aaron Ballman <aaron@aaronballman.com> Date: Mon, 26 Sep 2016 17:04:27 +0000 Subject: [PATCH] Complete support for the cxxCtorInitializer() AST matcher so that it can be used as a top-level matcher. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@282417 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/ASTMatchers/ASTMatchFinder.h | 3 ++ include/clang/ASTMatchers/ASTMatchers.h | 1 + lib/ASTMatchers/ASTMatchFinder.cpp | 38 +++++++++++++++++++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp | 5 +++ 4 files changed, 47 insertions(+) diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 2c9a377b52..389af1b6e2 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -158,6 +158,8 @@ public: MatchCallback *Action); void addMatcher(const TypeLocMatcher &NodeMatch, MatchCallback *Action); + void addMatcher(const CXXCtorInitializerMatcher &NodeMatch, + MatchCallback *Action); /// @} /// \brief Adds a matcher to execute when running over the AST. @@ -208,6 +210,7 @@ public: std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>> NestedNameSpecifierLoc; std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc; + std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit; /// \brief All the callbacks in one container to simplify iteration. llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks; }; diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index a45b0bebca..af4cd47d53 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -125,6 +125,7 @@ typedef internal::Matcher<QualType> TypeMatcher; typedef internal::Matcher<TypeLoc> TypeLocMatcher; typedef internal::Matcher<NestedNameSpecifier> NestedNameSpecifierMatcher; typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher; +typedef internal::Matcher<CXXCtorInitializer> CXXCtorInitializerMatcher; /// @} /// \brief Matches any node. diff --git a/lib/ASTMatchers/ASTMatchFinder.cpp b/lib/ASTMatchers/ASTMatchFinder.cpp index 19e5743ea1..49b15ee685 100644 --- a/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/lib/ASTMatchers/ASTMatchFinder.cpp @@ -126,6 +126,8 @@ public: traverse(*Q); else if (const TypeLoc *T = DynNode.get<TypeLoc>()) traverse(*T); + else if (const auto *C = DynNode.get<CXXCtorInitializer>()) + traverse(*C); // FIXME: Add other base types after adding tests. // It's OK to always overwrite the bound nodes, as if there was @@ -194,6 +196,12 @@ public: return false; return traverse(NNS); } + bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit) { + if (!CtorInit) + return true; + ScopedIncrement ScopedDepth(&CurrentDepth); + return traverse(*CtorInit); + } bool shouldVisitTemplateInstantiations() const { return true; } bool shouldVisitImplicitCode() const { return true; } @@ -235,6 +243,10 @@ private: bool baseTraverse(NestedNameSpecifierLoc NNS) { return VisitorBase::TraverseNestedNameSpecifierLoc(NNS); } + bool baseTraverse(const CXXCtorInitializer &CtorInit) { + return VisitorBase::TraverseConstructorInitializer( + const_cast<CXXCtorInitializer *>(&CtorInit)); + } // Sets 'Matched' to true if 'Matcher' matches 'Node' and: // 0 < CurrentDepth <= MaxDepth. @@ -371,6 +383,7 @@ public: bool TraverseTypeLoc(TypeLoc TypeNode); bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); + bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit); // Matches children or descendants of 'Node' with 'BaseMatcher'. bool memoizedMatchesRecursively(const ast_type_traits::DynTypedNode &Node, @@ -472,6 +485,8 @@ public: match(*N); } else if (auto *N = Node.get<TypeLoc>()) { match(*N); + } else if (auto *N = Node.get<CXXCtorInitializer>()) { + match(*N); } } @@ -593,6 +608,9 @@ private: void matchDispatch(const NestedNameSpecifierLoc *Node) { matchWithoutFilter(*Node, Matchers->NestedNameSpecifierLoc); } + void matchDispatch(const CXXCtorInitializer *Node) { + matchWithoutFilter(*Node, Matchers->CtorInit); + } void matchDispatch(const void *) { /* Do nothing. */ } /// @} @@ -864,6 +882,17 @@ bool MatchASTVisitor::TraverseNestedNameSpecifierLoc( RecursiveASTVisitor<MatchASTVisitor>::TraverseNestedNameSpecifierLoc(NNS); } +bool MatchASTVisitor::TraverseConstructorInitializer( + CXXCtorInitializer *CtorInit) { + if (!CtorInit) + return true; + + match(*CtorInit); + + return RecursiveASTVisitor<MatchASTVisitor>::TraverseConstructorInitializer( + CtorInit); +} + class MatchASTConsumer : public ASTConsumer { public: MatchASTConsumer(MatchFinder *Finder, @@ -934,6 +963,12 @@ void MatchFinder::addMatcher(const TypeLocMatcher &NodeMatch, Matchers.AllCallbacks.insert(Action); } +void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch, + MatchCallback *Action) { + Matchers.CtorInit.emplace_back(NodeMatch, Action); + Matchers.AllCallbacks.insert(Action); +} + bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action) { if (NodeMatch.canConvertTo<Decl>()) { @@ -954,6 +989,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, } else if (NodeMatch.canConvertTo<TypeLoc>()) { addMatcher(NodeMatch.convertTo<TypeLoc>(), Action); return true; + } else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) { + addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action); + return true; } return false; } diff --git a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 6c8a5e000f..a981e10f19 100644 --- a/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -528,6 +528,11 @@ TEST(Matcher, ConstructorCall) { EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor)); } +TEST(Match, ConstructorInitializers) { + EXPECT_TRUE(matches("class C { int i; public: C(int ii) : i(ii) {} };", + cxxCtorInitializer(forField(hasName("i"))))); +} + TEST(Matcher, ThisExpr) { EXPECT_TRUE( matches("struct X { int a; int f () { return a; } };", cxxThisExpr())); -- 2.40.0