return getMemoizationData() < Other.getMemoizationData();
}
bool operator==(const DynTypedNode &Other) const {
- // Nodes with different types cannot be equal.
- if (!NodeKind.isSame(Other.NodeKind))
+ if (!NodeKind.isBaseOf(Other.NodeKind) &&
+ !Other.NodeKind.isBaseOf(NodeKind))
return false;
// FIXME: Implement for other types.
}
TEST(EqualsBoundNodeMatcher, UsingForEachDescendant) {
-
EXPECT_TRUE(matchAndVerifyResultTrue(
"int f() {"
" if (1) {"
new VerifyIdIsBoundTo<VarDecl>("d", 5)));
}
+TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "struct StringRef { int size() const; const char* data() const; };"
+ "void f(StringRef v) {"
+ " v.data();"
+ "}",
+ memberCallExpr(
+ callee(methodDecl(hasName("data"))),
+ on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
+ .bind("var")))),
+ unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
+ callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
+ on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
+ .bind("data"),
+ new VerifyIdIsBoundTo<Expr>("data", 1)));
+
+ EXPECT_FALSE(matches(
+ "struct StringRef { int size() const; const char* data() const; };"
+ "void f(StringRef v) {"
+ " v.data();"
+ " v.size();"
+ "}",
+ memberCallExpr(
+ callee(methodDecl(hasName("data"))),
+ on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
+ .bind("var")))),
+ unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
+ callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
+ on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
+ .bind("data")));
+}
+
} // end namespace ast_matchers
} // end namespace clang