From 06963013d1972f1f7a58875bb40976b60522700b Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Fri, 19 Jul 2013 11:50:54 +0000 Subject: [PATCH] Adds ctorInitializer and forEachConstructorInitializer matchers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186668 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/ASTMatchers/ASTMatchers.h | 36 +++++++++++++++++++++++ unittests/ASTMatchers/ASTMatchersTest.cpp | 11 +++++++ 2 files changed, 47 insertions(+) diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 18bfe15486..1414c4ef2f 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -241,6 +241,17 @@ const internal::VariadicDynCastAllOfMatcher< Decl, AccessSpecDecl> accessSpecDecl; +/// \brief Matches constructor initializers. +/// +/// Examples matches \c i(42). +/// \code +/// class C { +/// C() : i(42) {} +/// int i; +/// }; +/// \endcode +const internal::VariadicAllOfMatcher ctorInitializer; + /// \brief Matches public C++ declarations. /// /// Given @@ -3494,6 +3505,31 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher, return Matched; } +/// \brief Matches each constructor initializer in a constructor definition. +/// +/// Given +/// \code +/// class A { A() : i(42), j(42) {} int i; int j; }; +/// \endcode +/// constructorDecl(forEachConstructorInitializer(forField(decl().bind("x")))) +/// will trigger two matches, binding for 'i' and 'j' respectively. +AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer, + internal::Matcher, InnerMatcher) { + BoundNodesTreeBuilder Result; + bool Matched = false; + for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(), + E = Node.init_end(); + I != E; ++I) { + BoundNodesTreeBuilder InitBuilder(*Builder); + if (InnerMatcher.matches(**I, Finder, &InitBuilder)) { + Matched = true; + Result.addMatch(InitBuilder); + } + } + *Builder = Result; + return Matched; +} + /// \brief If the given case statement does not use the GNU case range /// extension, matches the constant given in the statement. /// diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 8df0274504..b6d21e6997 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -2967,6 +2967,12 @@ TEST(SwitchCase, MatchesEachCase) { new VerifyIdIsBoundTo("x", 3))); } +TEST(ForEachConstructorInitializer, MatchesInitializers) { + EXPECT_TRUE(matches( + "struct X { X() : i(42), j(42) {} int i, j; };", + constructorDecl(forEachConstructorInitializer(ctorInitializer())))); +} + TEST(ExceptionHandling, SimpleCases) { EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", catchStmt())); EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", tryStmt())); @@ -3157,6 +3163,11 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) { "class A {};", recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))), new VerifyIdIsBoundTo("x", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + "class A { A() : s(), i(42) {} const char *s; int i; };", + constructorDecl(hasName("::A::A"), decl().bind("x"), + forEachConstructorInitializer(forField(hasName("i")))), + new VerifyIdIsBoundTo("x", 1))); } TEST(ForEachDescendant, BindsCorrectNodes) { -- 2.40.0