[cfe-commits] r166421 - in /cfe/trunk: include/clang/ASTMatchers/ASTMatchers.h include/clang/ASTMatchers/ASTMatchersInternal.h lib/ASTMatchers/ASTMatchFinder.cpp unittests/ASTMatchers/ASTMatchersTest.cpp

Daniel Jasper djasper at google.com
Mon Oct 22 09:26:51 PDT 2012


Author: djasper
Date: Mon Oct 22 11:26:51 2012
New Revision: 166421

URL: http://llvm.org/viewvc/llvm-project?rev=166421&view=rev
Log:
Implement hasParent()-matcher.

Modified:
    cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
    cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
    cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=166421&r1=166420&r2=166421&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Oct 22 11:26:51 2012
@@ -1402,6 +1402,24 @@
     DescendantT>(DescendantMatcher);
 }
 
+/// \brief Matches AST nodes that have a parent that matches the provided
+/// matcher.
+///
+/// Given
+/// \code
+/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } }
+/// \endcode
+/// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }".
+///
+/// Usable as: Any Matcher
+template <typename ParentT>
+internal::ArgumentAdaptingMatcher<internal::HasParentMatcher, ParentT>
+hasParent(const internal::Matcher<ParentT> &ParentMatcher) {
+  return internal::ArgumentAdaptingMatcher<
+    internal::HasParentMatcher,
+    ParentT>(ParentMatcher);
+}
+
 /// \brief Matches AST nodes that have an ancestor that matches the provided
 /// matcher.
 ///

Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h?rev=166421&r1=166420&r2=166421&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h Mon Oct 22 11:26:51 2012
@@ -460,6 +460,14 @@
     BK_All
   };
 
+  /// \brief Defines which ancestors are considered for a match.
+  enum AncestorMatchMode {
+    /// All ancestors.
+    AMM_All,
+    /// Direct parent only.
+    AMM_ParentOnly
+  };
+
   virtual ~ASTMatchFinder() {}
 
   /// \brief Returns true if the given class is directly or indirectly derived
@@ -499,12 +507,13 @@
   template <typename T>
   bool matchesAncestorOf(const T &Node,
                          const DynTypedMatcher &Matcher,
-                         BoundNodesTreeBuilder *Builder) {
+                         BoundNodesTreeBuilder *Builder,
+                         AncestorMatchMode MatchMode) {
     TOOLING_COMPILE_ASSERT((llvm::is_base_of<Decl, T>::value ||
                             llvm::is_base_of<Stmt, T>::value),
                            only_Decl_or_Stmt_allowed_for_recursive_matching);
     return matchesAncestorOf(ast_type_traits::DynTypedNode::create(Node),
-                             Matcher, Builder);
+                             Matcher, Builder, MatchMode);
   }
 
 protected:
@@ -521,7 +530,8 @@
 
   virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
                                  const DynTypedMatcher &Matcher,
-                                 BoundNodesTreeBuilder *Builder) = 0;
+                                 BoundNodesTreeBuilder *Builder,
+                                 AncestorMatchMode MatchMode) = 0;
 };
 
 /// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
@@ -864,6 +874,29 @@
   const Matcher<DescendantT> DescendantMatcher;
 };
 
+/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT
+/// for which the given inner matcher matches.
+///
+/// \c ParentT must be an AST base type.
+template <typename T, typename ParentT>
+class HasParentMatcher : public MatcherInterface<T> {
+  TOOLING_COMPILE_ASSERT(IsBaseType<ParentT>::value,
+                         has_parent_only_accepts_base_type_matcher);
+public:
+  explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
+      : ParentMatcher(ParentMatcher) {}
+
+  virtual bool matches(const T &Node,
+                       ASTMatchFinder *Finder,
+                       BoundNodesTreeBuilder *Builder) const {
+    return Finder->matchesAncestorOf(
+        Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly);
+  }
+
+ private:
+  const Matcher<ParentT> ParentMatcher;
+};
+
 /// \brief Matches nodes of type \c T that have at least one ancestor node of
 /// type \c AncestorT for which the given inner matcher matches.
 ///
@@ -880,7 +913,7 @@
                        ASTMatchFinder *Finder,
                        BoundNodesTreeBuilder *Builder) const {
     return Finder->matchesAncestorOf(
-        Node, AncestorMatcher, Builder);
+        Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All);
   }
 
  private:

Modified: cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp?rev=166421&r1=166420&r2=166421&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/ASTMatchFinder.cpp Mon Oct 22 11:26:51 2012
@@ -352,7 +352,7 @@
                                   const Matcher<NamedDecl> &Base,
                                   BoundNodesTreeBuilder *Builder);
 
-  // Implements ASTMatchFinder::MatchesChildOf.
+  // Implements ASTMatchFinder::matchesChildOf.
   virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node,
                               const DynTypedMatcher &Matcher,
                               BoundNodesTreeBuilder *Builder,
@@ -361,7 +361,7 @@
     return matchesRecursively(Node, Matcher, Builder, 1, Traversal,
                               Bind);
   }
-  // Implements ASTMatchFinder::MatchesDescendantOf.
+  // Implements ASTMatchFinder::matchesDescendantOf.
   virtual bool matchesDescendantOf(const ast_type_traits::DynTypedNode &Node,
                                    const DynTypedMatcher &Matcher,
                                    BoundNodesTreeBuilder *Builder,
@@ -372,7 +372,8 @@
   // Implements ASTMatchFinder::matchesAncestorOf.
   virtual bool matchesAncestorOf(const ast_type_traits::DynTypedNode &Node,
                                  const DynTypedMatcher &Matcher,
-                                 BoundNodesTreeBuilder *Builder) {
+                                 BoundNodesTreeBuilder *Builder,
+                                 AncestorMatchMode MatchMode) {
     if (!Parents) {
       // We always need to run over the whole translation unit, as
       // \c hasAncestor can escape any subtree.
@@ -395,6 +396,8 @@
       Ancestor = I->second;
       if (Matcher.matches(Ancestor, this, Builder))
         return true;
+      if (MatchMode == ASTMatchFinder::AMM_ParentOnly)
+        return false;
     }
     return false;
   }

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=166421&r1=166420&r2=166421&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Mon Oct 22 11:26:51 2012
@@ -2884,6 +2884,18 @@
               hasAncestor(recordDecl(hasName("A")))))))));
 }
 
+TEST(HasParent, MatchesOnlyParent) {
+  EXPECT_TRUE(matches(
+      "void f() { if (true) { int x = 42; } }",
+      compoundStmt(hasParent(ifStmt()))));
+  EXPECT_TRUE(notMatches(
+      "void f() { for (;;) { int x = 42; } }",
+      compoundStmt(hasParent(ifStmt()))));
+  EXPECT_TRUE(notMatches(
+      "void f() { if (true) for (;;) { int x = 42; } }",
+      compoundStmt(hasParent(ifStmt()))));
+}
+
 TEST(TypeMatching, MatchesTypes) {
   EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
 }





More information about the cfe-commits mailing list