From: Manuel Klimek Date: Mon, 4 Feb 2013 10:59:20 +0000 (+0000) Subject: Implements the convenience matcher findAll. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=abf4371339862cb739ae7dc8595e12cba7b7d6c3;p=platform%2Fupstream%2Fllvm.git Implements the convenience matcher findAll. We found that findAll has been implemented incorrectly multiple times by various people using the matchers. To prevent further wasted development effort, it makes sense to add it as convenience matcher implemented as eachOf(m, forEachDescendant(m)). This patch also updates the docs with the new matchers. llvm-svn: 174320 --- diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 163743c..672c12d 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1675,6 +1675,40 @@ match expressions.

Return typeNameParameters +Matcher<*>eachOfMatcher<*> P1, Matcher<*> P2 +
Matches if any of the given matchers matches.
+
+Unlike anyOf, eachOf will generate a match result for each
+matching submatcher.
+
+For example, in:
+  class A { int a; int b; };
+The matcher:
+  recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+                    has(fieldDecl(hasName("b")).bind("v"))))
+will generate two results binding "v", the first of which binds
+the field declaration of a, the second the field declaration of
+b.
+
+Usable as: Any Matcher
+
+ + +Matcher<*>findAllMatcher<T> Matcher +
Matches if the node or any descendant matches.
+
+Generates results for each match.
+
+For example, in:
+  class A { class B {}; class C {}; };
+The matcher:
+  recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m")))
+will generate results for A, B and C.
+
+Usable as: Any Matcher
+
+ + Matcher<*>forEachMatcher<ChildT> ChildMatcher
Matches AST nodes that have child AST nodes that match the
 provided matcher.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index bd26d09..933ef6b 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1450,6 +1450,29 @@ forEachDescendant(
     DescendantT>(DescendantMatcher);
 }
 
+/// \brief Matches if the node or any descendant matches.
+///
+/// Generates results for each match.
+///
+/// For example, in:
+/// \code
+///   class A { class B {}; class C {}; };
+/// \endcode
+/// The matcher:
+/// \code
+///   recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m")))
+/// \endcode
+/// will generate results for \c A, \c B and \c C.
+///
+/// Usable as: Any Matcher
+template 
+internal::PolymorphicMatcherWithParam2<
+    internal::EachOfMatcher, internal::Matcher,
+    internal::ArgumentAdaptingMatcher >
+findAll(const internal::Matcher &Matcher) {
+  return eachOf(Matcher, forEachDescendant(Matcher));
+}
+
 /// \brief Matches AST nodes that have a parent that matches the provided
 /// matcher.
 ///
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp
index dc8b15f..8668b49 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -2854,6 +2854,34 @@ TEST(ForEachDescendant, BindsCorrectNodes) {
       new VerifyIdIsBoundTo("decl", 1)));
 }
 
+TEST(FindAll, BindsNodeOnMatch) {
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class A {};",
+      recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),
+      new VerifyIdIsBoundTo("v", 1)));
+}
+
+TEST(FindAll, BindsDescendantNodeOnMatch) {
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class A { int a; int b; };",
+      recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),
+      new VerifyIdIsBoundTo("v", 2)));
+}
+
+TEST(FindAll, BindsNodeAndDescendantNodesOnOneMatch) {
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class A { int a; int b; };",
+      recordDecl(hasName("::A"),
+                 findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),
+                                    fieldDecl().bind("v"))))),
+      new VerifyIdIsBoundTo("v", 3)));
+
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class A { class B {}; class C {}; };",
+      recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),
+      new VerifyIdIsBoundTo("v", 3)));
+}
+
 TEST(EachOf, TriggersForEachMatch) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
       "class A { int a; int b; };",