Skip to content

Commit

Permalink
Make equalsNode work with pointers to subtypes.
Browse files Browse the repository at this point in the history
llvm-svn: 209652
  • Loading branch information
r4nt committed May 27, 2014
1 parent 1bed9af commit a2c2a4f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 14 deletions.
4 changes: 2 additions & 2 deletions clang/docs/LibASTMatchersReference.html
Original file line number Diff line number Diff line change
Expand Up @@ -1601,7 +1601,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</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.
Expand Down Expand Up @@ -1900,7 +1900,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</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.
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/// @}
Expand Down
14 changes: 14 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchersInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,20 @@ class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
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
Expand Down
24 changes: 16 additions & 8 deletions clang/unittests/ASTMatchers/ASTMatchersTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4158,24 +4158,32 @@ class VerifyAncestorHasChildIsEqual : public BoundNodesCallback {
}

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 {
Expand Down

0 comments on commit a2c2a4f

Please sign in to comment.