]> granicus.if.org Git - clang/commitdiff
Make equalsNode work with pointers to subtypes.
authorManuel Klimek <klimek@google.com>
Tue, 27 May 2014 12:31:10 +0000 (12:31 +0000)
committerManuel Klimek <klimek@google.com>
Tue, 27 May 2014 12:31:10 +0000 (12:31 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209652 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibASTMatchersReference.html
include/clang/ASTMatchers/ASTMatchers.h
include/clang/ASTMatchers/ASTMatchersInternal.h
unittests/ASTMatchers/ASTMatchersTest.cpp

index 90351e0602cdf286f01f9ee76639ad56b3d6260f..c308635e31e54195150c4cbdd29698c5c0399af6 100644 (file)
@@ -1601,7 +1601,7 @@ and reference to that variable declaration within a compound statement.
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('equalsNode0')"><a name="equalsNode0Anchor">equalsNode</a></td><td>Decl* Other</td></tr>
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('equalsNode0')"><a name="equalsNode0Anchor">equalsNode</a></td><td>Decl *Node</td></tr>
 <tr><td colspan="4" class="doc" id="equalsNode0"><pre>Matches if a node equals another node.
 
 Decl has pointer identity in the AST.
@@ -1900,7 +1900,7 @@ and reference to that variable declaration within a compound statement.
 </pre></td></tr>
 
 
-<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('equalsNode1')"><a name="equalsNode1Anchor">equalsNode</a></td><td>Stmt* Other</td></tr>
+<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('equalsNode1')"><a name="equalsNode1Anchor">equalsNode</a></td><td>Stmt *Node</td></tr>
 <tr><td colspan="4" class="doc" id="equalsNode1"><pre>Matches if a node equals another node.
 
 Stmt has pointer identity in the AST.
index 3636def66d2f8a634eb25b3d34b447d85a4040e6..3d677676889dab5349e4bb555dcbfface0608e10 100644 (file)
@@ -3504,15 +3504,15 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace,
 /// \brief Matches if a node equals another node.
 ///
 /// \c Decl has pointer identity in the AST.
-AST_MATCHER_P_OVERLOAD(Decl, equalsNode, Decl*, Other, 0) {
-  return &Node == Other;
+inline internal::Matcher<Decl> equalsNode(const Decl *Node) {
+  return makeMatcher(new internal::EqualsNodeMatcher<Decl>(Node));
 }
 /// \brief Matches if a node equals another node.
 ///
 /// \c Stmt has pointer identity in the AST.
 ///
-AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) {
-  return &Node == Other;
+inline internal::Matcher<Stmt> equalsNode(const Stmt *Node) {
+  return makeMatcher(new internal::EqualsNodeMatcher<Stmt>(Node));
 }
 
 /// @}
index ed20dee08897d33cd95d9b3be3555a9a1088908c..c0dd7b876e9036b11425815a3c6ea52fe6a1474b 100644 (file)
@@ -1387,6 +1387,20 @@ private:
   const ValueT ExpectedValue;
 };
 
+template <typename T>
+class EqualsNodeMatcher : public SingleNodeMatcherInterface<T> {
+public:
+  explicit EqualsNodeMatcher(const T *ExpectedNode)
+      : ExpectedNode(ExpectedNode) {}
+
+  bool matchesNode(const T &Node) const override {
+    return &Node == ExpectedNode;
+  }
+
+private:
+  const T *ExpectedNode;
+};
+
 /// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
 /// variadic functor that takes a number of Matcher<TargetT> and returns a
 /// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
index 9d9b2a15b799f5a8f4ae543cb4771dd48d54b6ea..691719c04e4fe7c9993af764a9170d6dfe8e9d66 100644 (file)
@@ -4158,24 +4158,32 @@ public:
   }
 
   bool verify(const BoundNodes &Nodes, ASTContext &Context, const Stmt *Node) {
+    // Use the original typed pointer to verify we can pass pointers to subtypes
+    // to equalsNode.
+    const T *TypedNode = cast<T>(Node);
     return selectFirst<const T>(
-        "", match(stmt(hasParent(stmt(has(stmt(equalsNode(Node)))).bind(""))),
-                  *Node, Context)) != NULL;
+               "", match(stmt(hasParent(
+                             stmt(has(stmt(equalsNode(TypedNode)))).bind(""))),
+                         *Node, Context)) != NULL;
   }
   bool verify(const BoundNodes &Nodes, ASTContext &Context, const Decl *Node) {
+    // Use the original typed pointer to verify we can pass pointers to subtypes
+    // to equalsNode.
+    const T *TypedNode = cast<T>(Node);
     return selectFirst<const T>(
-        "", match(decl(hasParent(decl(has(decl(equalsNode(Node)))).bind(""))),
-                  *Node, Context)) != NULL;
+               "", match(decl(hasParent(
+                             decl(has(decl(equalsNode(TypedNode)))).bind(""))),
+                         *Node, Context)) != NULL;
   }
 };
 
 TEST(IsEqualTo, MatchesNodesByIdentity) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
       "class X { class Y {}; };", recordDecl(hasName("::X::Y")).bind(""),
-      new VerifyAncestorHasChildIsEqual<Decl>()));
-  EXPECT_TRUE(
-      matchAndVerifyResultTrue("void f() { if(true) {} }", ifStmt().bind(""),
-                               new VerifyAncestorHasChildIsEqual<Stmt>()));
+      new VerifyAncestorHasChildIsEqual<CXXRecordDecl>()));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "void f() { if (true) if(true) {} }", ifStmt().bind(""),
+      new VerifyAncestorHasChildIsEqual<IfStmt>()));
 }
 
 class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback {