summaryrefslogtreecommitdiffstats
path: root/unittests/ASTMatchers/ASTMatchersTest.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
committerdim <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
commit056abd2059c65a3e908193aeae16fad98017437c (patch)
tree2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /unittests/ASTMatchers/ASTMatchersTest.cpp
parentcc73504950eb7b5dff2dded9bedd67bc36d64641 (diff)
downloadFreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip
FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'unittests/ASTMatchers/ASTMatchersTest.cpp')
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp1859
1 files changed, 1346 insertions, 513 deletions
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index adf0e94..e15940a 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -19,21 +19,21 @@ namespace ast_matchers {
#if GTEST_HAS_DEATH_TEST
TEST(HasNameDeathTest, DiesOnEmptyName) {
ASSERT_DEBUG_DEATH({
- DeclarationMatcher HasEmptyName = record(hasName(""));
+ DeclarationMatcher HasEmptyName = recordDecl(hasName(""));
EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
}, "");
}
TEST(HasNameDeathTest, DiesOnEmptyPattern) {
ASSERT_DEBUG_DEATH({
- DeclarationMatcher HasEmptyName = record(matchesName(""));
+ DeclarationMatcher HasEmptyName = recordDecl(matchesName(""));
EXPECT_TRUE(notMatches("class X {};", HasEmptyName));
}, "");
}
TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
ASSERT_DEBUG_DEATH({
- DeclarationMatcher IsDerivedFromEmpty = record(isDerivedFrom(""));
+ DeclarationMatcher IsDerivedFromEmpty = recordDecl(isDerivedFrom(""));
EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
}, "");
}
@@ -46,7 +46,7 @@ TEST(Decl, MatchesDeclarations) {
}
TEST(NameableDeclaration, MatchesVariousDecls) {
- DeclarationMatcher NamedX = nameableDeclaration(hasName("X"));
+ DeclarationMatcher NamedX = namedDecl(hasName("X"));
EXPECT_TRUE(matches("typedef int X;", NamedX));
EXPECT_TRUE(matches("int X;", NamedX));
EXPECT_TRUE(matches("class foo { virtual void X(); };", NamedX));
@@ -59,7 +59,7 @@ TEST(NameableDeclaration, MatchesVariousDecls) {
}
TEST(NameableDeclaration, REMatchesVariousDecls) {
- DeclarationMatcher NamedX = nameableDeclaration(matchesName("::X"));
+ DeclarationMatcher NamedX = namedDecl(matchesName("::X"));
EXPECT_TRUE(matches("typedef int Xa;", NamedX));
EXPECT_TRUE(matches("int Xb;", NamedX));
EXPECT_TRUE(matches("class foo { virtual void Xc(); };", NamedX));
@@ -70,11 +70,11 @@ TEST(NameableDeclaration, REMatchesVariousDecls) {
EXPECT_TRUE(notMatches("#define Xkl 1", NamedX));
- DeclarationMatcher StartsWithNo = nameableDeclaration(matchesName("::no"));
+ DeclarationMatcher StartsWithNo = namedDecl(matchesName("::no"));
EXPECT_TRUE(matches("int no_foo;", StartsWithNo));
EXPECT_TRUE(matches("class foo { virtual void nobody(); };", StartsWithNo));
- DeclarationMatcher Abc = nameableDeclaration(matchesName("a.*b.*c"));
+ DeclarationMatcher Abc = namedDecl(matchesName("a.*b.*c"));
EXPECT_TRUE(matches("int abc;", Abc));
EXPECT_TRUE(matches("int aFOObBARc;", Abc));
EXPECT_TRUE(notMatches("int cab;", Abc));
@@ -82,7 +82,7 @@ TEST(NameableDeclaration, REMatchesVariousDecls) {
}
TEST(DeclarationMatcher, MatchClass) {
- DeclarationMatcher ClassMatcher(record());
+ DeclarationMatcher ClassMatcher(recordDecl());
#if !defined(_MSC_VER)
EXPECT_FALSE(matches("", ClassMatcher));
#else
@@ -90,7 +90,7 @@ TEST(DeclarationMatcher, MatchClass) {
EXPECT_TRUE(matches("", ClassMatcher));
#endif
- DeclarationMatcher ClassX = record(record(hasName("X")));
+ DeclarationMatcher ClassX = recordDecl(recordDecl(hasName("X")));
EXPECT_TRUE(matches("class X;", ClassX));
EXPECT_TRUE(matches("class X {};", ClassX));
EXPECT_TRUE(matches("template<class T> class X {};", ClassX));
@@ -98,17 +98,24 @@ TEST(DeclarationMatcher, MatchClass) {
}
TEST(DeclarationMatcher, ClassIsDerived) {
- DeclarationMatcher IsDerivedFromX = record(isDerivedFrom("X"));
+ DeclarationMatcher IsDerivedFromX = recordDecl(isDerivedFrom("X"));
EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX));
- EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX));
- EXPECT_TRUE(matches("class X {};", IsDerivedFromX));
- EXPECT_TRUE(matches("class X;", IsDerivedFromX));
+ EXPECT_TRUE(notMatches("class X {};", IsDerivedFromX));
+ EXPECT_TRUE(notMatches("class X;", IsDerivedFromX));
EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
EXPECT_TRUE(notMatches("", IsDerivedFromX));
+ DeclarationMatcher IsAX = recordDecl(isSameOrDerivedFrom("X"));
+
+ EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsAX));
+ EXPECT_TRUE(matches("class X {};", IsAX));
+ EXPECT_TRUE(matches("class X;", IsAX));
+ EXPECT_TRUE(notMatches("class Y;", IsAX));
+ EXPECT_TRUE(notMatches("", IsAX));
+
DeclarationMatcher ZIsDerivedFromX =
- record(hasName("Z"), isDerivedFrom("X"));
+ recordDecl(hasName("Z"), isDerivedFrom("X"));
EXPECT_TRUE(
matches("class X {}; class Y : public X {}; class Z : public Y {};",
ZIsDerivedFromX));
@@ -239,19 +246,17 @@ TEST(DeclarationMatcher, ClassIsDerived) {
"void f() { Z<float> z_float; Z<double> z_double; Z<char> z_char; }";
EXPECT_TRUE(matches(
RecursiveTemplateOneParameter,
- variable(hasName("z_float"),
- hasInitializer(hasType(record(isDerivedFrom("Base1")))))));
+ varDecl(hasName("z_float"),
+ hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
EXPECT_TRUE(notMatches(
RecursiveTemplateOneParameter,
- variable(
- hasName("z_float"),
- hasInitializer(hasType(record(isDerivedFrom("Base2")))))));
+ varDecl(hasName("z_float"),
+ hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
RecursiveTemplateOneParameter,
- variable(
- hasName("z_char"),
- hasInitializer(hasType(record(isDerivedFrom("Base1"),
- isDerivedFrom("Base2")))))));
+ varDecl(hasName("z_char"),
+ hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
+ isDerivedFrom("Base2")))))));
const char *RecursiveTemplateTwoParameters =
"class Base1 {}; class Base2 {};"
@@ -266,47 +271,81 @@ TEST(DeclarationMatcher, ClassIsDerived) {
" Z<char, void> z_char; }";
EXPECT_TRUE(matches(
RecursiveTemplateTwoParameters,
- variable(
- hasName("z_float"),
- hasInitializer(hasType(record(isDerivedFrom("Base1")))))));
+ varDecl(hasName("z_float"),
+ hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
EXPECT_TRUE(notMatches(
RecursiveTemplateTwoParameters,
- variable(
- hasName("z_float"),
- hasInitializer(hasType(record(isDerivedFrom("Base2")))))));
+ varDecl(hasName("z_float"),
+ hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
RecursiveTemplateTwoParameters,
- variable(
- hasName("z_char"),
- hasInitializer(hasType(record(isDerivedFrom("Base1"),
- isDerivedFrom("Base2")))))));
+ varDecl(hasName("z_char"),
+ hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
+ isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
"namespace ns { class X {}; class Y : public X {}; }",
- record(isDerivedFrom("::ns::X"))));
+ recordDecl(isDerivedFrom("::ns::X"))));
EXPECT_TRUE(notMatches(
"class X {}; class Y : public X {};",
- record(isDerivedFrom("::ns::X"))));
+ recordDecl(isDerivedFrom("::ns::X"))));
EXPECT_TRUE(matches(
"class X {}; class Y : public X {};",
- record(isDerivedFrom(record(hasName("X")).bind("test")))));
+ recordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
+}
+
+TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
+ EXPECT_TRUE(matches(
+ "template <typename T> struct A {"
+ " template <typename T2> struct F {};"
+ "};"
+ "template <typename T> struct B : A<T>::template F<T> {};"
+ "B<int> b;",
+ recordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
+}
+
+TEST(ClassTemplate, DoesNotMatchClass) {
+ DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));
+ EXPECT_TRUE(notMatches("class X;", ClassX));
+ EXPECT_TRUE(notMatches("class X {};", ClassX));
+}
+
+TEST(ClassTemplate, MatchesClassTemplate) {
+ DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));
+ EXPECT_TRUE(matches("template<typename T> class X {};", ClassX));
+ EXPECT_TRUE(matches("class Z { template<class T> class X {}; };", ClassX));
+}
+
+TEST(ClassTemplate, DoesNotMatchClassTemplateExplicitSpecialization) {
+ EXPECT_TRUE(notMatches("template<typename T> class X { };"
+ "template<> class X<int> { int a; };",
+ classTemplateDecl(hasName("X"),
+ hasDescendant(fieldDecl(hasName("a"))))));
+}
+
+TEST(ClassTemplate, DoesNotMatchClassTemplatePartialSpecialization) {
+ EXPECT_TRUE(notMatches("template<typename T, typename U> class X { };"
+ "template<typename T> class X<T, int> { int a; };",
+ classTemplateDecl(hasName("X"),
+ hasDescendant(fieldDecl(hasName("a"))))));
}
TEST(AllOf, AllOverloadsWork) {
const char Program[] =
"struct T { }; int f(int, T*); void g(int x) { T t; f(x, &t); }";
EXPECT_TRUE(matches(Program,
- call(allOf(callee(function(hasName("f"))),
- hasArgument(0, declarationReference(to(variable())))))));
+ callExpr(allOf(callee(functionDecl(hasName("f"))),
+ hasArgument(0, declRefExpr(to(varDecl())))))));
EXPECT_TRUE(matches(Program,
- call(allOf(callee(function(hasName("f"))),
- hasArgument(0, declarationReference(to(variable()))),
- hasArgument(1, hasType(pointsTo(record(hasName("T")))))))));
+ callExpr(allOf(callee(functionDecl(hasName("f"))),
+ hasArgument(0, declRefExpr(to(varDecl()))),
+ hasArgument(1, hasType(pointsTo(
+ recordDecl(hasName("T")))))))));
}
TEST(DeclarationMatcher, MatchAnyOf) {
DeclarationMatcher YOrZDerivedFromX =
- record(anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
+ recordDecl(anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
EXPECT_TRUE(
matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
@@ -315,13 +354,13 @@ TEST(DeclarationMatcher, MatchAnyOf) {
EXPECT_TRUE(notMatches("class Z {};", YOrZDerivedFromX));
DeclarationMatcher XOrYOrZOrU =
- record(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U")));
+ recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U")));
EXPECT_TRUE(matches("class X {};", XOrYOrZOrU));
EXPECT_TRUE(notMatches("class V {};", XOrYOrZOrU));
DeclarationMatcher XOrYOrZOrUOrV =
- record(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U"),
- hasName("V")));
+ recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U"),
+ hasName("V")));
EXPECT_TRUE(matches("class X {};", XOrYOrZOrUOrV));
EXPECT_TRUE(matches("class Y {};", XOrYOrZOrUOrV));
EXPECT_TRUE(matches("class Z {};", XOrYOrZOrUOrV));
@@ -331,13 +370,12 @@ TEST(DeclarationMatcher, MatchAnyOf) {
}
TEST(DeclarationMatcher, MatchHas) {
- DeclarationMatcher HasClassX = record(has(record(hasName("X"))));
-
+ DeclarationMatcher HasClassX = recordDecl(has(recordDecl(hasName("X"))));
EXPECT_TRUE(matches("class Y { class X {}; };", HasClassX));
EXPECT_TRUE(matches("class X {};", HasClassX));
DeclarationMatcher YHasClassX =
- record(hasName("Y"), has(record(hasName("X"))));
+ recordDecl(hasName("Y"), has(recordDecl(hasName("X"))));
EXPECT_TRUE(matches("class Y { class X {}; };", YHasClassX));
EXPECT_TRUE(notMatches("class X {};", YHasClassX));
EXPECT_TRUE(
@@ -346,14 +384,14 @@ TEST(DeclarationMatcher, MatchHas) {
TEST(DeclarationMatcher, MatchHasRecursiveAllOf) {
DeclarationMatcher Recursive =
- record(
- has(record(
- has(record(hasName("X"))),
- has(record(hasName("Y"))),
+ recordDecl(
+ has(recordDecl(
+ has(recordDecl(hasName("X"))),
+ has(recordDecl(hasName("Y"))),
hasName("Z"))),
- has(record(
- has(record(hasName("A"))),
- has(record(hasName("B"))),
+ has(recordDecl(
+ has(recordDecl(hasName("A"))),
+ has(recordDecl(hasName("B"))),
hasName("C"))),
hasName("F"));
@@ -404,21 +442,21 @@ TEST(DeclarationMatcher, MatchHasRecursiveAllOf) {
TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
DeclarationMatcher Recursive =
- record(
+ recordDecl(
anyOf(
- has(record(
+ has(recordDecl(
anyOf(
- has(record(
+ has(recordDecl(
hasName("X"))),
- has(record(
+ has(recordDecl(
hasName("Y"))),
hasName("Z")))),
- has(record(
+ has(recordDecl(
anyOf(
hasName("C"),
- has(record(
+ has(recordDecl(
hasName("A"))),
- has(record(
+ has(recordDecl(
hasName("B")))))),
hasName("F")));
@@ -435,9 +473,8 @@ TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
TEST(DeclarationMatcher, MatchNot) {
DeclarationMatcher NotClassX =
- record(
+ recordDecl(
isDerivedFrom("Y"),
- unless(hasName("Y")),
unless(hasName("X")));
EXPECT_TRUE(notMatches("", NotClassX));
EXPECT_TRUE(notMatches("class Y {};", NotClassX));
@@ -448,11 +485,11 @@ TEST(DeclarationMatcher, MatchNot) {
NotClassX));
DeclarationMatcher ClassXHasNotClassY =
- record(
+ recordDecl(
hasName("X"),
- has(record(hasName("Z"))),
+ has(recordDecl(hasName("Z"))),
unless(
- has(record(hasName("Y")))));
+ has(recordDecl(hasName("Y")))));
EXPECT_TRUE(matches("class X { class Z {}; };", ClassXHasNotClassY));
EXPECT_TRUE(notMatches("class X { class Y {}; class Z {}; };",
ClassXHasNotClassY));
@@ -460,8 +497,8 @@ TEST(DeclarationMatcher, MatchNot) {
TEST(DeclarationMatcher, HasDescendant) {
DeclarationMatcher ZDescendantClassX =
- record(
- hasDescendant(record(hasName("X"))),
+ recordDecl(
+ hasDescendant(recordDecl(hasName("X"))),
hasName("Z"));
EXPECT_TRUE(matches("class Z { class X {}; };", ZDescendantClassX));
EXPECT_TRUE(
@@ -475,8 +512,8 @@ TEST(DeclarationMatcher, HasDescendant) {
EXPECT_TRUE(notMatches("class Z {};", ZDescendantClassX));
DeclarationMatcher ZDescendantClassXHasClassY =
- record(
- hasDescendant(record(has(record(hasName("Y"))),
+ recordDecl(
+ hasDescendant(recordDecl(has(recordDecl(hasName("Y"))),
hasName("X"))),
hasName("Z"));
EXPECT_TRUE(matches("class Z { class X { class Y {}; }; };",
@@ -498,9 +535,9 @@ TEST(DeclarationMatcher, HasDescendant) {
"};", ZDescendantClassXHasClassY));
DeclarationMatcher ZDescendantClassXDescendantClassY =
- record(
- hasDescendant(record(hasDescendant(record(hasName("Y"))),
- hasName("X"))),
+ recordDecl(
+ hasDescendant(recordDecl(hasDescendant(recordDecl(hasName("Y"))),
+ hasName("X"))),
hasName("Z"));
EXPECT_TRUE(
matches("class Z { class A { class X { class B { class Y {}; }; }; }; };",
@@ -518,6 +555,118 @@ TEST(DeclarationMatcher, HasDescendant) {
"};", ZDescendantClassXDescendantClassY));
}
+// Implements a run method that returns whether BoundNodes contains a
+// Decl bound to Id that can be dynamically cast to T.
+// Optionally checks that the check succeeded a specific number of times.
+template <typename T>
+class VerifyIdIsBoundTo : public BoundNodesCallback {
+public:
+ // Create an object that checks that a node of type \c T was bound to \c Id.
+ // Does not check for a certain number of matches.
+ explicit VerifyIdIsBoundTo(llvm::StringRef Id)
+ : Id(Id), ExpectedCount(-1), Count(0) {}
+
+ // Create an object that checks that a node of type \c T was bound to \c Id.
+ // Checks that there were exactly \c ExpectedCount matches.
+ VerifyIdIsBoundTo(llvm::StringRef Id, int ExpectedCount)
+ : Id(Id), ExpectedCount(ExpectedCount), Count(0) {}
+
+ // Create an object that checks that a node of type \c T was bound to \c Id.
+ // Checks that there was exactly one match with the name \c ExpectedName.
+ // Note that \c T must be a NamedDecl for this to work.
+ VerifyIdIsBoundTo(llvm::StringRef Id, llvm::StringRef ExpectedName)
+ : Id(Id), ExpectedCount(1), Count(0), ExpectedName(ExpectedName) {}
+
+ ~VerifyIdIsBoundTo() {
+ if (ExpectedCount != -1)
+ EXPECT_EQ(ExpectedCount, Count);
+ if (!ExpectedName.empty())
+ EXPECT_EQ(ExpectedName, Name);
+ }
+
+ virtual bool run(const BoundNodes *Nodes) {
+ if (Nodes->getNodeAs<T>(Id)) {
+ ++Count;
+ if (const NamedDecl *Named = Nodes->getNodeAs<NamedDecl>(Id)) {
+ Name = Named->getNameAsString();
+ } else if (const NestedNameSpecifier *NNS =
+ Nodes->getNodeAs<NestedNameSpecifier>(Id)) {
+ llvm::raw_string_ostream OS(Name);
+ NNS->print(OS, PrintingPolicy(LangOptions()));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool run(const BoundNodes *Nodes, ASTContext *Context) {
+ return run(Nodes);
+ }
+
+private:
+ const std::string Id;
+ const int ExpectedCount;
+ int Count;
+ const std::string ExpectedName;
+ std::string Name;
+};
+
+TEST(HasDescendant, MatchesDescendantTypes) {
+ EXPECT_TRUE(matches("void f() { int i = 3; }",
+ decl(hasDescendant(loc(builtinType())))));
+ EXPECT_TRUE(matches("void f() { int i = 3; }",
+ stmt(hasDescendant(builtinType()))));
+
+ EXPECT_TRUE(matches("void f() { int i = 3; }",
+ stmt(hasDescendant(loc(builtinType())))));
+ EXPECT_TRUE(matches("void f() { int i = 3; }",
+ stmt(hasDescendant(qualType(builtinType())))));
+
+ EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }",
+ stmt(hasDescendant(isInteger()))));
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void f() { int a; float c; int d; int e; }",
+ functionDecl(forEachDescendant(
+ varDecl(hasDescendant(isInteger())).bind("x"))),
+ new VerifyIdIsBoundTo<Decl>("x", 3)));
+}
+
+TEST(HasDescendant, MatchesDescendantsOfTypes) {
+ EXPECT_TRUE(matches("void f() { int*** i; }",
+ qualType(hasDescendant(builtinType()))));
+ EXPECT_TRUE(matches("void f() { int*** i; }",
+ qualType(hasDescendant(
+ pointerType(pointee(builtinType()))))));
+ EXPECT_TRUE(matches("void f() { int*** i; }",
+ typeLoc(hasDescendant(builtinTypeLoc()))));
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "void f() { int*** i; }",
+ qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))),
+ new VerifyIdIsBoundTo<Type>("x", 2)));
+}
+
+TEST(Has, MatchesChildrenOfTypes) {
+ EXPECT_TRUE(matches("int i;",
+ varDecl(hasName("i"), has(isInteger()))));
+ EXPECT_TRUE(notMatches("int** i;",
+ varDecl(hasName("i"), has(isInteger()))));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "int (*f)(float, int);",
+ qualType(functionType(), forEach(qualType(isInteger()).bind("x"))),
+ new VerifyIdIsBoundTo<QualType>("x", 2)));
+}
+
+TEST(Has, MatchesChildTypes) {
+ EXPECT_TRUE(matches(
+ "int* i;",
+ varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));
+ EXPECT_TRUE(notMatches(
+ "int* i;",
+ varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));
+}
+
TEST(Enum, DoesNotMatchClasses) {
EXPECT_TRUE(notMatches("class X {};", enumDecl(hasName("X"))));
}
@@ -527,7 +676,7 @@ TEST(Enum, MatchesEnums) {
}
TEST(EnumConstant, Matches) {
- DeclarationMatcher Matcher = enumConstant(hasName("A"));
+ DeclarationMatcher Matcher = enumConstantDecl(hasName("A"));
EXPECT_TRUE(matches("enum X{ A };", Matcher));
EXPECT_TRUE(notMatches("enum X{ B };", Matcher));
EXPECT_TRUE(notMatches("enum X {};", Matcher));
@@ -535,9 +684,8 @@ TEST(EnumConstant, Matches) {
TEST(StatementMatcher, Has) {
StatementMatcher HasVariableI =
- expression(
- hasType(pointsTo(record(hasName("X")))),
- has(declarationReference(to(variable(hasName("i"))))));
+ expr(hasType(pointsTo(recordDecl(hasName("X")))),
+ has(declRefExpr(to(varDecl(hasName("i"))))));
EXPECT_TRUE(matches(
"class X; X *x(int); void c() { int i; x(i); }", HasVariableI));
@@ -547,9 +695,8 @@ TEST(StatementMatcher, Has) {
TEST(StatementMatcher, HasDescendant) {
StatementMatcher HasDescendantVariableI =
- expression(
- hasType(pointsTo(record(hasName("X")))),
- hasDescendant(declarationReference(to(variable(hasName("i"))))));
+ expr(hasType(pointsTo(recordDecl(hasName("X")))),
+ hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));
EXPECT_TRUE(matches(
"class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",
@@ -560,160 +707,127 @@ TEST(StatementMatcher, HasDescendant) {
}
TEST(TypeMatcher, MatchesClassType) {
- TypeMatcher TypeA = hasDeclaration(record(hasName("A")));
+ TypeMatcher TypeA = hasDeclaration(recordDecl(hasName("A")));
EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));
EXPECT_TRUE(notMatches("class A {};", TypeA));
- TypeMatcher TypeDerivedFromA = hasDeclaration(record(isDerivedFrom("A")));
+ TypeMatcher TypeDerivedFromA = hasDeclaration(recordDecl(isDerivedFrom("A")));
EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",
TypeDerivedFromA));
EXPECT_TRUE(notMatches("class A {};", TypeA));
TypeMatcher TypeAHasClassB = hasDeclaration(
- record(hasName("A"), has(record(hasName("B")))));
+ recordDecl(hasName("A"), has(recordDecl(hasName("B")))));
EXPECT_TRUE(
matches("class A { public: A *a; class B {}; };", TypeAHasClassB));
}
-// Returns from Run whether 'bound_nodes' contain a Decl bound to 'Id', which
-// can be dynamically casted to T.
-// Optionally checks that the check succeeded a specific number of times.
-template <typename T>
-class VerifyIdIsBoundToDecl : public BoundNodesCallback {
-public:
- // Create an object that checks that a node of type 'T' was bound to 'Id'.
- // Does not check for a certain number of matches.
- explicit VerifyIdIsBoundToDecl(const std::string& Id)
- : Id(Id), ExpectedCount(-1), Count(0) {}
-
- // Create an object that checks that a node of type 'T' was bound to 'Id'.
- // Checks that there were exactly 'ExpectedCount' matches.
- explicit VerifyIdIsBoundToDecl(const std::string& Id, int ExpectedCount)
- : Id(Id), ExpectedCount(ExpectedCount), Count(0) {}
-
- ~VerifyIdIsBoundToDecl() {
- if (ExpectedCount != -1) {
- EXPECT_EQ(ExpectedCount, Count);
- }
- }
-
- virtual bool run(const BoundNodes *Nodes) {
- if (Nodes->getDeclAs<T>(Id) != NULL) {
- ++Count;
- return true;
- }
- return false;
- }
-
-private:
- const std::string Id;
- const int ExpectedCount;
- int Count;
-};
-template <typename T>
-class VerifyIdIsBoundToStmt : public BoundNodesCallback {
-public:
- explicit VerifyIdIsBoundToStmt(const std::string &Id) : Id(Id) {}
- virtual bool run(const BoundNodes *Nodes) {
- const T *Node = Nodes->getStmtAs<T>(Id);
- return Node != NULL;
- }
-private:
- const std::string Id;
-};
-
TEST(Matcher, BindMatchedNodes) {
- DeclarationMatcher ClassX = has(record(hasName("::X")).bind("x"));
+ DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x"));
EXPECT_TRUE(matchAndVerifyResultTrue("class X {};",
- ClassX, new VerifyIdIsBoundToDecl<CXXRecordDecl>("x")));
+ ClassX, new VerifyIdIsBoundTo<CXXRecordDecl>("x")));
EXPECT_TRUE(matchAndVerifyResultFalse("class X {};",
- ClassX, new VerifyIdIsBoundToDecl<CXXRecordDecl>("other-id")));
+ ClassX, new VerifyIdIsBoundTo<CXXRecordDecl>("other-id")));
TypeMatcher TypeAHasClassB = hasDeclaration(
- record(hasName("A"), has(record(hasName("B")).bind("b"))));
+ recordDecl(hasName("A"), has(recordDecl(hasName("B")).bind("b"))));
EXPECT_TRUE(matchAndVerifyResultTrue("class A { public: A *a; class B {}; };",
TypeAHasClassB,
- new VerifyIdIsBoundToDecl<Decl>("b")));
+ new VerifyIdIsBoundTo<Decl>("b")));
- StatementMatcher MethodX = call(callee(method(hasName("x")))).bind("x");
+ StatementMatcher MethodX =
+ callExpr(callee(methodDecl(hasName("x")))).bind("x");
EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };",
MethodX,
- new VerifyIdIsBoundToStmt<CXXMemberCallExpr>("x")));
+ new VerifyIdIsBoundTo<CXXMemberCallExpr>("x")));
}
TEST(Matcher, BindTheSameNameInAlternatives) {
StatementMatcher matcher = anyOf(
binaryOperator(hasOperatorName("+"),
- hasLHS(expression().bind("x")),
+ hasLHS(expr().bind("x")),
hasRHS(integerLiteral(equals(0)))),
binaryOperator(hasOperatorName("+"),
hasLHS(integerLiteral(equals(0))),
- hasRHS(expression().bind("x"))));
+ hasRHS(expr().bind("x"))));
EXPECT_TRUE(matchAndVerifyResultTrue(
// The first branch of the matcher binds x to 0 but then fails.
// The second branch binds x to f() and succeeds.
"int f() { return 0 + f(); }",
matcher,
- new VerifyIdIsBoundToStmt<CallExpr>("x")));
+ new VerifyIdIsBoundTo<CallExpr>("x")));
+}
+
+TEST(Matcher, BindsIDForMemoizedResults) {
+ // Using the same matcher in two match expressions will make memoization
+ // kick in.
+ DeclarationMatcher ClassX = recordDecl(hasName("X")).bind("x");
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class A { class B { class X {}; }; };",
+ DeclarationMatcher(anyOf(
+ recordDecl(hasName("A"), hasDescendant(ClassX)),
+ recordDecl(hasName("B"), hasDescendant(ClassX)))),
+ new VerifyIdIsBoundTo<Decl>("x", 2)));
}
TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
- TypeMatcher ClassX = hasDeclaration(record(hasName("X")));
+ TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
EXPECT_TRUE(
- matches("class X {}; void y(X &x) { x; }", expression(hasType(ClassX))));
+ matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));
EXPECT_TRUE(
notMatches("class X {}; void y(X *x) { x; }",
- expression(hasType(ClassX))));
+ expr(hasType(ClassX))));
EXPECT_TRUE(
matches("class X {}; void y(X *x) { x; }",
- expression(hasType(pointsTo(ClassX)))));
+ expr(hasType(pointsTo(ClassX)))));
}
TEST(HasType, TakesQualTypeMatcherAndMatchesValueDecl) {
- TypeMatcher ClassX = hasDeclaration(record(hasName("X")));
+ TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
EXPECT_TRUE(
- matches("class X {}; void y() { X x; }", variable(hasType(ClassX))));
+ matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));
EXPECT_TRUE(
- notMatches("class X {}; void y() { X *x; }", variable(hasType(ClassX))));
+ notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
EXPECT_TRUE(
matches("class X {}; void y() { X *x; }",
- variable(hasType(pointsTo(ClassX)))));
+ varDecl(hasType(pointsTo(ClassX)))));
}
TEST(HasType, TakesDeclMatcherAndMatchesExpr) {
- DeclarationMatcher ClassX = record(hasName("X"));
+ DeclarationMatcher ClassX = recordDecl(hasName("X"));
EXPECT_TRUE(
- matches("class X {}; void y(X &x) { x; }", expression(hasType(ClassX))));
+ matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));
EXPECT_TRUE(
notMatches("class X {}; void y(X *x) { x; }",
- expression(hasType(ClassX))));
+ expr(hasType(ClassX))));
}
TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {
- DeclarationMatcher ClassX = record(hasName("X"));
+ DeclarationMatcher ClassX = recordDecl(hasName("X"));
EXPECT_TRUE(
- matches("class X {}; void y() { X x; }", variable(hasType(ClassX))));
+ matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));
EXPECT_TRUE(
- notMatches("class X {}; void y() { X *x; }", variable(hasType(ClassX))));
+ notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
}
TEST(Matcher, Call) {
// FIXME: Do we want to overload Call() to directly take
// Matcher<Decl>, too?
- StatementMatcher MethodX = call(hasDeclaration(method(hasName("x"))));
+ StatementMatcher MethodX = callExpr(hasDeclaration(methodDecl(hasName("x"))));
EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));
EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));
- StatementMatcher MethodOnY = memberCall(on(hasType(record(hasName("Y")))));
+ StatementMatcher MethodOnY =
+ memberCallExpr(on(hasType(recordDecl(hasName("Y")))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
@@ -732,7 +846,7 @@ TEST(Matcher, Call) {
MethodOnY));
StatementMatcher MethodOnYPointer =
- memberCall(on(hasType(pointsTo(record(hasName("Y"))))));
+ memberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
@@ -751,20 +865,50 @@ TEST(Matcher, Call) {
MethodOnYPointer));
}
+TEST(Matcher, Lambda) {
+ EXPECT_TRUE(matches("auto f = [&] (int i) { return i; };",
+ lambdaExpr()));
+}
+
+TEST(Matcher, ForRange) {
+ EXPECT_TRUE(matches("int as[] = { 1, 2, 3 };"
+ "void f() { for (auto &a : as); }",
+ forRangeStmt()));
+ EXPECT_TRUE(notMatches("void f() { for (int i; i<5; ++i); }",
+ forRangeStmt()));
+}
+
+TEST(Matcher, UserDefinedLiteral) {
+ EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"
+ " return i + 1;"
+ "}"
+ "char c = 'a'_inc;",
+ userDefinedLiteral()));
+}
+
+TEST(Matcher, FlowControl) {
+ EXPECT_TRUE(matches("void f() { while(true) { break; } }", breakStmt()));
+ EXPECT_TRUE(matches("void f() { while(true) { continue; } }",
+ continueStmt()));
+ EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", gotoStmt()));
+ EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", labelStmt()));
+ EXPECT_TRUE(matches("void f() { return; }", returnStmt()));
+}
+
TEST(HasType, MatchesAsString) {
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
- memberCall(on(hasType(asString("class Y *"))))));
+ memberCallExpr(on(hasType(asString("class Y *"))))));
EXPECT_TRUE(matches("class X { void x(int x) {} };",
- method(hasParameter(0, hasType(asString("int"))))));
+ methodDecl(hasParameter(0, hasType(asString("int"))))));
EXPECT_TRUE(matches("namespace ns { struct A {}; } struct B { ns::A a; };",
- field(hasType(asString("ns::A")))));
+ fieldDecl(hasType(asString("ns::A")))));
EXPECT_TRUE(matches("namespace { struct A {}; } struct B { A a; };",
- field(hasType(asString("struct <anonymous>::A")))));
+ fieldDecl(hasType(asString("struct <anonymous>::A")))));
}
TEST(Matcher, OverloadedOperatorCall) {
- StatementMatcher OpCall = overloadedOperatorCall();
+ StatementMatcher OpCall = operatorCallExpr();
// Unary operator
EXPECT_TRUE(matches("class Y { }; "
"bool operator!(Y x) { return false; }; "
@@ -791,12 +935,12 @@ TEST(Matcher, OverloadedOperatorCall) {
TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
StatementMatcher OpCallAndAnd =
- overloadedOperatorCall(hasOverloadedOperatorName("&&"));
+ operatorCallExpr(hasOverloadedOperatorName("&&"));
EXPECT_TRUE(matches("class Y { }; "
"bool operator&&(Y x, Y y) { return true; }; "
"Y a; Y b; bool c = a && b;", OpCallAndAnd));
StatementMatcher OpCallLessLess =
- overloadedOperatorCall(hasOverloadedOperatorName("<<"));
+ operatorCallExpr(hasOverloadedOperatorName("<<"));
EXPECT_TRUE(notMatches("class Y { }; "
"bool operator&&(Y x, Y y) { return true; }; "
"Y a; Y b; bool c = a && b;",
@@ -805,7 +949,7 @@ TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
TEST(Matcher, ThisPointerType) {
StatementMatcher MethodOnY =
- memberCall(thisPointerType(record(hasName("Y"))));
+ memberCallExpr(thisPointerType(recordDecl(hasName("Y"))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
@@ -835,9 +979,9 @@ TEST(Matcher, ThisPointerType) {
TEST(Matcher, VariableUsage) {
StatementMatcher Reference =
- declarationReference(to(
- variable(hasInitializer(
- memberCall(thisPointerType(record(hasName("Y"))))))));
+ declRefExpr(to(
+ varDecl(hasInitializer(
+ memberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
EXPECT_TRUE(matches(
"class Y {"
@@ -862,12 +1006,12 @@ TEST(Matcher, VariableUsage) {
TEST(Matcher, FindsVarDeclInFuncitonParameter) {
EXPECT_TRUE(matches(
"void f(int i) {}",
- variable(hasName("i"))));
+ varDecl(hasName("i"))));
}
TEST(Matcher, CalledVariable) {
- StatementMatcher CallOnVariableY = expression(
- memberCall(on(declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher CallOnVariableY =
+ memberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(matches(
"class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY));
@@ -904,81 +1048,81 @@ TEST(UnaryExpressionOrTypeTraitExpression, MatchesCorrectType) {
hasArgumentOfType(asString("float")))));
EXPECT_TRUE(matches(
"struct A {}; void x() { A a; int b = sizeof(a); }",
- sizeOfExpr(hasArgumentOfType(hasDeclaration(record(hasName("A")))))));
+ sizeOfExpr(hasArgumentOfType(hasDeclaration(recordDecl(hasName("A")))))));
EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr(
- hasArgumentOfType(hasDeclaration(record(hasName("string")))))));
+ hasArgumentOfType(hasDeclaration(recordDecl(hasName("string")))))));
}
TEST(MemberExpression, DoesNotMatchClasses) {
- EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpression()));
+ EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpr()));
}
TEST(MemberExpression, MatchesMemberFunctionCall) {
- EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpression()));
+ EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr()));
}
TEST(MemberExpression, MatchesVariable) {
EXPECT_TRUE(
- matches("class Y { void x() { this->y; } int y; };", memberExpression()));
+ matches("class Y { void x() { this->y; } int y; };", memberExpr()));
EXPECT_TRUE(
- matches("class Y { void x() { y; } int y; };", memberExpression()));
+ matches("class Y { void x() { y; } int y; };", memberExpr()));
EXPECT_TRUE(
- matches("class Y { void x() { Y y; y.y; } int y; };",
- memberExpression()));
+ matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));
}
TEST(MemberExpression, MatchesStaticVariable) {
EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
- memberExpression()));
+ memberExpr()));
EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
- memberExpression()));
+ memberExpr()));
EXPECT_TRUE(notMatches("class Y { void x() { Y::y; } static int y; };",
- memberExpression()));
+ memberExpr()));
}
TEST(IsInteger, MatchesIntegers) {
- EXPECT_TRUE(matches("int i = 0;", variable(hasType(isInteger()))));
- EXPECT_TRUE(matches("long long i = 0; void f(long long) { }; void g() {f(i);}",
- call(hasArgument(0, declarationReference(
- to(variable(hasType(isInteger()))))))));
+ EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isInteger()))));
+ EXPECT_TRUE(matches(
+ "long long i = 0; void f(long long) { }; void g() {f(i);}",
+ callExpr(hasArgument(0, declRefExpr(
+ to(varDecl(hasType(isInteger()))))))));
}
TEST(IsInteger, ReportsNoFalsePositives) {
- EXPECT_TRUE(notMatches("int *i;", variable(hasType(isInteger()))));
+ EXPECT_TRUE(notMatches("int *i;", varDecl(hasType(isInteger()))));
EXPECT_TRUE(notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}",
- call(hasArgument(0, declarationReference(
- to(variable(hasType(isInteger()))))))));
+ callExpr(hasArgument(0, declRefExpr(
+ to(varDecl(hasType(isInteger()))))))));
}
TEST(IsArrow, MatchesMemberVariablesViaArrow) {
EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
EXPECT_TRUE(matches("class Y { void x() { y; } int y; };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
}
TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) {
EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } static int y; };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
}
TEST(IsArrow, MatchesMemberCallsViaArrow) {
EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
EXPECT_TRUE(matches("class Y { void x() { x(); } };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
- memberExpression(isArrow())));
+ memberExpr(isArrow())));
}
TEST(Callee, MatchesDeclarations) {
- StatementMatcher CallMethodX = call(callee(method(hasName("x"))));
+ StatementMatcher CallMethodX = callExpr(callee(methodDecl(hasName("x"))));
EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));
EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));
@@ -986,13 +1130,13 @@ TEST(Callee, MatchesDeclarations) {
TEST(Callee, MatchesMemberExpressions) {
EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
- call(callee(memberExpression()))));
+ callExpr(callee(memberExpr()))));
EXPECT_TRUE(
- notMatches("class Y { void x() { this->x(); } };", call(callee(call()))));
+ notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));
}
TEST(Function, MatchesFunctionDeclarations) {
- StatementMatcher CallFunctionF = call(callee(function(hasName("f"))));
+ StatementMatcher CallFunctionF = callExpr(callee(functionDecl(hasName("f"))));
EXPECT_TRUE(matches("void f() { f(); }", CallFunctionF));
EXPECT_TRUE(notMatches("void f() { }", CallFunctionF));
@@ -1017,30 +1161,51 @@ TEST(Function, MatchesFunctionDeclarations) {
CallFunctionF));
}
+TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
+ EXPECT_TRUE(
+ matches("template <typename T> void f(T t) {}",
+ functionTemplateDecl(hasName("f"))));
+}
+
+TEST(FunctionTemplate, DoesNotMatchFunctionDeclarations) {
+ EXPECT_TRUE(
+ notMatches("void f(double d); void f(int t) {}",
+ functionTemplateDecl(hasName("f"))));
+}
+
+TEST(FunctionTemplate, DoesNotMatchFunctionTemplateSpecializations) {
+ EXPECT_TRUE(
+ notMatches("void g(); template <typename T> void f(T t) {}"
+ "template <> void f(int t) { g(); }",
+ functionTemplateDecl(hasName("f"),
+ hasDescendant(declRefExpr(to(
+ functionDecl(hasName("g"))))))));
+}
+
TEST(Matcher, Argument) {
- StatementMatcher CallArgumentY = expression(call(
- hasArgument(0, declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher CallArgumentY = callExpr(
+ hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY));
EXPECT_TRUE(
matches("class X { void x(int) { int y; x(y); } };", CallArgumentY));
EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY));
- StatementMatcher WrongIndex = expression(call(
- hasArgument(42, declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher WrongIndex = callExpr(
+ hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex));
}
TEST(Matcher, AnyArgument) {
- StatementMatcher CallArgumentY = expression(call(
- hasAnyArgument(declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher CallArgumentY = callExpr(
+ hasAnyArgument(declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
}
TEST(Matcher, ArgumentCount) {
- StatementMatcher Call1Arg = expression(call(argumentCountIs(1)));
+ StatementMatcher Call1Arg = callExpr(argumentCountIs(1));
EXPECT_TRUE(matches("void x(int) { x(0); }", Call1Arg));
EXPECT_TRUE(matches("class X { void x(int) { x(0); } };", Call1Arg));
@@ -1048,8 +1213,8 @@ TEST(Matcher, ArgumentCount) {
}
TEST(Matcher, References) {
- DeclarationMatcher ReferenceClassX = variable(
- hasType(references(record(hasName("X")))));
+ DeclarationMatcher ReferenceClassX = varDecl(
+ hasType(references(recordDecl(hasName("X")))));
EXPECT_TRUE(matches("class X {}; void y(X y) { X &x = y; }",
ReferenceClassX));
EXPECT_TRUE(
@@ -1062,81 +1227,86 @@ TEST(Matcher, References) {
TEST(HasParameter, CallsInnerMatcher) {
EXPECT_TRUE(matches("class X { void x(int) {} };",
- method(hasParameter(0, variable()))));
+ methodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
- method(hasParameter(0, hasName("x")))));
+ methodDecl(hasParameter(0, hasName("x")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
- method(hasParameter(42, variable()))));
+ methodDecl(hasParameter(42, varDecl()))));
}
TEST(HasType, MatchesParameterVariableTypesStrictly) {
EXPECT_TRUE(matches("class X { void x(X x) {} };",
- method(hasParameter(0, hasType(record(hasName("X")))))));
+ methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(notMatches("class X { void x(const X &x) {} };",
- method(hasParameter(0, hasType(record(hasName("X")))))));
+ methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
- method(hasParameter(0, hasType(pointsTo(record(hasName("X"))))))));
+ methodDecl(hasParameter(0,
+ hasType(pointsTo(recordDecl(hasName("X"))))))));
EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
- method(hasParameter(0, hasType(references(record(hasName("X"))))))));
+ methodDecl(hasParameter(0,
+ hasType(references(recordDecl(hasName("X"))))))));
}
TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
EXPECT_TRUE(matches("class Y {}; class X { void x(X x, Y y) {} };",
- method(hasAnyParameter(hasType(record(hasName("X")))))));
+ methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(matches("class Y {}; class X { void x(Y y, X x) {} };",
- method(hasAnyParameter(hasType(record(hasName("X")))))));
+ methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
}
TEST(Returns, MatchesReturnTypes) {
EXPECT_TRUE(matches("class Y { int f() { return 1; } };",
- function(returns(asString("int")))));
+ functionDecl(returns(asString("int")))));
EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",
- function(returns(asString("float")))));
+ functionDecl(returns(asString("float")))));
EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",
- function(returns(hasDeclaration(record(hasName("Y")))))));
+ functionDecl(returns(hasDeclaration(
+ recordDecl(hasName("Y")))))));
}
TEST(IsExternC, MatchesExternCFunctionDeclarations) {
- EXPECT_TRUE(matches("extern \"C\" void f() {}", function(isExternC())));
- EXPECT_TRUE(matches("extern \"C\" { void f() {} }", function(isExternC())));
- EXPECT_TRUE(notMatches("void f() {}", function(isExternC())));
+ EXPECT_TRUE(matches("extern \"C\" void f() {}", functionDecl(isExternC())));
+ EXPECT_TRUE(matches("extern \"C\" { void f() {} }",
+ functionDecl(isExternC())));
+ EXPECT_TRUE(notMatches("void f() {}", functionDecl(isExternC())));
}
TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
- method(hasAnyParameter(hasType(record(hasName("X")))))));
+ methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
}
TEST(HasAnyParameter, DoesNotMatchThisPointer) {
EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
- method(hasAnyParameter(hasType(pointsTo(record(hasName("X"))))))));
+ methodDecl(hasAnyParameter(hasType(pointsTo(
+ recordDecl(hasName("X"))))))));
}
TEST(HasName, MatchesParameterVariableDeclartions) {
EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
- method(hasAnyParameter(hasName("x")))));
+ methodDecl(hasAnyParameter(hasName("x")))));
EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
- method(hasAnyParameter(hasName("x")))));
+ methodDecl(hasAnyParameter(hasName("x")))));
}
TEST(Matcher, MatchesClassTemplateSpecialization) {
EXPECT_TRUE(matches("template<typename T> struct A {};"
"template<> struct A<int> {};",
- classTemplateSpecialization()));
+ classTemplateSpecializationDecl()));
EXPECT_TRUE(matches("template<typename T> struct A {}; A<int> a;",
- classTemplateSpecialization()));
+ classTemplateSpecializationDecl()));
EXPECT_TRUE(notMatches("template<typename T> struct A {};",
- classTemplateSpecialization()));
+ classTemplateSpecializationDecl()));
}
TEST(Matcher, MatchesTypeTemplateArgument) {
EXPECT_TRUE(matches(
"template<typename T> struct B {};"
"B<int> b;",
- classTemplateSpecialization(hasAnyTemplateArgument(refersToType(
+ classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
asString("int"))))));
}
@@ -1145,25 +1315,31 @@ TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {
"struct B { int next; };"
"template<int(B::*next_ptr)> struct A {};"
"A<&B::next> a;",
- classTemplateSpecialization(hasAnyTemplateArgument(
- refersToDeclaration(field(hasName("next")))))));
+ classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToDeclaration(fieldDecl(hasName("next")))))));
+
+ EXPECT_TRUE(notMatches(
+ "template <typename T> struct A {};"
+ "A<int> a;",
+ classTemplateSpecializationDecl(hasAnyTemplateArgument(
+ refersToDeclaration(decl())))));
}
TEST(Matcher, MatchesSpecificArgument) {
EXPECT_TRUE(matches(
"template<typename T, typename U> class A {};"
"A<bool, int> a;",
- classTemplateSpecialization(hasTemplateArgument(
+ classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))));
EXPECT_TRUE(notMatches(
"template<typename T, typename U> class A {};"
"A<int, bool> a;",
- classTemplateSpecialization(hasTemplateArgument(
+ classTemplateSpecializationDecl(hasTemplateArgument(
1, refersToType(asString("int"))))));
}
TEST(Matcher, ConstructorCall) {
- StatementMatcher Constructor = expression(constructorCall());
+ StatementMatcher Constructor = constructExpr();
EXPECT_TRUE(
matches("class X { public: X(); }; void x() { X x; }", Constructor));
@@ -1177,8 +1353,8 @@ TEST(Matcher, ConstructorCall) {
}
TEST(Matcher, ConstructorArgument) {
- StatementMatcher Constructor = expression(constructorCall(
- hasArgument(0, declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher Constructor = constructExpr(
+ hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { int y; X x(y); }",
@@ -1193,16 +1369,15 @@ TEST(Matcher, ConstructorArgument) {
notMatches("class X { public: X(int); }; void x() { int z; X x(z); }",
Constructor));
- StatementMatcher WrongIndex = expression(constructorCall(
- hasArgument(42, declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher WrongIndex = constructExpr(
+ hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
notMatches("class X { public: X(int); }; void x() { int y; X x(y); }",
WrongIndex));
}
TEST(Matcher, ConstructorArgumentCount) {
- StatementMatcher Constructor1Arg =
- expression(constructorCall(argumentCountIs(1)));
+ StatementMatcher Constructor1Arg = constructExpr(argumentCountIs(1));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { X x(0); }",
@@ -1218,8 +1393,15 @@ TEST(Matcher, ConstructorArgumentCount) {
Constructor1Arg));
}
+TEST(Matcher,ThisExpr) {
+ EXPECT_TRUE(
+ matches("struct X { int a; int f () { return a; } };", thisExpr()));
+ EXPECT_TRUE(
+ notMatches("struct X { int f () { int a; return a; } };", thisExpr()));
+}
+
TEST(Matcher, BindTemporaryExpression) {
- StatementMatcher TempExpression = expression(bindTemporaryExpression());
+ StatementMatcher TempExpression = bindTemporaryExpr();
std::string ClassString = "class string { public: string(); ~string(); }; ";
@@ -1249,44 +1431,80 @@ TEST(Matcher, BindTemporaryExpression) {
TempExpression));
}
+TEST(MaterializeTemporaryExpr, MatchesTemporary) {
+ std::string ClassString =
+ "class string { public: string(); int length(); }; ";
+
+ EXPECT_TRUE(
+ matches(ClassString +
+ "string GetStringByValue();"
+ "void FunctionTakesString(string s);"
+ "void run() { FunctionTakesString(GetStringByValue()); }",
+ materializeTemporaryExpr()));
+
+ EXPECT_TRUE(
+ notMatches(ClassString +
+ "string* GetStringPointer(); "
+ "void FunctionTakesStringPtr(string* s);"
+ "void run() {"
+ " string* s = GetStringPointer();"
+ " FunctionTakesStringPtr(GetStringPointer());"
+ " FunctionTakesStringPtr(s);"
+ "}",
+ materializeTemporaryExpr()));
+
+ EXPECT_TRUE(
+ notMatches(ClassString +
+ "string GetStringByValue();"
+ "void run() { int k = GetStringByValue().length(); }",
+ materializeTemporaryExpr()));
+
+ EXPECT_TRUE(
+ notMatches(ClassString +
+ "string GetStringByValue();"
+ "void run() { GetStringByValue(); }",
+ materializeTemporaryExpr()));
+}
+
TEST(ConstructorDeclaration, SimpleCase) {
EXPECT_TRUE(matches("class Foo { Foo(int i); };",
- constructor(ofClass(hasName("Foo")))));
+ constructorDecl(ofClass(hasName("Foo")))));
EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
- constructor(ofClass(hasName("Bar")))));
+ constructorDecl(ofClass(hasName("Bar")))));
}
TEST(ConstructorDeclaration, IsImplicit) {
// This one doesn't match because the constructor is not added by the
// compiler (it is not needed).
EXPECT_TRUE(notMatches("class Foo { };",
- constructor(isImplicit())));
+ constructorDecl(isImplicit())));
// The compiler added the implicit default constructor.
EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
- constructor(isImplicit())));
+ constructorDecl(isImplicit())));
EXPECT_TRUE(matches("class Foo { Foo(){} };",
- constructor(unless(isImplicit()))));
+ constructorDecl(unless(isImplicit()))));
}
TEST(DestructorDeclaration, MatchesVirtualDestructor) {
EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
- destructor(ofClass(hasName("Foo")))));
+ destructorDecl(ofClass(hasName("Foo")))));
}
TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {
- EXPECT_TRUE(notMatches("class Foo {};", destructor(ofClass(hasName("Foo")))));
+ EXPECT_TRUE(notMatches("class Foo {};",
+ destructorDecl(ofClass(hasName("Foo")))));
}
TEST(HasAnyConstructorInitializer, SimpleCase) {
EXPECT_TRUE(notMatches(
"class Foo { Foo() { } };",
- constructor(hasAnyConstructorInitializer(anything()))));
+ constructorDecl(hasAnyConstructorInitializer(anything()))));
EXPECT_TRUE(matches(
"class Foo {"
" Foo() : foo_() { }"
" int foo_;"
"};",
- constructor(hasAnyConstructorInitializer(anything()))));
+ constructorDecl(hasAnyConstructorInitializer(anything()))));
}
TEST(HasAnyConstructorInitializer, ForField) {
@@ -1297,12 +1515,12 @@ TEST(HasAnyConstructorInitializer, ForField) {
" Baz foo_;"
" Baz bar_;"
"};";
- EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
- forField(hasType(record(hasName("Baz"))))))));
- EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ forField(hasType(recordDecl(hasName("Baz"))))))));
+ EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
forField(hasName("foo_"))))));
- EXPECT_TRUE(notMatches(Code, constructor(hasAnyConstructorInitializer(
- forField(hasType(record(hasName("Bar"))))))));
+ EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ forField(hasType(recordDecl(hasName("Bar"))))))));
}
TEST(HasAnyConstructorInitializer, WithInitializer) {
@@ -1311,9 +1529,9 @@ TEST(HasAnyConstructorInitializer, WithInitializer) {
" Foo() : foo_(0) { }"
" int foo_;"
"};";
- EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(0)))))));
- EXPECT_TRUE(notMatches(Code, constructor(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(1)))))));
}
@@ -1325,16 +1543,16 @@ TEST(HasAnyConstructorInitializer, IsWritten) {
" Bar foo_;"
" Bar bar_;"
"};";
- EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("foo_")), isWritten())))));
- EXPECT_TRUE(notMatches(Code, constructor(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("bar_")), isWritten())))));
- EXPECT_TRUE(matches(Code, constructor(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("bar_")), unless(isWritten()))))));
}
TEST(Matcher, NewExpression) {
- StatementMatcher New = expression(newExpression());
+ StatementMatcher New = newExpr();
EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }", New));
EXPECT_TRUE(
@@ -1345,9 +1563,8 @@ TEST(Matcher, NewExpression) {
}
TEST(Matcher, NewExpressionArgument) {
- StatementMatcher New = expression(constructorCall(
- hasArgument(
- 0, declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher New = constructExpr(
+ hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { int y; new X(y); }",
@@ -1359,16 +1576,15 @@ TEST(Matcher, NewExpressionArgument) {
notMatches("class X { public: X(int); }; void x() { int z; new X(z); }",
New));
- StatementMatcher WrongIndex = expression(constructorCall(
- hasArgument(
- 42, declarationReference(to(variable(hasName("y")))))));
+ StatementMatcher WrongIndex = constructExpr(
+ hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
notMatches("class X { public: X(int); }; void x() { int y; new X(y); }",
WrongIndex));
}
TEST(Matcher, NewExpressionArgumentCount) {
- StatementMatcher New = constructorCall(argumentCountIs(1));
+ StatementMatcher New = constructExpr(argumentCountIs(1));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { new X(0); }", New));
@@ -1379,11 +1595,11 @@ TEST(Matcher, NewExpressionArgumentCount) {
TEST(Matcher, DeleteExpression) {
EXPECT_TRUE(matches("struct A {}; void f(A* a) { delete a; }",
- deleteExpression()));
+ deleteExpr()));
}
TEST(Matcher, DefaultArgument) {
- StatementMatcher Arg = defaultArgument();
+ StatementMatcher Arg = defaultArgExpr();
EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));
EXPECT_TRUE(
@@ -1392,7 +1608,7 @@ TEST(Matcher, DefaultArgument) {
}
TEST(Matcher, StringLiterals) {
- StatementMatcher Literal = expression(stringLiteral());
+ StatementMatcher Literal = stringLiteral();
EXPECT_TRUE(matches("const char *s = \"string\";", Literal));
// wide string
EXPECT_TRUE(matches("const wchar_t *s = L\"string\";", Literal));
@@ -1403,7 +1619,7 @@ TEST(Matcher, StringLiterals) {
}
TEST(Matcher, CharacterLiterals) {
- StatementMatcher CharLiteral = expression(characterLiteral());
+ StatementMatcher CharLiteral = characterLiteral();
EXPECT_TRUE(matches("const char c = 'c';", CharLiteral));
// wide character
EXPECT_TRUE(matches("const char c = L'c';", CharLiteral));
@@ -1413,7 +1629,7 @@ TEST(Matcher, CharacterLiterals) {
}
TEST(Matcher, IntegerLiterals) {
- StatementMatcher HasIntLiteral = expression(integerLiteral());
+ StatementMatcher HasIntLiteral = integerLiteral();
EXPECT_TRUE(matches("int i = 10;", HasIntLiteral));
EXPECT_TRUE(matches("int i = 0x1AB;", HasIntLiteral));
EXPECT_TRUE(matches("int i = 10L;", HasIntLiteral));
@@ -1428,6 +1644,14 @@ TEST(Matcher, IntegerLiterals) {
EXPECT_TRUE(notMatches("int i = 10.0;", HasIntLiteral));
}
+TEST(Matcher, NullPtrLiteral) {
+ EXPECT_TRUE(matches("int* i = nullptr;", nullPtrLiteralExpr()));
+}
+
+TEST(Matcher, AsmStatement) {
+ EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt()));
+}
+
TEST(Matcher, Conditions) {
StatementMatcher Condition = ifStmt(hasCondition(boolLiteral(equals(true))));
@@ -1654,87 +1878,91 @@ TEST(ArraySubscriptMatchers, ArrayIndex) {
TEST(ArraySubscriptMatchers, MatchesArrayBase) {
EXPECT_TRUE(matches(
"int i[2]; void f() { i[1] = 2; }",
- arraySubscriptExpr(hasBase(implicitCast(
- hasSourceExpression(declarationReference()))))));
+ arraySubscriptExpr(hasBase(implicitCastExpr(
+ hasSourceExpression(declRefExpr()))))));
}
TEST(Matcher, HasNameSupportsNamespaces) {
EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
- record(hasName("a::b::C"))));
+ recordDecl(hasName("a::b::C"))));
EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
- record(hasName("::a::b::C"))));
+ recordDecl(hasName("::a::b::C"))));
EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
- record(hasName("b::C"))));
+ recordDecl(hasName("b::C"))));
EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
- record(hasName("C"))));
+ recordDecl(hasName("C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("c::b::C"))));
+ recordDecl(hasName("c::b::C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("a::c::C"))));
+ recordDecl(hasName("a::c::C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("a::b::A"))));
+ recordDecl(hasName("a::b::A"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("::C"))));
+ recordDecl(hasName("::C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("::b::C"))));
+ recordDecl(hasName("::b::C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("z::a::b::C"))));
+ recordDecl(hasName("z::a::b::C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
- record(hasName("a+b::C"))));
+ recordDecl(hasName("a+b::C"))));
EXPECT_TRUE(notMatches("namespace a { namespace b { class AC; } }",
- record(hasName("C"))));
+ recordDecl(hasName("C"))));
}
TEST(Matcher, HasNameSupportsOuterClasses) {
EXPECT_TRUE(
- matches("class A { class B { class C; }; };", record(hasName("A::B::C"))));
+ matches("class A { class B { class C; }; };",
+ recordDecl(hasName("A::B::C"))));
EXPECT_TRUE(
matches("class A { class B { class C; }; };",
- record(hasName("::A::B::C"))));
+ recordDecl(hasName("::A::B::C"))));
EXPECT_TRUE(
- matches("class A { class B { class C; }; };", record(hasName("B::C"))));
+ matches("class A { class B { class C; }; };",
+ recordDecl(hasName("B::C"))));
EXPECT_TRUE(
- matches("class A { class B { class C; }; };", record(hasName("C"))));
+ matches("class A { class B { class C; }; };",
+ recordDecl(hasName("C"))));
EXPECT_TRUE(
notMatches("class A { class B { class C; }; };",
- record(hasName("c::B::C"))));
+ recordDecl(hasName("c::B::C"))));
EXPECT_TRUE(
notMatches("class A { class B { class C; }; };",
- record(hasName("A::c::C"))));
+ recordDecl(hasName("A::c::C"))));
EXPECT_TRUE(
notMatches("class A { class B { class C; }; };",
- record(hasName("A::B::A"))));
+ recordDecl(hasName("A::B::A"))));
EXPECT_TRUE(
- notMatches("class A { class B { class C; }; };", record(hasName("::C"))));
+ notMatches("class A { class B { class C; }; };",
+ recordDecl(hasName("::C"))));
EXPECT_TRUE(
notMatches("class A { class B { class C; }; };",
- record(hasName("::B::C"))));
+ recordDecl(hasName("::B::C"))));
EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
- record(hasName("z::A::B::C"))));
+ recordDecl(hasName("z::A::B::C"))));
EXPECT_TRUE(
notMatches("class A { class B { class C; }; };",
- record(hasName("A+B::C"))));
+ recordDecl(hasName("A+B::C"))));
}
TEST(Matcher, IsDefinition) {
DeclarationMatcher DefinitionOfClassA =
- record(hasName("A"), isDefinition());
+ recordDecl(hasName("A"), isDefinition());
EXPECT_TRUE(matches("class A {};", DefinitionOfClassA));
EXPECT_TRUE(notMatches("class A;", DefinitionOfClassA));
DeclarationMatcher DefinitionOfVariableA =
- variable(hasName("a"), isDefinition());
+ varDecl(hasName("a"), isDefinition());
EXPECT_TRUE(matches("int a;", DefinitionOfVariableA));
EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
DeclarationMatcher DefinitionOfMethodA =
- method(hasName("a"), isDefinition());
+ methodDecl(hasName("a"), isDefinition());
EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
}
TEST(Matcher, OfClass) {
- StatementMatcher Constructor = constructorCall(hasDeclaration(method(
+ StatementMatcher Constructor = constructExpr(hasDeclaration(methodDecl(
ofClass(hasName("X")))));
EXPECT_TRUE(
@@ -1751,7 +1979,8 @@ TEST(Matcher, VisitsTemplateInstantiations) {
EXPECT_TRUE(matches(
"class A { public: void x(); };"
"template <typename T> class B { public: void y() { T t; t.x(); } };"
- "void f() { B<A> b; b.y(); }", call(callee(method(hasName("x"))))));
+ "void f() { B<A> b; b.y(); }",
+ callExpr(callee(methodDecl(hasName("x"))))));
EXPECT_TRUE(matches(
"class A { public: void x(); };"
@@ -1761,8 +1990,9 @@ TEST(Matcher, VisitsTemplateInstantiations) {
"};"
"void f() {"
" C::B<A> b; b.y();"
- "}", record(hasName("C"),
- hasDescendant(call(callee(method(hasName("x"))))))));
+ "}",
+ recordDecl(hasName("C"),
+ hasDescendant(callExpr(callee(methodDecl(hasName("x"))))))));
}
TEST(Matcher, HandlesNullQualTypes) {
@@ -1781,7 +2011,7 @@ TEST(Matcher, HandlesNullQualTypes) {
"void g() {"
" f(0);"
"}",
- expression(hasType(TypeMatcher(
+ expr(hasType(TypeMatcher(
anyOf(
TypeMatcher(hasDeclaration(anything())),
pointsTo(AnyType),
@@ -1798,16 +2028,16 @@ AST_MATCHER_P(Decl, just, internal::Matcher<Decl>, AMatcher) {
}
TEST(AstMatcherPMacro, Works) {
- DeclarationMatcher HasClassB = just(has(record(hasName("B")).bind("b")));
+ DeclarationMatcher HasClassB = just(has(recordDecl(hasName("B")).bind("b")));
EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
- HasClassB, new VerifyIdIsBoundToDecl<Decl>("b")));
+ HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
- HasClassB, new VerifyIdIsBoundToDecl<Decl>("a")));
+ HasClassB, new VerifyIdIsBoundTo<Decl>("a")));
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
- HasClassB, new VerifyIdIsBoundToDecl<Decl>("b")));
+ HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
}
AST_POLYMORPHIC_MATCHER_P(
@@ -1815,27 +2045,27 @@ AST_POLYMORPHIC_MATCHER_P(
TOOLING_COMPILE_ASSERT((llvm::is_same<NodeType, Decl>::value) ||
(llvm::is_same<NodeType, Stmt>::value),
assert_node_type_is_accessible);
- internal::TypedBaseMatcher<Decl> ChildMatcher(AMatcher);
return Finder->matchesChildOf(
- Node, ChildMatcher, Builder,
+ Node, AMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_First);
}
TEST(AstPolymorphicMatcherPMacro, Works) {
- DeclarationMatcher HasClassB = polymorphicHas(record(hasName("B")).bind("b"));
+ DeclarationMatcher HasClassB =
+ polymorphicHas(recordDecl(hasName("B")).bind("b"));
EXPECT_TRUE(matchAndVerifyResultTrue("class A { class B {}; };",
- HasClassB, new VerifyIdIsBoundToDecl<Decl>("b")));
+ HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class B {}; };",
- HasClassB, new VerifyIdIsBoundToDecl<Decl>("a")));
+ HasClassB, new VerifyIdIsBoundTo<Decl>("a")));
EXPECT_TRUE(matchAndVerifyResultFalse("class A { class C {}; };",
- HasClassB, new VerifyIdIsBoundToDecl<Decl>("b")));
+ HasClassB, new VerifyIdIsBoundTo<Decl>("b")));
StatementMatcher StatementHasClassB =
- polymorphicHas(record(hasName("B")));
+ polymorphicHas(recordDecl(hasName("B")));
EXPECT_TRUE(matches("void x() { class B {}; }", StatementHasClassB));
}
@@ -1843,6 +2073,9 @@ TEST(AstPolymorphicMatcherPMacro, Works) {
TEST(For, FindsForLoops) {
EXPECT_TRUE(matches("void f() { for(;;); }", forStmt()));
EXPECT_TRUE(matches("void f() { if(true) for(;;); }", forStmt()));
+ EXPECT_TRUE(notMatches("int as[] = { 1, 2, 3 };"
+ "void f() { for (auto &a : as); }",
+ forStmt()));
}
TEST(For, ForLoopInternals) {
@@ -1854,7 +2087,7 @@ TEST(For, ForLoopInternals) {
TEST(For, NegativeForLoopInternals) {
EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
- forStmt(hasCondition(expression()))));
+ forStmt(hasCondition(expr()))));
EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
forStmt(hasLoopInit(anything()))));
}
@@ -1865,29 +2098,29 @@ TEST(For, ReportsNoFalsePositives) {
}
TEST(CompoundStatement, HandlesSimpleCases) {
- EXPECT_TRUE(notMatches("void f();", compoundStatement()));
- EXPECT_TRUE(matches("void f() {}", compoundStatement()));
- EXPECT_TRUE(matches("void f() {{}}", compoundStatement()));
+ EXPECT_TRUE(notMatches("void f();", compoundStmt()));
+ EXPECT_TRUE(matches("void f() {}", compoundStmt()));
+ EXPECT_TRUE(matches("void f() {{}}", compoundStmt()));
}
TEST(CompoundStatement, DoesNotMatchEmptyStruct) {
// It's not a compound statement just because there's "{}" in the source
// text. This is an AST search, not grep.
EXPECT_TRUE(notMatches("namespace n { struct S {}; }",
- compoundStatement()));
+ compoundStmt()));
EXPECT_TRUE(matches("namespace n { struct S { void f() {{}} }; }",
- compoundStatement()));
+ compoundStmt()));
}
TEST(HasBody, FindsBodyOfForWhileDoLoops) {
EXPECT_TRUE(matches("void f() { for(;;) {} }",
- forStmt(hasBody(compoundStatement()))));
+ forStmt(hasBody(compoundStmt()))));
EXPECT_TRUE(notMatches("void f() { for(;;); }",
- forStmt(hasBody(compoundStatement()))));
+ forStmt(hasBody(compoundStmt()))));
EXPECT_TRUE(matches("void f() { while(true) {} }",
- whileStmt(hasBody(compoundStatement()))));
+ whileStmt(hasBody(compoundStmt()))));
EXPECT_TRUE(matches("void f() { do {} while(true); }",
- doStmt(hasBody(compoundStatement()))));
+ doStmt(hasBody(compoundStmt()))));
}
TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
@@ -1895,67 +2128,67 @@ TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
// definition, and the function body itself must be a compound
// statement.
EXPECT_TRUE(matches("void f() { for (;;); }",
- compoundStatement(hasAnySubstatement(forStmt()))));
+ compoundStmt(hasAnySubstatement(forStmt()))));
}
TEST(HasAnySubstatement, IsNotRecursive) {
// It's really "has any immediate substatement".
EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
- compoundStatement(hasAnySubstatement(forStmt()))));
+ compoundStmt(hasAnySubstatement(forStmt()))));
}
TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {
EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
- compoundStatement(hasAnySubstatement(forStmt()))));
+ compoundStmt(hasAnySubstatement(forStmt()))));
}
TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {
EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
- compoundStatement(hasAnySubstatement(forStmt()))));
+ compoundStmt(hasAnySubstatement(forStmt()))));
}
TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
EXPECT_TRUE(matches("void f() { }",
- compoundStatement(statementCountIs(0))));
+ compoundStmt(statementCountIs(0))));
EXPECT_TRUE(notMatches("void f() {}",
- compoundStatement(statementCountIs(1))));
+ compoundStmt(statementCountIs(1))));
}
TEST(StatementCountIs, AppearsToMatchOnlyOneCount) {
EXPECT_TRUE(matches("void f() { 1; }",
- compoundStatement(statementCountIs(1))));
+ compoundStmt(statementCountIs(1))));
EXPECT_TRUE(notMatches("void f() { 1; }",
- compoundStatement(statementCountIs(0))));
+ compoundStmt(statementCountIs(0))));
EXPECT_TRUE(notMatches("void f() { 1; }",
- compoundStatement(statementCountIs(2))));
+ compoundStmt(statementCountIs(2))));
}
TEST(StatementCountIs, WorksWithMultipleStatements) {
EXPECT_TRUE(matches("void f() { 1; 2; 3; }",
- compoundStatement(statementCountIs(3))));
+ compoundStmt(statementCountIs(3))));
}
TEST(StatementCountIs, WorksWithNestedCompoundStatements) {
EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
- compoundStatement(statementCountIs(1))));
+ compoundStmt(statementCountIs(1))));
EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
- compoundStatement(statementCountIs(2))));
+ compoundStmt(statementCountIs(2))));
EXPECT_TRUE(notMatches("void f() { { 1; } { 1; 2; 3; 4; } }",
- compoundStatement(statementCountIs(3))));
+ compoundStmt(statementCountIs(3))));
EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
- compoundStatement(statementCountIs(4))));
+ compoundStmt(statementCountIs(4))));
}
TEST(Member, WorksInSimplestCase) {
EXPECT_TRUE(matches("struct { int first; } s; int i(s.first);",
- memberExpression(member(hasName("first")))));
+ memberExpr(member(hasName("first")))));
}
TEST(Member, DoesNotMatchTheBaseExpression) {
// Don't pick out the wrong part of the member expression, this should
// be checking the member (name) only.
EXPECT_TRUE(notMatches("struct { int i; } first; int i(first.i);",
- memberExpression(member(hasName("first")))));
+ memberExpr(member(hasName("first")))));
}
TEST(Member, MatchesInMemberFunctionCall) {
@@ -1963,211 +2196,246 @@ TEST(Member, MatchesInMemberFunctionCall) {
" struct { void first() {}; } s;"
" s.first();"
"};",
- memberExpression(member(hasName("first")))));
+ memberExpr(member(hasName("first")))));
+}
+
+TEST(Member, MatchesMember) {
+ EXPECT_TRUE(matches(
+ "struct A { int i; }; void f() { A a; a.i = 2; }",
+ memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
+ EXPECT_TRUE(notMatches(
+ "struct A { float f; }; void f() { A a; a.f = 2.0f; }",
+ memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
+}
+
+TEST(Member, MatchesMemberAllocationFunction) {
+ // Fails in C++11 mode
+ EXPECT_TRUE(matchesConditionally(
+ "namespace std { typedef typeof(sizeof(int)) size_t; }"
+ "class X { void *operator new(std::size_t); };",
+ methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
+
+ EXPECT_TRUE(matches("class X { void operator delete(void*); };",
+ methodDecl(ofClass(hasName("X")))));
+
+ // Fails in C++11 mode
+ EXPECT_TRUE(matchesConditionally(
+ "namespace std { typedef typeof(sizeof(int)) size_t; }"
+ "class X { void operator delete[](void*, std::size_t); };",
+ methodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
}
TEST(HasObjectExpression, DoesNotMatchMember) {
EXPECT_TRUE(notMatches(
"class X {}; struct Z { X m; }; void f(Z z) { z.m; }",
- memberExpression(hasObjectExpression(hasType(record(hasName("X")))))));
+ memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
}
TEST(HasObjectExpression, MatchesBaseOfVariable) {
EXPECT_TRUE(matches(
"struct X { int m; }; void f(X x) { x.m; }",
- memberExpression(hasObjectExpression(hasType(record(hasName("X")))))));
+ memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(matches(
"struct X { int m; }; void f(X* x) { x->m; }",
- memberExpression(hasObjectExpression(
- hasType(pointsTo(record(hasName("X"))))))));
+ memberExpr(hasObjectExpression(
+ hasType(pointsTo(recordDecl(hasName("X"))))))));
}
TEST(HasObjectExpression,
MatchesObjectExpressionOfImplicitlyFormedMemberExpression) {
EXPECT_TRUE(matches(
"class X {}; struct S { X m; void f() { this->m; } };",
- memberExpression(hasObjectExpression(
- hasType(pointsTo(record(hasName("S"))))))));
+ memberExpr(hasObjectExpression(
+ hasType(pointsTo(recordDecl(hasName("S"))))))));
EXPECT_TRUE(matches(
"class X {}; struct S { X m; void f() { m; } };",
- memberExpression(hasObjectExpression(
- hasType(pointsTo(record(hasName("S"))))))));
+ memberExpr(hasObjectExpression(
+ hasType(pointsTo(recordDecl(hasName("S"))))))));
}
TEST(Field, DoesNotMatchNonFieldMembers) {
- EXPECT_TRUE(notMatches("class X { void m(); };", field(hasName("m"))));
- EXPECT_TRUE(notMatches("class X { class m {}; };", field(hasName("m"))));
- EXPECT_TRUE(notMatches("class X { enum { m }; };", field(hasName("m"))));
- EXPECT_TRUE(notMatches("class X { enum m {}; };", field(hasName("m"))));
+ EXPECT_TRUE(notMatches("class X { void m(); };", fieldDecl(hasName("m"))));
+ EXPECT_TRUE(notMatches("class X { class m {}; };", fieldDecl(hasName("m"))));
+ EXPECT_TRUE(notMatches("class X { enum { m }; };", fieldDecl(hasName("m"))));
+ EXPECT_TRUE(notMatches("class X { enum m {}; };", fieldDecl(hasName("m"))));
}
TEST(Field, MatchesField) {
- EXPECT_TRUE(matches("class X { int m; };", field(hasName("m"))));
+ EXPECT_TRUE(matches("class X { int m; };", fieldDecl(hasName("m"))));
}
TEST(IsConstQualified, MatchesConstInt) {
EXPECT_TRUE(matches("const int i = 42;",
- variable(hasType(isConstQualified()))));
+ varDecl(hasType(isConstQualified()))));
}
TEST(IsConstQualified, MatchesConstPointer) {
EXPECT_TRUE(matches("int i = 42; int* const p(&i);",
- variable(hasType(isConstQualified()))));
+ varDecl(hasType(isConstQualified()))));
}
TEST(IsConstQualified, MatchesThroughTypedef) {
EXPECT_TRUE(matches("typedef const int const_int; const_int i = 42;",
- variable(hasType(isConstQualified()))));
+ varDecl(hasType(isConstQualified()))));
EXPECT_TRUE(matches("typedef int* int_ptr; const int_ptr p(0);",
- variable(hasType(isConstQualified()))));
+ varDecl(hasType(isConstQualified()))));
}
TEST(IsConstQualified, DoesNotMatchInappropriately) {
EXPECT_TRUE(notMatches("typedef int nonconst_int; nonconst_int i = 42;",
- variable(hasType(isConstQualified()))));
+ varDecl(hasType(isConstQualified()))));
EXPECT_TRUE(notMatches("int const* p;",
- variable(hasType(isConstQualified()))));
+ varDecl(hasType(isConstQualified()))));
}
TEST(CastExpression, MatchesExplicitCasts) {
- EXPECT_TRUE(matches("char *p = reinterpret_cast<char *>(&p);",
- expression(castExpr())));
- EXPECT_TRUE(matches("void *p = (void *)(&p);", expression(castExpr())));
- EXPECT_TRUE(matches("char q, *p = const_cast<char *>(&q);",
- expression(castExpr())));
- EXPECT_TRUE(matches("char c = char(0);", expression(castExpr())));
+ EXPECT_TRUE(matches("char *p = reinterpret_cast<char *>(&p);",castExpr()));
+ EXPECT_TRUE(matches("void *p = (void *)(&p);", castExpr()));
+ EXPECT_TRUE(matches("char q, *p = const_cast<char *>(&q);", castExpr()));
+ EXPECT_TRUE(matches("char c = char(0);", castExpr()));
}
TEST(CastExpression, MatchesImplicitCasts) {
// This test creates an implicit cast from int to char.
- EXPECT_TRUE(matches("char c = 0;", expression(castExpr())));
+ EXPECT_TRUE(matches("char c = 0;", castExpr()));
// This test creates an implicit cast from lvalue to rvalue.
- EXPECT_TRUE(matches("char c = 0, d = c;", expression(castExpr())));
+ EXPECT_TRUE(matches("char c = 0, d = c;", castExpr()));
}
TEST(CastExpression, DoesNotMatchNonCasts) {
- EXPECT_TRUE(notMatches("char c = '0';", expression(castExpr())));
- EXPECT_TRUE(notMatches("char c, &q = c;", expression(castExpr())));
- EXPECT_TRUE(notMatches("int i = (0);", expression(castExpr())));
- EXPECT_TRUE(notMatches("int i = 0;", expression(castExpr())));
+ EXPECT_TRUE(notMatches("char c = '0';", castExpr()));
+ EXPECT_TRUE(notMatches("char c, &q = c;", castExpr()));
+ EXPECT_TRUE(notMatches("int i = (0);", castExpr()));
+ EXPECT_TRUE(notMatches("int i = 0;", castExpr()));
}
TEST(ReinterpretCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
- expression(reinterpretCast())));
+ reinterpretCastExpr()));
}
TEST(ReinterpretCast, DoesNotMatchOtherCasts) {
- EXPECT_TRUE(notMatches("char* p = (char*)(&p);",
- expression(reinterpretCast())));
+ EXPECT_TRUE(notMatches("char* p = (char*)(&p);", reinterpretCastExpr()));
EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
- expression(reinterpretCast())));
+ reinterpretCastExpr()));
EXPECT_TRUE(notMatches("void* p = static_cast<void*>(&p);",
- expression(reinterpretCast())));
+ reinterpretCastExpr()));
EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- expression(reinterpretCast())));
+ reinterpretCastExpr()));
}
TEST(FunctionalCast, MatchesSimpleCase) {
std::string foo_class = "class Foo { public: Foo(char*); };";
EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello world\"); }",
- expression(functionalCast())));
+ functionalCastExpr()));
}
TEST(FunctionalCast, DoesNotMatchOtherCasts) {
std::string FooClass = "class Foo { public: Foo(char*); };";
EXPECT_TRUE(
notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
- expression(functionalCast())));
+ functionalCastExpr()));
EXPECT_TRUE(
notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
- expression(functionalCast())));
+ functionalCastExpr()));
}
TEST(DynamicCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- expression(dynamicCast())));
+ dynamicCastExpr()));
}
TEST(StaticCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("void* p(static_cast<void*>(&p));",
- expression(staticCast())));
+ staticCastExpr()));
}
TEST(StaticCast, DoesNotMatchOtherCasts) {
- EXPECT_TRUE(notMatches("char* p = (char*)(&p);",
- expression(staticCast())));
+ EXPECT_TRUE(notMatches("char* p = (char*)(&p);", staticCastExpr()));
EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
- expression(staticCast())));
+ staticCastExpr()));
EXPECT_TRUE(notMatches("void* p = reinterpret_cast<char*>(&p);",
- expression(staticCast())));
+ staticCastExpr()));
EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- expression(staticCast())));
+ staticCastExpr()));
+}
+
+TEST(CStyleCast, MatchesSimpleCase) {
+ EXPECT_TRUE(matches("int i = (int) 2.2f;", cStyleCastExpr()));
+}
+
+TEST(CStyleCast, DoesNotMatchOtherCasts) {
+ EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);"
+ "char q, *r = const_cast<char*>(&q);"
+ "void* s = reinterpret_cast<char*>(&s);"
+ "struct B { virtual ~B() {} }; struct D : B {};"
+ "B b;"
+ "D* t = dynamic_cast<D*>(&b);",
+ cStyleCastExpr()));
}
TEST(HasDestinationType, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
- expression(
- staticCast(hasDestinationType(
- pointsTo(TypeMatcher(anything())))))));
+ staticCastExpr(hasDestinationType(
+ pointsTo(TypeMatcher(anything()))))));
}
TEST(HasImplicitDestinationType, MatchesSimpleCase) {
// This test creates an implicit const cast.
EXPECT_TRUE(matches("int x; const int i = x;",
- expression(implicitCast(
- hasImplicitDestinationType(isInteger())))));
+ implicitCastExpr(
+ hasImplicitDestinationType(isInteger()))));
// This test creates an implicit array-to-pointer cast.
EXPECT_TRUE(matches("int arr[3]; int *p = arr;",
- expression(implicitCast(hasImplicitDestinationType(
- pointsTo(TypeMatcher(anything())))))));
+ implicitCastExpr(hasImplicitDestinationType(
+ pointsTo(TypeMatcher(anything()))))));
}
TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {
// This test creates an implicit cast from int to char.
EXPECT_TRUE(notMatches("char c = 0;",
- expression(implicitCast(hasImplicitDestinationType(
- unless(anything()))))));
+ implicitCastExpr(hasImplicitDestinationType(
+ unless(anything())))));
// This test creates an implicit array-to-pointer cast.
EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
- expression(implicitCast(hasImplicitDestinationType(
- unless(anything()))))));
+ implicitCastExpr(hasImplicitDestinationType(
+ unless(anything())))));
}
TEST(ImplicitCast, MatchesSimpleCase) {
// This test creates an implicit const cast.
EXPECT_TRUE(matches("int x = 0; const int y = x;",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
// This test creates an implicit cast from int to char.
EXPECT_TRUE(matches("char c = 0;",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
// This test creates an implicit array-to-pointer cast.
EXPECT_TRUE(matches("int arr[6]; int *p = arr;",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
}
TEST(ImplicitCast, DoesNotMatchIncorrectly) {
- // This test verifies that implicitCast() matches exactly when implicit casts
+ // This test verifies that implicitCastExpr() matches exactly when implicit casts
// are present, and that it ignores explicit and paren casts.
// These two test cases have no casts.
EXPECT_TRUE(notMatches("int x = 0;",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
EXPECT_TRUE(notMatches("int x = 0, &y = x;",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
EXPECT_TRUE(notMatches("int x = 0; double d = (double) x;",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
EXPECT_TRUE(notMatches("const int *p; int *q = const_cast<int *>(p);",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
EXPECT_TRUE(notMatches("int x = (0);",
- variable(hasInitializer(implicitCast()))));
+ varDecl(hasInitializer(implicitCastExpr()))));
}
TEST(IgnoringImpCasts, MatchesImpCasts) {
@@ -2175,11 +2443,11 @@ TEST(IgnoringImpCasts, MatchesImpCasts) {
// present and its inner matcher alone does not match.
// Note that this test creates an implicit const cast.
EXPECT_TRUE(matches("int x = 0; const int y = x;",
- variable(hasInitializer(ignoringImpCasts(
- declarationReference(to(variable(hasName("x")))))))));
+ varDecl(hasInitializer(ignoringImpCasts(
+ declRefExpr(to(varDecl(hasName("x")))))))));
// This test creates an implict cast from int to char.
EXPECT_TRUE(matches("char x = 0;",
- variable(hasInitializer(ignoringImpCasts(
+ varDecl(hasInitializer(ignoringImpCasts(
integerLiteral(equals(0)))))));
}
@@ -2188,82 +2456,82 @@ TEST(IgnoringImpCasts, DoesNotMatchIncorrectly) {
// matcher does not match.
// Note that the first test creates an implicit const cast.
EXPECT_TRUE(notMatches("int x; const int y = x;",
- variable(hasInitializer(ignoringImpCasts(
+ varDecl(hasInitializer(ignoringImpCasts(
unless(anything()))))));
EXPECT_TRUE(notMatches("int x; int y = x;",
- variable(hasInitializer(ignoringImpCasts(
+ varDecl(hasInitializer(ignoringImpCasts(
unless(anything()))))));
// These tests verify that ignoringImplictCasts does not look through explicit
// casts or parentheses.
EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
- variable(hasInitializer(ignoringImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringImpCasts(
+ integerLiteral())))));
EXPECT_TRUE(notMatches("int i = (0);",
- variable(hasInitializer(ignoringImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringImpCasts(
+ integerLiteral())))));
EXPECT_TRUE(notMatches("float i = (float)0;",
- variable(hasInitializer(ignoringImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringImpCasts(
+ integerLiteral())))));
EXPECT_TRUE(notMatches("float i = float(0);",
- variable(hasInitializer(ignoringImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringImpCasts(
+ integerLiteral())))));
}
TEST(IgnoringImpCasts, MatchesWithoutImpCasts) {
// This test verifies that expressions that do not have implicit casts
// still match the inner matcher.
EXPECT_TRUE(matches("int x = 0; int &y = x;",
- variable(hasInitializer(ignoringImpCasts(
- declarationReference(to(variable(hasName("x")))))))));
+ varDecl(hasInitializer(ignoringImpCasts(
+ declRefExpr(to(varDecl(hasName("x")))))))));
}
TEST(IgnoringParenCasts, MatchesParenCasts) {
// This test checks that ignoringParenCasts matches when parentheses and/or
// casts are present and its inner matcher alone does not match.
EXPECT_TRUE(matches("int x = (0);",
- variable(hasInitializer(ignoringParenCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenCasts(
+ integerLiteral(equals(0)))))));
EXPECT_TRUE(matches("int x = (((((0)))));",
- variable(hasInitializer(ignoringParenCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenCasts(
+ integerLiteral(equals(0)))))));
// This test creates an implict cast from int to char in addition to the
// parentheses.
EXPECT_TRUE(matches("char x = (0);",
- variable(hasInitializer(ignoringParenCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenCasts(
+ integerLiteral(equals(0)))))));
EXPECT_TRUE(matches("char x = (char)0;",
- variable(hasInitializer(ignoringParenCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenCasts(
+ integerLiteral(equals(0)))))));
EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
- variable(hasInitializer(ignoringParenCasts(
+ varDecl(hasInitializer(ignoringParenCasts(
integerLiteral(equals(0)))))));
}
TEST(IgnoringParenCasts, MatchesWithoutParenCasts) {
// This test verifies that expressions that do not have any casts still match.
EXPECT_TRUE(matches("int x = 0;",
- variable(hasInitializer(ignoringParenCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenCasts(
+ integerLiteral(equals(0)))))));
}
TEST(IgnoringParenCasts, DoesNotMatchIncorrectly) {
// These tests verify that ignoringImpCasts does not match if the inner
// matcher does not match.
EXPECT_TRUE(notMatches("int x = ((0));",
- variable(hasInitializer(ignoringParenCasts(
+ varDecl(hasInitializer(ignoringParenCasts(
unless(anything()))))));
// This test creates an implicit cast from int to char in addition to the
// parentheses.
EXPECT_TRUE(notMatches("char x = ((0));",
- variable(hasInitializer(ignoringParenCasts(
+ varDecl(hasInitializer(ignoringParenCasts(
unless(anything()))))));
EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
- variable(hasInitializer(ignoringParenCasts(
+ varDecl(hasInitializer(ignoringParenCasts(
unless(anything()))))));
}
@@ -2273,23 +2541,23 @@ TEST(IgnoringParenAndImpCasts, MatchesParenImpCasts) {
// does not match.
// Note that this test creates an implicit const cast.
EXPECT_TRUE(matches("int x = 0; const int y = x;",
- variable(hasInitializer(ignoringParenImpCasts(
- declarationReference(to(variable(hasName("x")))))))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ declRefExpr(to(varDecl(hasName("x")))))))));
// This test creates an implicit cast from int to char.
EXPECT_TRUE(matches("const char x = (0);",
- variable(hasInitializer(ignoringParenImpCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ integerLiteral(equals(0)))))));
}
TEST(IgnoringParenAndImpCasts, MatchesWithoutParenImpCasts) {
// This test verifies that expressions that do not have parentheses or
// implicit casts still match.
EXPECT_TRUE(matches("int x = 0; int &y = x;",
- variable(hasInitializer(ignoringParenImpCasts(
- declarationReference(to(variable(hasName("x")))))))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ declRefExpr(to(varDecl(hasName("x")))))))));
EXPECT_TRUE(matches("int x = 0;",
- variable(hasInitializer(ignoringParenImpCasts(
- integerLiteral(equals(0)))))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ integerLiteral(equals(0)))))));
}
TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {
@@ -2297,56 +2565,56 @@ TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {
// the inner matcher does not match.
// This test creates an implicit cast.
EXPECT_TRUE(notMatches("char c = ((3));",
- variable(hasInitializer(ignoringParenImpCasts(
+ varDecl(hasInitializer(ignoringParenImpCasts(
unless(anything()))))));
// These tests verify that ignoringParenAndImplictCasts does not look
// through explicit casts.
EXPECT_TRUE(notMatches("float y = (float(0));",
- variable(hasInitializer(ignoringParenImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ integerLiteral())))));
EXPECT_TRUE(notMatches("float y = (float)0;",
- variable(hasInitializer(ignoringParenImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ integerLiteral())))));
EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
- variable(hasInitializer(ignoringParenImpCasts(
- integerLiteral())))));
+ varDecl(hasInitializer(ignoringParenImpCasts(
+ integerLiteral())))));
}
TEST(HasSourceExpression, MatchesImplicitCasts) {
EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
"void r() {string a_string; URL url = a_string; }",
- expression(implicitCast(
- hasSourceExpression(constructorCall())))));
+ implicitCastExpr(
+ hasSourceExpression(constructExpr()))));
}
TEST(HasSourceExpression, MatchesExplicitCasts) {
EXPECT_TRUE(matches("float x = static_cast<float>(42);",
- expression(explicitCast(
- hasSourceExpression(hasDescendant(
- expression(integerLiteral())))))));
+ explicitCastExpr(
+ hasSourceExpression(hasDescendant(
+ expr(integerLiteral()))))));
}
TEST(Statement, DoesNotMatchDeclarations) {
- EXPECT_TRUE(notMatches("class X {};", statement()));
+ EXPECT_TRUE(notMatches("class X {};", stmt()));
}
TEST(Statement, MatchesCompoundStatments) {
- EXPECT_TRUE(matches("void x() {}", statement()));
+ EXPECT_TRUE(matches("void x() {}", stmt()));
}
TEST(DeclarationStatement, DoesNotMatchCompoundStatements) {
- EXPECT_TRUE(notMatches("void x() {}", declarationStatement()));
+ EXPECT_TRUE(notMatches("void x() {}", declStmt()));
}
TEST(DeclarationStatement, MatchesVariableDeclarationStatements) {
- EXPECT_TRUE(matches("void x() { int a; }", declarationStatement()));
+ EXPECT_TRUE(matches("void x() { int a; }", declStmt()));
}
TEST(InitListExpression, MatchesInitListExpression) {
EXPECT_TRUE(matches("int a[] = { 1, 2 };",
initListExpr(hasType(asString("int [2]")))));
EXPECT_TRUE(matches("struct B { int x, y; }; B b = { 5, 6 };",
- initListExpr(hasType(record(hasName("B"))))));
+ initListExpr(hasType(recordDecl(hasName("B"))))));
}
TEST(UsingDeclaration, MatchesUsingDeclarations) {
@@ -2362,24 +2630,24 @@ TEST(UsingDeclaration, MatchesShadowUsingDelcarations) {
TEST(UsingDeclaration, MatchesSpecificTarget) {
EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",
usingDecl(hasAnyUsingShadowDecl(
- hasTargetDecl(function())))));
+ hasTargetDecl(functionDecl())))));
EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",
usingDecl(hasAnyUsingShadowDecl(
- hasTargetDecl(function())))));
+ hasTargetDecl(functionDecl())))));
}
TEST(UsingDeclaration, ThroughUsingDeclaration) {
EXPECT_TRUE(matches(
"namespace a { void f(); } using a::f; void g() { f(); }",
- declarationReference(throughUsingDecl(anything()))));
+ declRefExpr(throughUsingDecl(anything()))));
EXPECT_TRUE(notMatches(
"namespace a { void f(); } using a::f; void g() { a::f(); }",
- declarationReference(throughUsingDecl(anything()))));
+ declRefExpr(throughUsingDecl(anything()))));
}
TEST(SingleDecl, IsSingleDecl) {
StatementMatcher SingleDeclStmt =
- declarationStatement(hasSingleDecl(variable(hasInitializer(anything()))));
+ declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));
EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt));
EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt));
EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
@@ -2387,28 +2655,26 @@ TEST(SingleDecl, IsSingleDecl) {
}
TEST(DeclStmt, ContainsDeclaration) {
- DeclarationMatcher MatchesInit = variable(hasInitializer(anything()));
+ DeclarationMatcher MatchesInit = varDecl(hasInitializer(anything()));
EXPECT_TRUE(matches("void f() {int a = 4;}",
- declarationStatement(containsDeclaration(0,
- MatchesInit))));
+ declStmt(containsDeclaration(0, MatchesInit))));
EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
- declarationStatement(containsDeclaration(0, MatchesInit),
- containsDeclaration(1,
- MatchesInit))));
+ declStmt(containsDeclaration(0, MatchesInit),
+ containsDeclaration(1, MatchesInit))));
unsigned WrongIndex = 42;
EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
- declarationStatement(containsDeclaration(WrongIndex,
+ declStmt(containsDeclaration(WrongIndex,
MatchesInit))));
}
TEST(DeclCount, DeclCountIsCorrect) {
EXPECT_TRUE(matches("void f() {int i,j;}",
- declarationStatement(declCountIs(2))));
+ declStmt(declCountIs(2))));
EXPECT_TRUE(notMatches("void f() {int i,j; int k;}",
- declarationStatement(declCountIs(3))));
+ declStmt(declCountIs(3))));
EXPECT_TRUE(notMatches("void f() {int i,j, k, l;}",
- declarationStatement(declCountIs(3))));
+ declStmt(declCountIs(3))));
}
TEST(While, MatchesWhileLoops) {
@@ -2433,61 +2699,91 @@ TEST(SwitchCase, MatchesCase) {
EXPECT_TRUE(notMatches("void x() { switch(42) {} }", switchCase()));
}
+TEST(SwitchCase, MatchesSwitch) {
+ EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }", switchStmt()));
+ EXPECT_TRUE(matches("void x() { switch(42) { default:; } }", switchStmt()));
+ EXPECT_TRUE(matches("void x() { switch(42) default:; }", switchStmt()));
+ EXPECT_TRUE(notMatches("void x() {}", switchStmt()));
+}
+
+TEST(ExceptionHandling, SimpleCases) {
+ EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", catchStmt()));
+ EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", tryStmt()));
+ EXPECT_TRUE(notMatches("void foo() try { } catch(int X) { }", throwExpr()));
+ EXPECT_TRUE(matches("void foo() try { throw; } catch(int X) { }",
+ throwExpr()));
+ EXPECT_TRUE(matches("void foo() try { throw 5;} catch(int X) { }",
+ throwExpr()));
+}
+
TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
EXPECT_TRUE(notMatches(
"void x() { if(true) {} }",
- ifStmt(hasConditionVariableStatement(declarationStatement()))));
+ ifStmt(hasConditionVariableStatement(declStmt()))));
EXPECT_TRUE(notMatches(
"void x() { int x; if((x = 42)) {} }",
- ifStmt(hasConditionVariableStatement(declarationStatement()))));
+ ifStmt(hasConditionVariableStatement(declStmt()))));
}
TEST(HasConditionVariableStatement, MatchesConditionVariables) {
EXPECT_TRUE(matches(
"void x() { if(int* a = 0) {} }",
- ifStmt(hasConditionVariableStatement(declarationStatement()))));
+ ifStmt(hasConditionVariableStatement(declStmt()))));
}
TEST(ForEach, BindsOneNode) {
EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
- record(hasName("C"), forEach(field(hasName("x")).bind("x"))),
- new VerifyIdIsBoundToDecl<FieldDecl>("x", 1)));
+ recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),
+ new VerifyIdIsBoundTo<FieldDecl>("x", 1)));
}
TEST(ForEach, BindsMultipleNodes) {
EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",
- record(hasName("C"), forEach(field().bind("f"))),
- new VerifyIdIsBoundToDecl<FieldDecl>("f", 3)));
+ recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),
+ new VerifyIdIsBoundTo<FieldDecl>("f", 3)));
}
TEST(ForEach, BindsRecursiveCombinations) {
EXPECT_TRUE(matchAndVerifyResultTrue(
"class C { class D { int x; int y; }; class E { int y; int z; }; };",
- record(hasName("C"), forEach(record(forEach(field().bind("f"))))),
- new VerifyIdIsBoundToDecl<FieldDecl>("f", 4)));
+ recordDecl(hasName("C"),
+ forEach(recordDecl(forEach(fieldDecl().bind("f"))))),
+ new VerifyIdIsBoundTo<FieldDecl>("f", 4)));
}
TEST(ForEachDescendant, BindsOneNode) {
EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",
- record(hasName("C"), forEachDescendant(field(hasName("x")).bind("x"))),
- new VerifyIdIsBoundToDecl<FieldDecl>("x", 1)));
+ recordDecl(hasName("C"),
+ forEachDescendant(fieldDecl(hasName("x")).bind("x"))),
+ new VerifyIdIsBoundTo<FieldDecl>("x", 1)));
}
TEST(ForEachDescendant, BindsMultipleNodes) {
EXPECT_TRUE(matchAndVerifyResultTrue(
"class C { class D { int x; int y; }; "
" class E { class F { int y; int z; }; }; };",
- record(hasName("C"), forEachDescendant(field().bind("f"))),
- new VerifyIdIsBoundToDecl<FieldDecl>("f", 4)));
+ recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),
+ new VerifyIdIsBoundTo<FieldDecl>("f", 4)));
}
TEST(ForEachDescendant, BindsRecursiveCombinations) {
EXPECT_TRUE(matchAndVerifyResultTrue(
"class C { class D { "
" class E { class F { class G { int y; int z; }; }; }; }; };",
- record(hasName("C"), forEachDescendant(record(
- forEachDescendant(field().bind("f"))))),
- new VerifyIdIsBoundToDecl<FieldDecl>("f", 8)));
+ recordDecl(hasName("C"), forEachDescendant(recordDecl(
+ forEachDescendant(fieldDecl().bind("f"))))),
+ new VerifyIdIsBoundTo<FieldDecl>("f", 8)));
+}
+
+TEST(ForEachDescendant, BindsCorrectNodes) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { void f(); int i; };",
+ recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
+ new VerifyIdIsBoundTo<FieldDecl>("decl", 1)));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { void f() {} int i; };",
+ recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
+ new VerifyIdIsBoundTo<FunctionDecl>("decl", 1)));
}
@@ -2497,18 +2793,18 @@ TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> class X {}; class A {}; X<A> x;",
- record(hasName("::X"), isTemplateInstantiation())));
+ recordDecl(hasName("::X"), isTemplateInstantiation())));
EXPECT_TRUE(matches(
"template <typename T> class X { T t; }; class A {}; X<A> x;",
- record(isTemplateInstantiation(), hasDescendant(
- field(hasType(record(hasName("A"))))))));
+ recordDecl(isTemplateInstantiation(), hasDescendant(
+ fieldDecl(hasType(recordDecl(hasName("A"))))))));
}
TEST(IsTemplateInstantiation, MatchesImplicitFunctionTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> void f(T t) {} class A {}; void g() { f(A()); }",
- function(hasParameter(0, hasType(record(hasName("A")))),
+ functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
isTemplateInstantiation())));
}
@@ -2516,8 +2812,8 @@ TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> class X { T t; }; class A {};"
"template class X<A>;",
- record(isTemplateInstantiation(), hasDescendant(
- field(hasType(record(hasName("A"))))))));
+ recordDecl(isTemplateInstantiation(), hasDescendant(
+ fieldDecl(hasType(recordDecl(hasName("A"))))))));
}
TEST(IsTemplateInstantiation,
@@ -2525,7 +2821,7 @@ TEST(IsTemplateInstantiation,
EXPECT_TRUE(matches(
"template <typename T> class X {};"
"template <typename T> class X<T*> {}; class A {}; X<A*> x;",
- record(hasName("::X"), isTemplateInstantiation())));
+ recordDecl(hasName("::X"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation,
@@ -2536,7 +2832,7 @@ TEST(IsTemplateInstantiation,
" template <typename U> class Y { U u; };"
" Y<A> y;"
"};",
- record(hasName("::X::Y"), isTemplateInstantiation())));
+ recordDecl(hasName("::X::Y"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
@@ -2549,20 +2845,557 @@ TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
" template <typename U> class Y { U u; };"
" Y<T> y;"
"}; X<A> x;",
- record(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
+ recordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
}
TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {}; class A {};"
"template <> class X<A> {}; X<A> x;",
- record(hasName("::X"), isTemplateInstantiation())));
+ recordDecl(hasName("::X"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
EXPECT_TRUE(notMatches(
"class A {}; class Y { A a; };",
- record(isTemplateInstantiation())));
+ recordDecl(isTemplateInstantiation())));
+}
+
+TEST(IsExplicitTemplateSpecialization,
+ DoesNotMatchPrimaryTemplate) {
+ EXPECT_TRUE(notMatches(
+ "template <typename T> class X {};",
+ recordDecl(isExplicitTemplateSpecialization())));
+ EXPECT_TRUE(notMatches(
+ "template <typename T> void f(T t);",
+ functionDecl(isExplicitTemplateSpecialization())));
+}
+
+TEST(IsExplicitTemplateSpecialization,
+ DoesNotMatchExplicitTemplateInstantiations) {
+ EXPECT_TRUE(notMatches(
+ "template <typename T> class X {};"
+ "template class X<int>; extern template class X<long>;",
+ recordDecl(isExplicitTemplateSpecialization())));
+ EXPECT_TRUE(notMatches(
+ "template <typename T> void f(T t) {}"
+ "template void f(int t); extern template void f(long t);",
+ functionDecl(isExplicitTemplateSpecialization())));
+}
+
+TEST(IsExplicitTemplateSpecialization,
+ DoesNotMatchImplicitTemplateInstantiations) {
+ EXPECT_TRUE(notMatches(
+ "template <typename T> class X {}; X<int> x;",
+ recordDecl(isExplicitTemplateSpecialization())));
+ EXPECT_TRUE(notMatches(
+ "template <typename T> void f(T t); void g() { f(10); }",
+ functionDecl(isExplicitTemplateSpecialization())));
+}
+
+TEST(IsExplicitTemplateSpecialization,
+ MatchesExplicitTemplateSpecializations) {
+ EXPECT_TRUE(matches(
+ "template <typename T> class X {};"
+ "template<> class X<int> {};",
+ recordDecl(isExplicitTemplateSpecialization())));
+ EXPECT_TRUE(matches(
+ "template <typename T> void f(T t) {}"
+ "template<> void f(int t) {}",
+ functionDecl(isExplicitTemplateSpecialization())));
+}
+
+TEST(HasAncenstor, MatchesDeclarationAncestors) {
+ EXPECT_TRUE(matches(
+ "class A { class B { class C {}; }; };",
+ recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));
+}
+
+TEST(HasAncenstor, FailsIfNoAncestorMatches) {
+ EXPECT_TRUE(notMatches(
+ "class A { class B { class C {}; }; };",
+ recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));
+}
+
+TEST(HasAncestor, MatchesDeclarationsThatGetVisitedLater) {
+ EXPECT_TRUE(matches(
+ "class A { class B { void f() { C c; } class C {}; }; };",
+ varDecl(hasName("c"), hasType(recordDecl(hasName("C"),
+ hasAncestor(recordDecl(hasName("A"))))))));
+}
+
+TEST(HasAncenstor, MatchesStatementAncestors) {
+ EXPECT_TRUE(matches(
+ "void f() { if (true) { while (false) { 42; } } }",
+ integerLiteral(equals(42), hasAncestor(ifStmt()))));
+}
+
+TEST(HasAncestor, DrillsThroughDifferentHierarchies) {
+ EXPECT_TRUE(matches(
+ "void f() { if (true) { int x = 42; } }",
+ integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));
+}
+
+TEST(HasAncestor, BindsRecursiveCombinations) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { class D { class E { class F { int y; }; }; }; };",
+ fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),
+ new VerifyIdIsBoundTo<CXXRecordDecl>("r", 1)));
+}
+
+TEST(HasAncestor, BindsCombinationsWithHasDescendant) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class C { class D { class E { class F { int y; }; }; }; };",
+ fieldDecl(hasAncestor(
+ decl(
+ hasDescendant(recordDecl(isDefinition(),
+ hasAncestor(recordDecl())))
+ ).bind("d")
+ )),
+ new VerifyIdIsBoundTo<CXXRecordDecl>("d", "E")));
+}
+
+TEST(HasAncestor, MatchesInTemplateInstantiations) {
+ EXPECT_TRUE(matches(
+ "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
+ "A<int>::B::C a;",
+ fieldDecl(hasType(asString("int")),
+ hasAncestor(recordDecl(hasName("A"))))));
+}
+
+TEST(HasAncestor, MatchesInImplicitCode) {
+ EXPECT_TRUE(matches(
+ "struct X {}; struct A { A() {} X x; };",
+ constructorDecl(
+ hasAnyConstructorInitializer(withInitializer(expr(
+ 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")));
+}
+
+TEST(TypeMatching, MatchesArrayTypes) {
+ EXPECT_TRUE(matches("int a[] = {2,3};", arrayType()));
+ EXPECT_TRUE(matches("int a[42];", arrayType()));
+ EXPECT_TRUE(matches("void f(int b) { int a[b]; }", arrayType()));
+
+ EXPECT_TRUE(notMatches("struct A {}; A a[7];",
+ arrayType(hasElementType(builtinType()))));
+
+ EXPECT_TRUE(matches(
+ "int const a[] = { 2, 3 };",
+ qualType(arrayType(hasElementType(builtinType())))));
+ EXPECT_TRUE(matches(
+ "int const a[] = { 2, 3 };",
+ qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
+ EXPECT_TRUE(matches(
+ "typedef const int T; T x[] = { 1, 2 };",
+ qualType(isConstQualified(), arrayType())));
+
+ EXPECT_TRUE(notMatches(
+ "int a[] = { 2, 3 };",
+ qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
+ EXPECT_TRUE(notMatches(
+ "int a[] = { 2, 3 };",
+ qualType(arrayType(hasElementType(isConstQualified(), builtinType())))));
+ EXPECT_TRUE(notMatches(
+ "int const a[] = { 2, 3 };",
+ qualType(arrayType(hasElementType(builtinType())),
+ unless(isConstQualified()))));
+
+ EXPECT_TRUE(matches("int a[2];",
+ constantArrayType(hasElementType(builtinType()))));
+ EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger())));
+}
+
+TEST(TypeMatching, MatchesComplexTypes) {
+ EXPECT_TRUE(matches("_Complex float f;", complexType()));
+ EXPECT_TRUE(matches(
+ "_Complex float f;",
+ complexType(hasElementType(builtinType()))));
+ EXPECT_TRUE(notMatches(
+ "_Complex float f;",
+ complexType(hasElementType(isInteger()))));
+}
+
+TEST(TypeMatching, MatchesConstantArrayTypes) {
+ EXPECT_TRUE(matches("int a[2];", constantArrayType()));
+ EXPECT_TRUE(notMatches(
+ "void f() { int a[] = { 2, 3 }; int b[a[0]]; }",
+ constantArrayType(hasElementType(builtinType()))));
+
+ EXPECT_TRUE(matches("int a[42];", constantArrayType(hasSize(42))));
+ EXPECT_TRUE(matches("int b[2*21];", constantArrayType(hasSize(42))));
+ EXPECT_TRUE(notMatches("int c[41], d[43];", constantArrayType(hasSize(42))));
+}
+
+TEST(TypeMatching, MatchesDependentSizedArrayTypes) {
+ EXPECT_TRUE(matches(
+ "template <typename T, int Size> class array { T data[Size]; };",
+ dependentSizedArrayType()));
+ EXPECT_TRUE(notMatches(
+ "int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }",
+ dependentSizedArrayType()));
+}
+
+TEST(TypeMatching, MatchesIncompleteArrayType) {
+ EXPECT_TRUE(matches("int a[] = { 2, 3 };", incompleteArrayType()));
+ EXPECT_TRUE(matches("void f(int a[]) {}", incompleteArrayType()));
+
+ EXPECT_TRUE(notMatches("int a[42]; void f() { int b[a[0]]; }",
+ incompleteArrayType()));
+}
+
+TEST(TypeMatching, MatchesVariableArrayType) {
+ EXPECT_TRUE(matches("void f(int b) { int a[b]; }", variableArrayType()));
+ EXPECT_TRUE(notMatches("int a[] = {2, 3}; int b[42];", variableArrayType()));
+
+ EXPECT_TRUE(matches(
+ "void f(int b) { int a[b]; }",
+ variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
+ varDecl(hasName("b")))))))));
+}
+
+TEST(TypeMatching, MatchesAtomicTypes) {
+ EXPECT_TRUE(matches("_Atomic(int) i;", atomicType()));
+
+ EXPECT_TRUE(matches("_Atomic(int) i;",
+ atomicType(hasValueType(isInteger()))));
+ EXPECT_TRUE(notMatches("_Atomic(float) f;",
+ atomicType(hasValueType(isInteger()))));
+}
+
+TEST(TypeMatching, MatchesAutoTypes) {
+ EXPECT_TRUE(matches("auto i = 2;", autoType()));
+ EXPECT_TRUE(matches("int v[] = { 2, 3 }; void f() { for (int i : v) {} }",
+ autoType()));
+
+ EXPECT_TRUE(matches("auto a = 1;",
+ autoType(hasDeducedType(isInteger()))));
+ EXPECT_TRUE(notMatches("auto b = 2.0;",
+ autoType(hasDeducedType(isInteger()))));
+}
+
+TEST(TypeMatching, MatchesFunctionTypes) {
+ EXPECT_TRUE(matches("int (*f)(int);", functionType()));
+ EXPECT_TRUE(matches("void f(int i) {}", functionType()));
+}
+
+TEST(TypeMatching, PointerTypes) {
+ // FIXME: Reactive when these tests can be more specific (not matching
+ // implicit code on certain platforms), likely when we have hasDescendant for
+ // Types/TypeLocs.
+ //EXPECT_TRUE(matchAndVerifyResultTrue(
+ // "int* a;",
+ // pointerTypeLoc(pointeeLoc(typeLoc().bind("loc"))),
+ // new VerifyIdIsBoundTo<TypeLoc>("loc", 1)));
+ //EXPECT_TRUE(matchAndVerifyResultTrue(
+ // "int* a;",
+ // pointerTypeLoc().bind("loc"),
+ // new VerifyIdIsBoundTo<TypeLoc>("loc", 1)));
+ EXPECT_TRUE(matches(
+ "int** a;",
+ pointerTypeLoc(pointeeLoc(loc(qualType())))));
+ EXPECT_TRUE(matches(
+ "int** a;",
+ loc(pointerType(pointee(pointerType())))));
+ EXPECT_TRUE(matches(
+ "int* b; int* * const a = &b;",
+ loc(qualType(isConstQualified(), pointerType()))));
+
+ std::string Fragment = "struct A { int i; }; int A::* ptr = &A::i;";
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
+ hasType(blockPointerType()))));
+ EXPECT_TRUE(matches(Fragment, varDecl(hasName("ptr"),
+ hasType(memberPointerType()))));
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
+ hasType(pointerType()))));
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
+ hasType(referenceType()))));
+
+ Fragment = "int *ptr;";
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
+ hasType(blockPointerType()))));
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
+ hasType(memberPointerType()))));
+ EXPECT_TRUE(matches(Fragment, varDecl(hasName("ptr"),
+ hasType(pointerType()))));
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
+ hasType(referenceType()))));
+
+ Fragment = "int a; int &ref = a;";
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
+ hasType(blockPointerType()))));
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
+ hasType(memberPointerType()))));
+ EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ref"),
+ hasType(pointerType()))));
+ EXPECT_TRUE(matches(Fragment, varDecl(hasName("ref"),
+ hasType(referenceType()))));
+}
+
+TEST(TypeMatching, PointeeTypes) {
+ EXPECT_TRUE(matches("int b; int &a = b;",
+ referenceType(pointee(builtinType()))));
+ EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));
+
+ EXPECT_TRUE(matches("int *a;",
+ pointerTypeLoc(pointeeLoc(loc(builtinType())))));
+
+ EXPECT_TRUE(matches(
+ "int const *A;",
+ pointerType(pointee(isConstQualified(), builtinType()))));
+ EXPECT_TRUE(notMatches(
+ "int *A;",
+ pointerType(pointee(isConstQualified(), builtinType()))));
+}
+
+TEST(TypeMatching, MatchesPointersToConstTypes) {
+ EXPECT_TRUE(matches("int b; int * const a = &b;",
+ loc(pointerType())));
+ EXPECT_TRUE(matches("int b; int * const a = &b;",
+ pointerTypeLoc()));
+ EXPECT_TRUE(matches(
+ "int b; const int * a = &b;",
+ pointerTypeLoc(pointeeLoc(builtinTypeLoc()))));
+ EXPECT_TRUE(matches(
+ "int b; const int * a = &b;",
+ pointerType(pointee(builtinType()))));
+}
+
+TEST(TypeMatching, MatchesTypedefTypes) {
+ EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"),
+ hasType(typedefType()))));
+
+ EXPECT_TRUE(matches("typedef int X; X a;",
+ varDecl(hasName("a"),
+ hasType(typedefType(hasDecl(decl()))))));
+}
+
+TEST(NNS, MatchesNestedNameSpecifiers) {
+ EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;",
+ nestedNameSpecifier()));
+ EXPECT_TRUE(matches("template <typename T> class A { typename T::B b; };",
+ nestedNameSpecifier()));
+ EXPECT_TRUE(matches("struct A { void f(); }; void A::f() {}",
+ nestedNameSpecifier()));
+
+ EXPECT_TRUE(matches(
+ "struct A { static void f() {} }; void g() { A::f(); }",
+ nestedNameSpecifier()));
+ EXPECT_TRUE(notMatches(
+ "struct A { static void f() {} }; void g(A* a) { a->f(); }",
+ nestedNameSpecifier()));
+}
+
+TEST(NullStatement, SimpleCases) {
+ EXPECT_TRUE(matches("void f() {int i;;}", nullStmt()));
+ EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt()));
+}
+
+TEST(NNS, MatchesTypes) {
+ NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
+ specifiesType(hasDeclaration(recordDecl(hasName("A")))));
+ EXPECT_TRUE(matches("struct A { struct B {}; }; A::B b;", Matcher));
+ EXPECT_TRUE(matches("struct A { struct B { struct C {}; }; }; A::B::C c;",
+ Matcher));
+ EXPECT_TRUE(notMatches("namespace A { struct B {}; } A::B b;", Matcher));
+}
+
+TEST(NNS, MatchesNamespaceDecls) {
+ NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
+ specifiesNamespace(hasName("ns")));
+ EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;", Matcher));
+ EXPECT_TRUE(notMatches("namespace xx { struct A {}; } xx::A a;", Matcher));
+ EXPECT_TRUE(notMatches("struct ns { struct A {}; }; ns::A a;", Matcher));
+}
+
+TEST(NNS, BindsNestedNameSpecifiers) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
+ nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
+ new VerifyIdIsBoundTo<NestedNameSpecifier>("nns", "ns::struct E::")));
+}
+
+TEST(NNS, BindsNestedNameSpecifierLocs) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "namespace ns { struct B {}; } ns::B b;",
+ loc(nestedNameSpecifier()).bind("loc"),
+ new VerifyIdIsBoundTo<NestedNameSpecifierLoc>("loc", 1)));
+}
+
+TEST(NNS, MatchesNestedNameSpecifierPrefixes) {
+ EXPECT_TRUE(matches(
+ "struct A { struct B { struct C {}; }; }; A::B::C c;",
+ nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A"))))));
+ EXPECT_TRUE(matches(
+ "struct A { struct B { struct C {}; }; }; A::B::C c;",
+ nestedNameSpecifierLoc(hasPrefix(
+ specifiesTypeLoc(loc(qualType(asString("struct A"))))))));
+}
+
+TEST(NNS, DescendantsOfNestedNameSpecifiers) {
+ std::string Fragment =
+ "namespace a { struct A { struct B { struct C {}; }; }; };"
+ "void f() { a::A::B::C c; }";
+ EXPECT_TRUE(matches(
+ Fragment,
+ nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
+ hasDescendant(nestedNameSpecifier(
+ specifiesNamespace(hasName("a")))))));
+ EXPECT_TRUE(notMatches(
+ Fragment,
+ nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
+ has(nestedNameSpecifier(
+ specifiesNamespace(hasName("a")))))));
+ EXPECT_TRUE(matches(
+ Fragment,
+ nestedNameSpecifier(specifiesType(asString("struct a::A")),
+ has(nestedNameSpecifier(
+ specifiesNamespace(hasName("a")))))));
+
+ // Not really useful because a NestedNameSpecifier can af at most one child,
+ // but to complete the interface.
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ Fragment,
+ nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
+ forEach(nestedNameSpecifier().bind("x"))),
+ new VerifyIdIsBoundTo<NestedNameSpecifier>("x", 1)));
+}
+
+TEST(NNS, NestedNameSpecifiersAsDescendants) {
+ std::string Fragment =
+ "namespace a { struct A { struct B { struct C {}; }; }; };"
+ "void f() { a::A::B::C c; }";
+ EXPECT_TRUE(matches(
+ Fragment,
+ decl(hasDescendant(nestedNameSpecifier(specifiesType(
+ asString("struct a::A")))))));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ Fragment,
+ functionDecl(hasName("f"),
+ forEachDescendant(nestedNameSpecifier().bind("x"))),
+ // Nested names: a, a::A and a::A::B.
+ new VerifyIdIsBoundTo<NestedNameSpecifier>("x", 3)));
+}
+
+TEST(NNSLoc, DescendantsOfNestedNameSpecifierLocs) {
+ std::string Fragment =
+ "namespace a { struct A { struct B { struct C {}; }; }; };"
+ "void f() { a::A::B::C c; }";
+ EXPECT_TRUE(matches(
+ Fragment,
+ nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
+ hasDescendant(loc(nestedNameSpecifier(
+ specifiesNamespace(hasName("a"))))))));
+ EXPECT_TRUE(notMatches(
+ Fragment,
+ nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
+ has(loc(nestedNameSpecifier(
+ specifiesNamespace(hasName("a"))))))));
+ EXPECT_TRUE(matches(
+ Fragment,
+ nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
+ has(loc(nestedNameSpecifier(
+ specifiesNamespace(hasName("a"))))))));
+
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ Fragment,
+ nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
+ forEach(nestedNameSpecifierLoc().bind("x"))),
+ new VerifyIdIsBoundTo<NestedNameSpecifierLoc>("x", 1)));
+}
+
+TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) {
+ std::string Fragment =
+ "namespace a { struct A { struct B { struct C {}; }; }; };"
+ "void f() { a::A::B::C c; }";
+ EXPECT_TRUE(matches(
+ Fragment,
+ decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
+ asString("struct a::A"))))))));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ Fragment,
+ functionDecl(hasName("f"),
+ forEachDescendant(nestedNameSpecifierLoc().bind("x"))),
+ // Nested names: a, a::A and a::A::B.
+ new VerifyIdIsBoundTo<NestedNameSpecifierLoc>("x", 3)));
+}
+
+template <typename T>
+class VerifyRecursiveMatch : public BoundNodesCallback {
+public:
+ explicit VerifyRecursiveMatch(StringRef Id,
+ const internal::Matcher<T> &InnerMatcher)
+ : Id(Id), InnerMatcher(InnerMatcher) {}
+
+ virtual bool run(const BoundNodes *Nodes) {
+ return false;
+ }
+
+ virtual bool run(const BoundNodes *Nodes, ASTContext *Context) {
+ const T *Node = Nodes->getNodeAs<T>(Id);
+ bool Found = false;
+ MatchFinder Finder;
+ Finder.addMatcher(InnerMatcher, new VerifyMatch(0, &Found));
+ Finder.findAll(*Node, *Context);
+ return Found;
+ }
+private:
+ std::string Id;
+ internal::Matcher<T> InnerMatcher;
+};
+
+TEST(MatchFinder, CanMatchDeclarationsRecursively) {
+ EXPECT_TRUE(matchAndVerifyResultTrue("class X { class Y {}; };",
+ recordDecl(hasName("::X")).bind("X"),
+ new VerifyRecursiveMatch<clang::Decl>("X", recordDecl(hasName("X::Y")))));
+ EXPECT_TRUE(matchAndVerifyResultFalse("class X { class Y {}; };",
+ recordDecl(hasName("::X")).bind("X"),
+ new VerifyRecursiveMatch<clang::Decl>("X", recordDecl(hasName("X::Z")))));
+}
+
+TEST(MatchFinder, CanMatchStatementsRecursively) {
+ EXPECT_TRUE(matchAndVerifyResultTrue("void f() { if (1) { for (;;) { } } }",
+ ifStmt().bind("if"),
+ new VerifyRecursiveMatch<clang::Stmt>("if", forStmt())));
+ EXPECT_TRUE(matchAndVerifyResultFalse("void f() { if (1) { for (;;) { } } }",
+ ifStmt().bind("if"),
+ new VerifyRecursiveMatch<clang::Stmt>("if", declStmt())));
+}
+
+class VerifyStartOfTranslationUnit : public MatchFinder::MatchCallback {
+public:
+ VerifyStartOfTranslationUnit() : Called(false) {}
+ virtual void run(const MatchFinder::MatchResult &Result) {
+ EXPECT_TRUE(Called);
+ }
+ virtual void onStartOfTranslationUnit() {
+ Called = true;
+ }
+ bool Called;
+};
+
+TEST(MatchFinder, InterceptsStartOfTranslationUnit) {
+ MatchFinder Finder;
+ VerifyStartOfTranslationUnit VerifyCallback;
+ Finder.addMatcher(decl(), &VerifyCallback);
+ OwningPtr<FrontendActionFactory> Factory(newFrontendActionFactory(&Finder));
+ ASSERT_TRUE(tooling::runToolOnCode(Factory->create(), "int x;"));
+ EXPECT_TRUE(VerifyCallback.Called);
}
} // end namespace ast_matchers
OpenPOWER on IntegriCloud