summaryrefslogtreecommitdiffstats
path: root/unittests/ASTMatchers/ASTMatchersTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ASTMatchers/ASTMatchersTest.cpp')
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp765
1 files changed, 529 insertions, 236 deletions
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index 8ef3f15..cd18df8 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -36,7 +36,7 @@ TEST(HasNameDeathTest, DiesOnEmptyPattern) {
TEST(IsDerivedFromDeathTest, DiesOnEmptyBaseName) {
ASSERT_DEBUG_DEATH({
- DeclarationMatcher IsDerivedFromEmpty = recordDecl(isDerivedFrom(""));
+ DeclarationMatcher IsDerivedFromEmpty = cxxRecordDecl(isDerivedFrom(""));
EXPECT_TRUE(notMatches("class X {};", IsDerivedFromEmpty));
}, "");
}
@@ -122,7 +122,7 @@ TEST(DeclarationMatcher, MatchClass) {
}
TEST(DeclarationMatcher, ClassIsDerived) {
- DeclarationMatcher IsDerivedFromX = recordDecl(isDerivedFrom("X"));
+ DeclarationMatcher IsDerivedFromX = cxxRecordDecl(isDerivedFrom("X"));
EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX));
EXPECT_TRUE(notMatches("class X {};", IsDerivedFromX));
@@ -130,7 +130,7 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
EXPECT_TRUE(notMatches("", IsDerivedFromX));
- DeclarationMatcher IsAX = recordDecl(isSameOrDerivedFrom("X"));
+ DeclarationMatcher IsAX = cxxRecordDecl(isSameOrDerivedFrom("X"));
EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsAX));
EXPECT_TRUE(matches("class X {};", IsAX));
@@ -139,7 +139,7 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(notMatches("", IsAX));
DeclarationMatcher ZIsDerivedFromX =
- recordDecl(hasName("Z"), isDerivedFrom("X"));
+ cxxRecordDecl(hasName("Z"), isDerivedFrom("X"));
EXPECT_TRUE(
matches("class X {}; class Y : public X {}; class Z : public Y {};",
ZIsDerivedFromX));
@@ -258,14 +258,14 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(
notMatches("template<int> struct X;"
"template<int i> struct X : public X<i-1> {};",
- recordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
+ cxxRecordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
EXPECT_TRUE(matches(
"struct A {};"
"template<int> struct X;"
"template<int i> struct X : public X<i-1> {};"
"template<> struct X<0> : public A {};"
"struct B : public X<42> {};",
- recordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
+ cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
// FIXME: Once we have better matchers for template type matching,
// get rid of the Variable(...) matching and match the right template
@@ -282,15 +282,15 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(matches(
RecursiveTemplateOneParameter,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
EXPECT_TRUE(notMatches(
RecursiveTemplateOneParameter,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
RecursiveTemplateOneParameter,
varDecl(hasName("z_char"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"),
isDerivedFrom("Base2")))))));
const char *RecursiveTemplateTwoParameters =
@@ -307,39 +307,39 @@ TEST(DeclarationMatcher, ClassIsDerived) {
EXPECT_TRUE(matches(
RecursiveTemplateTwoParameters,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
EXPECT_TRUE(notMatches(
RecursiveTemplateTwoParameters,
varDecl(hasName("z_float"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base2")))))));
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
RecursiveTemplateTwoParameters,
varDecl(hasName("z_char"),
- hasInitializer(hasType(recordDecl(isDerivedFrom("Base1"),
+ hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"),
isDerivedFrom("Base2")))))));
EXPECT_TRUE(matches(
"namespace ns { class X {}; class Y : public X {}; }",
- recordDecl(isDerivedFrom("::ns::X"))));
+ cxxRecordDecl(isDerivedFrom("::ns::X"))));
EXPECT_TRUE(notMatches(
"class X {}; class Y : public X {};",
- recordDecl(isDerivedFrom("::ns::X"))));
+ cxxRecordDecl(isDerivedFrom("::ns::X"))));
EXPECT_TRUE(matches(
"class X {}; class Y : public X {};",
- recordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
+ cxxRecordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
EXPECT_TRUE(matches(
"template<typename T> class X {};"
"template<typename T> using Z = X<T>;"
"template <typename T> class Y : Z<T> {};",
- recordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
+ cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
}
TEST(DeclarationMatcher, hasMethod) {
EXPECT_TRUE(matches("class A { void func(); };",
- recordDecl(hasMethod(hasName("func")))));
+ cxxRecordDecl(hasMethod(hasName("func")))));
EXPECT_TRUE(notMatches("class A { void func(); };",
- recordDecl(hasMethod(isPublic()))));
+ cxxRecordDecl(hasMethod(isPublic()))));
}
TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
@@ -349,7 +349,7 @@ TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {
"};"
"template <typename T> struct B : A<T>::template F<T> {};"
"B<int> b;",
- recordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
+ cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
}
TEST(DeclarationMatcher, hasDeclContext) {
@@ -453,11 +453,20 @@ TEST(AllOf, AllOverloadsWork) {
hasArgument(3, integerLiteral(equals(4)))))));
}
-TEST(DeclarationMatcher, MatchAnyOf) {
- DeclarationMatcher YOrZDerivedFromX =
- recordDecl(anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
+TEST(ConstructVariadic, MismatchedTypes_Regression) {
EXPECT_TRUE(
- matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
+ matches("const int a = 0;",
+ internal::DynTypedMatcher::constructVariadic(
+ internal::DynTypedMatcher::VO_AnyOf,
+ ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>(),
+ {isConstQualified(), arrayType()})
+ .convertTo<QualType>()));
+}
+
+TEST(DeclarationMatcher, MatchAnyOf) {
+ DeclarationMatcher YOrZDerivedFromX = cxxRecordDecl(
+ anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
+ EXPECT_TRUE(matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
EXPECT_TRUE(
notMatches("class X {}; class W : public X {};", YOrZDerivedFromX));
@@ -485,7 +494,7 @@ TEST(DeclarationMatcher, MatchAnyOf) {
EXPECT_TRUE(
matches("void f() try { } catch (int) { } catch (...) { }",
- catchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
+ cxxCatchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
}
TEST(DeclarationMatcher, MatchHas) {
@@ -592,7 +601,7 @@ TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
TEST(DeclarationMatcher, MatchNot) {
DeclarationMatcher NotClassX =
- recordDecl(
+ cxxRecordDecl(
isDerivedFrom("Y"),
unless(hasName("X")));
EXPECT_TRUE(notMatches("", NotClassX));
@@ -709,11 +718,11 @@ TEST(DeclarationMatcher, HasAttr) {
TEST(DeclarationMatcher, MatchCudaDecl) {
EXPECT_TRUE(matchesWithCuda("__global__ void f() { }"
"void g() { f<<<1, 2>>>(); }",
- CUDAKernelCallExpr()));
+ cudaKernelCallExpr()));
EXPECT_TRUE(matchesWithCuda("__attribute__((device)) void f() {}",
hasAttr(clang::attr::CUDADevice)));
EXPECT_TRUE(notMatchesWithCuda("void f() {}",
- CUDAKernelCallExpr()));
+ cudaKernelCallExpr()));
EXPECT_FALSE(notMatchesWithCuda("__attribute__((global)) void f() {}",
hasAttr(clang::attr::CUDAGlobal)));
}
@@ -898,7 +907,8 @@ TEST(TypeMatcher, MatchesClassType) {
EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));
EXPECT_TRUE(notMatches("class A {};", TypeA));
- TypeMatcher TypeDerivedFromA = hasDeclaration(recordDecl(isDerivedFrom("A")));
+ TypeMatcher TypeDerivedFromA =
+ hasDeclaration(cxxRecordDecl(isDerivedFrom("A")));
EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",
TypeDerivedFromA));
@@ -909,6 +919,57 @@ TEST(TypeMatcher, MatchesClassType) {
EXPECT_TRUE(
matches("class A { public: A *a; class B {}; };", TypeAHasClassB));
+
+ EXPECT_TRUE(matchesC("struct S {}; void f(void) { struct S s; }",
+ varDecl(hasType(namedDecl(hasName("S"))))));
+}
+
+TEST(TypeMatcher, MatchesDeclTypes) {
+ // TypedefType -> TypedefNameDecl
+ EXPECT_TRUE(matches("typedef int I; void f(I i);",
+ parmVarDecl(hasType(namedDecl(hasName("I"))))));
+ // ObjCObjectPointerType
+ EXPECT_TRUE(matchesObjC("@interface Foo @end void f(Foo *f);",
+ parmVarDecl(hasType(objcObjectPointerType()))));
+ // ObjCObjectPointerType -> ObjCInterfaceType -> ObjCInterfaceDecl
+ EXPECT_TRUE(matchesObjC(
+ "@interface Foo @end void f(Foo *f);",
+ parmVarDecl(hasType(pointsTo(objcInterfaceDecl(hasName("Foo")))))));
+ // TemplateTypeParmType
+ EXPECT_TRUE(matches("template <typename T> void f(T t);",
+ parmVarDecl(hasType(templateTypeParmType()))));
+ // TemplateTypeParmType -> TemplateTypeParmDecl
+ EXPECT_TRUE(matches("template <typename T> void f(T t);",
+ parmVarDecl(hasType(namedDecl(hasName("T"))))));
+ // InjectedClassNameType
+ EXPECT_TRUE(matches("template <typename T> struct S {"
+ " void f(S s);"
+ "};",
+ parmVarDecl(hasType(injectedClassNameType()))));
+ EXPECT_TRUE(notMatches("template <typename T> struct S {"
+ " void g(S<T> s);"
+ "};",
+ parmVarDecl(hasType(injectedClassNameType()))));
+ // InjectedClassNameType -> CXXRecordDecl
+ EXPECT_TRUE(matches("template <typename T> struct S {"
+ " void f(S s);"
+ "};",
+ parmVarDecl(hasType(namedDecl(hasName("S"))))));
+
+ static const char Using[] = "template <typename T>"
+ "struct Base {"
+ " typedef T Foo;"
+ "};"
+ ""
+ "template <typename T>"
+ "struct S : private Base<T> {"
+ " using typename Base<T>::Foo;"
+ " void f(Foo);"
+ "};";
+ // UnresolvedUsingTypenameDecl
+ EXPECT_TRUE(matches(Using, unresolvedUsingTypenameDecl(hasName("Foo"))));
+ // UnresolvedUsingTypenameType -> UnresolvedUsingTypenameDecl
+ EXPECT_TRUE(matches(Using, parmVarDecl(hasType(namedDecl(hasName("Foo"))))));
}
TEST(Matcher, BindMatchedNodes) {
@@ -928,7 +989,7 @@ TEST(Matcher, BindMatchedNodes) {
new VerifyIdIsBoundTo<Decl>("b")));
StatementMatcher MethodX =
- callExpr(callee(methodDecl(hasName("x")))).bind("x");
+ callExpr(callee(cxxMethodDecl(hasName("x")))).bind("x");
EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };",
MethodX,
@@ -1042,13 +1103,14 @@ TEST(HasTypeLoc, MatchesDeclaratorDecls) {
TEST(Matcher, Call) {
// FIXME: Do we want to overload Call() to directly take
// Matcher<Decl>, too?
- StatementMatcher MethodX = callExpr(hasDeclaration(methodDecl(hasName("x"))));
+ StatementMatcher MethodX =
+ callExpr(hasDeclaration(cxxMethodDecl(hasName("x"))));
EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));
EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));
StatementMatcher MethodOnY =
- memberCallExpr(on(hasType(recordDecl(hasName("Y")))));
+ cxxMemberCallExpr(on(hasType(recordDecl(hasName("Y")))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
@@ -1067,7 +1129,7 @@ TEST(Matcher, Call) {
MethodOnY));
StatementMatcher MethodOnYPointer =
- memberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
+ cxxMemberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
@@ -1094,9 +1156,9 @@ TEST(Matcher, Lambda) {
TEST(Matcher, ForRange) {
EXPECT_TRUE(matches("int as[] = { 1, 2, 3 };"
"void f() { for (auto &a : as); }",
- forRangeStmt()));
+ cxxForRangeStmt()));
EXPECT_TRUE(notMatches("void f() { for (int i; i<5; ++i); }",
- forRangeStmt()));
+ cxxForRangeStmt()));
}
TEST(Matcher, SubstNonTypeTemplateParm) {
@@ -1110,6 +1172,20 @@ TEST(Matcher, SubstNonTypeTemplateParm) {
substNonTypeTemplateParmExpr()));
}
+TEST(Matcher, NonTypeTemplateParmDecl) {
+ EXPECT_TRUE(matches("template <int N> void f();",
+ nonTypeTemplateParmDecl(hasName("N"))));
+ EXPECT_TRUE(
+ notMatches("template <typename T> void f();", nonTypeTemplateParmDecl()));
+}
+
+TEST(Matcher, templateTypeParmDecl) {
+ EXPECT_TRUE(matches("template <typename T> void f();",
+ templateTypeParmDecl(hasName("T"))));
+ EXPECT_TRUE(
+ notMatches("template <int N> void f();", templateTypeParmDecl()));
+}
+
TEST(Matcher, UserDefinedLiteral) {
EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"
" return i + 1;"
@@ -1130,9 +1206,10 @@ TEST(Matcher, FlowControl) {
TEST(HasType, MatchesAsString) {
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
- memberCallExpr(on(hasType(asString("class Y *"))))));
- EXPECT_TRUE(matches("class X { void x(int x) {} };",
- methodDecl(hasParameter(0, hasType(asString("int"))))));
+ cxxMemberCallExpr(on(hasType(asString("class Y *"))))));
+ EXPECT_TRUE(
+ matches("class X { void x(int x) {} };",
+ cxxMethodDecl(hasParameter(0, hasType(asString("int"))))));
EXPECT_TRUE(matches("namespace ns { struct A {}; } struct B { ns::A a; };",
fieldDecl(hasType(asString("ns::A")))));
EXPECT_TRUE(matches("namespace { struct A {}; } struct B { A a; };",
@@ -1140,7 +1217,7 @@ TEST(HasType, MatchesAsString) {
}
TEST(Matcher, OverloadedOperatorCall) {
- StatementMatcher OpCall = operatorCallExpr();
+ StatementMatcher OpCall = cxxOperatorCallExpr();
// Unary operator
EXPECT_TRUE(matches("class Y { }; "
"bool operator!(Y x) { return false; }; "
@@ -1167,22 +1244,22 @@ TEST(Matcher, OverloadedOperatorCall) {
TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
StatementMatcher OpCallAndAnd =
- operatorCallExpr(hasOverloadedOperatorName("&&"));
+ cxxOperatorCallExpr(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 =
- operatorCallExpr(hasOverloadedOperatorName("<<"));
+ cxxOperatorCallExpr(hasOverloadedOperatorName("<<"));
EXPECT_TRUE(notMatches("class Y { }; "
"bool operator&&(Y x, Y y) { return true; }; "
"Y a; Y b; bool c = a && b;",
OpCallLessLess));
StatementMatcher OpStarCall =
- operatorCallExpr(hasOverloadedOperatorName("*"));
+ cxxOperatorCallExpr(hasOverloadedOperatorName("*"));
EXPECT_TRUE(matches("class Y; int operator*(Y &); void f(Y &y) { *y; }",
OpStarCall));
DeclarationMatcher ClassWithOpStar =
- recordDecl(hasMethod(hasOverloadedOperatorName("*")));
+ cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")));
EXPECT_TRUE(matches("class Y { int operator*(); };",
ClassWithOpStar));
EXPECT_TRUE(notMatches("class Y { void myOperator(); };",
@@ -1194,26 +1271,25 @@ TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
TEST(Matcher, NestedOverloadedOperatorCalls) {
EXPECT_TRUE(matchAndVerifyResultTrue(
- "class Y { }; "
- "Y& operator&&(Y& x, Y& y) { return x; }; "
- "Y a; Y b; Y c; Y d = a && b && c;",
- operatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
- new VerifyIdIsBoundTo<CXXOperatorCallExpr>("x", 2)));
- EXPECT_TRUE(matches(
- "class Y { }; "
- "Y& operator&&(Y& x, Y& y) { return x; }; "
- "Y a; Y b; Y c; Y d = a && b && c;",
- operatorCallExpr(hasParent(operatorCallExpr()))));
- EXPECT_TRUE(matches(
- "class Y { }; "
- "Y& operator&&(Y& x, Y& y) { return x; }; "
- "Y a; Y b; Y c; Y d = a && b && c;",
- operatorCallExpr(hasDescendant(operatorCallExpr()))));
+ "class Y { }; "
+ "Y& operator&&(Y& x, Y& y) { return x; }; "
+ "Y a; Y b; Y c; Y d = a && b && c;",
+ cxxOperatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
+ new VerifyIdIsBoundTo<CXXOperatorCallExpr>("x", 2)));
+ EXPECT_TRUE(matches("class Y { }; "
+ "Y& operator&&(Y& x, Y& y) { return x; }; "
+ "Y a; Y b; Y c; Y d = a && b && c;",
+ cxxOperatorCallExpr(hasParent(cxxOperatorCallExpr()))));
+ EXPECT_TRUE(
+ matches("class Y { }; "
+ "Y& operator&&(Y& x, Y& y) { return x; }; "
+ "Y a; Y b; Y c; Y d = a && b && c;",
+ cxxOperatorCallExpr(hasDescendant(cxxOperatorCallExpr()))));
}
TEST(Matcher, ThisPointerType) {
StatementMatcher MethodOnY =
- memberCallExpr(thisPointerType(recordDecl(hasName("Y"))));
+ cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))));
EXPECT_TRUE(
matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
@@ -1245,7 +1321,7 @@ TEST(Matcher, VariableUsage) {
StatementMatcher Reference =
declRefExpr(to(
varDecl(hasInitializer(
- memberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
+ cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
EXPECT_TRUE(matches(
"class Y {"
@@ -1279,6 +1355,29 @@ TEST(Matcher, VarDecl_Storage) {
EXPECT_TRUE(matches("void f() { static int X; }", M));
}
+TEST(Matcher, VarDecl_StorageDuration) {
+ std::string T =
+ "void f() { int x; static int y; } int a;";
+
+ EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration())));
+ EXPECT_TRUE(
+ notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration())));
+ EXPECT_TRUE(
+ notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration())));
+
+ EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration())));
+ EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration())));
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasStaticStorageDuration())));
+
+ // FIXME: It is really hard to test with thread_local itself because not all
+ // targets support TLS, which causes this to be an error depending on what
+ // platform the test is being run on. We do not have access to the TargetInfo
+ // object to be able to test whether the platform supports TLS or not.
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasThreadStorageDuration())));
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("y"), hasThreadStorageDuration())));
+ EXPECT_TRUE(notMatches(T, varDecl(hasName("a"), hasThreadStorageDuration())));
+}
+
TEST(Matcher, FindsVarDeclInFunctionParameter) {
EXPECT_TRUE(matches(
"void f(int i) {}",
@@ -1287,7 +1386,7 @@ TEST(Matcher, FindsVarDeclInFunctionParameter) {
TEST(Matcher, CalledVariable) {
StatementMatcher CallOnVariableY =
- memberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
+ cxxMemberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(matches(
"class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY));
@@ -1370,6 +1469,14 @@ TEST(IsInteger, ReportsNoFalsePositives) {
to(varDecl(hasType(isInteger()))))))));
}
+TEST(IsAnyCharacter, MatchesCharacters) {
+ EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter()))));
+}
+
+TEST(IsAnyCharacter, ReportsNoFalsePositives) {
+ EXPECT_TRUE(notMatches("int i;", varDecl(hasType(isAnyCharacter()))));
+}
+
TEST(IsArrow, MatchesMemberVariablesViaArrow) {
EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
memberExpr(isArrow())));
@@ -1398,18 +1505,25 @@ TEST(IsArrow, MatchesMemberCallsViaArrow) {
}
TEST(Callee, MatchesDeclarations) {
- StatementMatcher CallMethodX = callExpr(callee(methodDecl(hasName("x"))));
+ StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x"))));
EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));
EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));
- CallMethodX = callExpr(callee(conversionDecl()));
+ CallMethodX = callExpr(callee(cxxConversionDecl()));
EXPECT_TRUE(
matches("struct Y { operator int() const; }; int i = Y();", CallMethodX));
EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",
CallMethodX));
}
+TEST(ConversionDeclaration, IsExplicit) {
+ EXPECT_TRUE(matches("struct S { explicit operator int(); };",
+ cxxConversionDecl(isExplicit())));
+ EXPECT_TRUE(notMatches("struct S { operator int(); };",
+ cxxConversionDecl(isExplicit())));
+}
+
TEST(Callee, MatchesMemberExpressions) {
EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
callExpr(callee(memberExpr()))));
@@ -1442,6 +1556,13 @@ TEST(Function, MatchesFunctionDeclarations) {
notMatches("void f(int);"
"template <typename T> struct S { void g(T t) { f(t); } };",
CallFunctionF));
+
+ EXPECT_TRUE(matches("void f(...);", functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatches("void f(int);", functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatches("template <typename... Ts> void f(Ts...);",
+ functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatches("void f();", functionDecl(isVariadic())));
+ EXPECT_TRUE(notMatchesC("void f();", functionDecl(isVariadic())));
}
TEST(FunctionTemplate, MatchesFunctionTemplateDeclarations) {
@@ -1545,34 +1666,38 @@ TEST(QualType, hasLocalQualifiers) {
TEST(HasParameter, CallsInnerMatcher) {
EXPECT_TRUE(matches("class X { void x(int) {} };",
- methodDecl(hasParameter(0, varDecl()))));
+ cxxMethodDecl(hasParameter(0, varDecl()))));
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
- methodDecl(hasParameter(0, hasName("x")))));
+ cxxMethodDecl(hasParameter(0, hasName("x")))));
}
TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
EXPECT_TRUE(notMatches("class X { void x(int) {} };",
- methodDecl(hasParameter(42, varDecl()))));
+ cxxMethodDecl(hasParameter(42, varDecl()))));
}
TEST(HasType, MatchesParameterVariableTypesStrictly) {
- EXPECT_TRUE(matches("class X { void x(X x) {} };",
- methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
- EXPECT_TRUE(notMatches("class X { void x(const X &x) {} };",
- methodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches(
+ "class X { void x(X x) {} };",
+ cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(notMatches(
+ "class X { void x(const X &x) {} };",
+ cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
- methodDecl(hasParameter(0,
- hasType(pointsTo(recordDecl(hasName("X"))))))));
+ cxxMethodDecl(hasParameter(
+ 0, hasType(pointsTo(recordDecl(hasName("X"))))))));
EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
- methodDecl(hasParameter(0,
- hasType(references(recordDecl(hasName("X"))))))));
+ cxxMethodDecl(hasParameter(
+ 0, hasType(references(recordDecl(hasName("X"))))))));
}
TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
- EXPECT_TRUE(matches("class Y {}; class X { void x(X x, Y y) {} };",
- methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
- EXPECT_TRUE(matches("class Y {}; class X { void x(Y y, X x) {} };",
- methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches(
+ "class Y {}; class X { void x(X x, Y y) {} };",
+ cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(matches(
+ "class Y {}; class X { void x(Y y, X x) {} };",
+ cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
}
TEST(Returns, MatchesReturnTypes) {
@@ -1599,6 +1724,15 @@ TEST(IsDeleted, MatchesDeletedFunctionDeclarations) {
functionDecl(hasName("Func"), isDeleted())));
}
+TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) {
+ EXPECT_TRUE(notMatches("void f();", functionDecl(isNoThrow())));
+ EXPECT_TRUE(notMatches("void f() throw(int);", functionDecl(isNoThrow())));
+ EXPECT_TRUE(
+ notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
+ EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow())));
+ EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow())));
+}
+
TEST(isConstexpr, MatchesConstexprDeclarations) {
EXPECT_TRUE(matches("constexpr int foo = 42;",
varDecl(hasName("foo"), isConstexpr())));
@@ -1607,21 +1741,22 @@ TEST(isConstexpr, MatchesConstexprDeclarations) {
}
TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
- EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
- methodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
+ EXPECT_TRUE(notMatches(
+ "class Y {}; class X { void x(int) {} };",
+ cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
}
TEST(HasAnyParameter, DoesNotMatchThisPointer) {
EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
- methodDecl(hasAnyParameter(hasType(pointsTo(
- recordDecl(hasName("X"))))))));
+ cxxMethodDecl(hasAnyParameter(
+ hasType(pointsTo(recordDecl(hasName("X"))))))));
}
TEST(HasName, MatchesParameterVariableDeclarations) {
EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
- methodDecl(hasAnyParameter(hasName("x")))));
+ cxxMethodDecl(hasAnyParameter(hasName("x")))));
EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
- methodDecl(hasAnyParameter(hasName("x")))));
+ cxxMethodDecl(hasAnyParameter(hasName("x")))));
}
TEST(Matcher, MatchesClassTemplateSpecialization) {
@@ -1774,46 +1909,68 @@ TEST(Matcher, MatchesAccessSpecDecls) {
EXPECT_TRUE(notMatches("class C { int i; };", accessSpecDecl()));
}
+TEST(Matcher, MatchesFinal) {
+ EXPECT_TRUE(matches("class X final {};", cxxRecordDecl(isFinal())));
+ EXPECT_TRUE(matches("class X { virtual void f() final; };",
+ cxxMethodDecl(isFinal())));
+ EXPECT_TRUE(notMatches("class X {};", cxxRecordDecl(isFinal())));
+ EXPECT_TRUE(
+ notMatches("class X { virtual void f(); };", cxxMethodDecl(isFinal())));
+}
+
TEST(Matcher, MatchesVirtualMethod) {
EXPECT_TRUE(matches("class X { virtual int f(); };",
- methodDecl(isVirtual(), hasName("::X::f"))));
- EXPECT_TRUE(notMatches("class X { int f(); };",
- methodDecl(isVirtual())));
+ cxxMethodDecl(isVirtual(), hasName("::X::f"))));
+ EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isVirtual())));
}
TEST(Matcher, MatchesPureMethod) {
EXPECT_TRUE(matches("class X { virtual int f() = 0; };",
- methodDecl(isPure(), hasName("::X::f"))));
- EXPECT_TRUE(notMatches("class X { int f(); };",
- methodDecl(isPure())));
+ cxxMethodDecl(isPure(), hasName("::X::f"))));
+ EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isPure())));
+}
+
+TEST(Matcher, MatchesCopyAssignmentOperator) {
+ EXPECT_TRUE(matches("class X { X &operator=(X); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(const X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(volatile X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(matches("class X { X &operator=(const volatile X &); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
+ EXPECT_TRUE(notMatches("class X { X &operator=(X &&); };",
+ cxxMethodDecl(isCopyAssignmentOperator())));
}
TEST(Matcher, MatchesConstMethod) {
- EXPECT_TRUE(matches("struct A { void foo() const; };",
- methodDecl(isConst())));
- EXPECT_TRUE(notMatches("struct A { void foo(); };",
- methodDecl(isConst())));
+ EXPECT_TRUE(
+ matches("struct A { void foo() const; };", cxxMethodDecl(isConst())));
+ EXPECT_TRUE(
+ notMatches("struct A { void foo(); };", cxxMethodDecl(isConst())));
}
TEST(Matcher, MatchesOverridingMethod) {
EXPECT_TRUE(matches("class X { virtual int f(); }; "
"class Y : public X { int f(); };",
- methodDecl(isOverride(), hasName("::Y::f"))));
+ cxxMethodDecl(isOverride(), hasName("::Y::f"))));
EXPECT_TRUE(notMatches("class X { virtual int f(); }; "
- "class Y : public X { int f(); };",
- methodDecl(isOverride(), hasName("::X::f"))));
+ "class Y : public X { int f(); };",
+ cxxMethodDecl(isOverride(), hasName("::X::f"))));
EXPECT_TRUE(notMatches("class X { int f(); }; "
"class Y : public X { int f(); };",
- methodDecl(isOverride())));
+ cxxMethodDecl(isOverride())));
EXPECT_TRUE(notMatches("class X { int f(); int f(int); }; ",
- methodDecl(isOverride())));
+ cxxMethodDecl(isOverride())));
EXPECT_TRUE(
matches("template <typename Base> struct Y : Base { void f() override;};",
- methodDecl(isOverride(), hasName("::Y::f"))));
+ cxxMethodDecl(isOverride(), hasName("::Y::f"))));
}
TEST(Matcher, ConstructorCall) {
- StatementMatcher Constructor = constructExpr();
+ StatementMatcher Constructor = cxxConstructExpr();
EXPECT_TRUE(
matches("class X { public: X(); }; void x() { X x; }", Constructor));
@@ -1827,7 +1984,7 @@ TEST(Matcher, ConstructorCall) {
}
TEST(Matcher, ConstructorArgument) {
- StatementMatcher Constructor = constructExpr(
+ StatementMatcher Constructor = cxxConstructExpr(
hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
@@ -1843,7 +2000,7 @@ TEST(Matcher, ConstructorArgument) {
notMatches("class X { public: X(int); }; void x() { int z; X x(z); }",
Constructor));
- StatementMatcher WrongIndex = constructExpr(
+ StatementMatcher WrongIndex = cxxConstructExpr(
hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
notMatches("class X { public: X(int); }; void x() { int y; X x(y); }",
@@ -1851,7 +2008,7 @@ TEST(Matcher, ConstructorArgument) {
}
TEST(Matcher, ConstructorArgumentCount) {
- StatementMatcher Constructor1Arg = constructExpr(argumentCountIs(1));
+ StatementMatcher Constructor1Arg = cxxConstructExpr(argumentCountIs(1));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { X x(0); }",
@@ -1868,7 +2025,8 @@ TEST(Matcher, ConstructorArgumentCount) {
}
TEST(Matcher, ConstructorListInitialization) {
- StatementMatcher ConstructorListInit = constructExpr(isListInitialization());
+ StatementMatcher ConstructorListInit =
+ cxxConstructExpr(isListInitialization());
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { X x{0}; }",
@@ -1880,13 +2038,13 @@ TEST(Matcher, ConstructorListInitialization) {
TEST(Matcher,ThisExpr) {
EXPECT_TRUE(
- matches("struct X { int a; int f () { return a; } };", thisExpr()));
+ matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));
EXPECT_TRUE(
- notMatches("struct X { int f () { int a; return a; } };", thisExpr()));
+ notMatches("struct X { int f () { int a; return a; } };", cxxThisExpr()));
}
TEST(Matcher, BindTemporaryExpression) {
- StatementMatcher TempExpression = bindTemporaryExpr();
+ StatementMatcher TempExpression = cxxBindTemporaryExpr();
std::string ClassString = "class string { public: string(); ~string(); }; ";
@@ -1953,46 +2111,76 @@ TEST(MaterializeTemporaryExpr, MatchesTemporary) {
TEST(ConstructorDeclaration, SimpleCase) {
EXPECT_TRUE(matches("class Foo { Foo(int i); };",
- constructorDecl(ofClass(hasName("Foo")))));
+ cxxConstructorDecl(ofClass(hasName("Foo")))));
EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
- constructorDecl(ofClass(hasName("Bar")))));
+ cxxConstructorDecl(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 { };",
- constructorDecl(isImplicit())));
+ cxxConstructorDecl(isImplicit())));
// The compiler added the implicit default constructor.
EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
- constructorDecl(isImplicit())));
+ cxxConstructorDecl(isImplicit())));
EXPECT_TRUE(matches("class Foo { Foo(){} };",
- constructorDecl(unless(isImplicit()))));
+ cxxConstructorDecl(unless(isImplicit()))));
// The compiler added an implicit assignment operator.
EXPECT_TRUE(matches("struct A { int x; } a = {0}, b = a; void f() { a = b; }",
- methodDecl(isImplicit(), hasName("operator="))));
+ cxxMethodDecl(isImplicit(), hasName("operator="))));
+}
+
+TEST(ConstructorDeclaration, IsExplicit) {
+ EXPECT_TRUE(matches("struct S { explicit S(int); };",
+ cxxConstructorDecl(isExplicit())));
+ EXPECT_TRUE(notMatches("struct S { S(int); };",
+ cxxConstructorDecl(isExplicit())));
+}
+
+TEST(ConstructorDeclaration, Kinds) {
+ EXPECT_TRUE(matches("struct S { S(); };",
+ cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(); };",
+ cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(); };",
+ cxxConstructorDecl(isMoveConstructor())));
+
+ EXPECT_TRUE(notMatches("struct S { S(const S&); };",
+ cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(matches("struct S { S(const S&); };",
+ cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(const S&); };",
+ cxxConstructorDecl(isMoveConstructor())));
+
+ EXPECT_TRUE(notMatches("struct S { S(S&&); };",
+ cxxConstructorDecl(isDefaultConstructor())));
+ EXPECT_TRUE(notMatches("struct S { S(S&&); };",
+ cxxConstructorDecl(isCopyConstructor())));
+ EXPECT_TRUE(matches("struct S { S(S&&); };",
+ cxxConstructorDecl(isMoveConstructor())));
}
TEST(DestructorDeclaration, MatchesVirtualDestructor) {
EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
- destructorDecl(ofClass(hasName("Foo")))));
+ cxxDestructorDecl(ofClass(hasName("Foo")))));
}
TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {
EXPECT_TRUE(notMatches("class Foo {};",
- destructorDecl(ofClass(hasName("Foo")))));
+ cxxDestructorDecl(ofClass(hasName("Foo")))));
}
TEST(HasAnyConstructorInitializer, SimpleCase) {
- EXPECT_TRUE(notMatches(
- "class Foo { Foo() { } };",
- constructorDecl(hasAnyConstructorInitializer(anything()))));
- EXPECT_TRUE(matches(
- "class Foo {"
- " Foo() : foo_() { }"
- " int foo_;"
- "};",
- constructorDecl(hasAnyConstructorInitializer(anything()))));
+ EXPECT_TRUE(
+ notMatches("class Foo { Foo() { } };",
+ cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
+ EXPECT_TRUE(
+ matches("class Foo {"
+ " Foo() : foo_() { }"
+ " int foo_;"
+ "};",
+ cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
}
TEST(HasAnyConstructorInitializer, ForField) {
@@ -2003,11 +2191,11 @@ TEST(HasAnyConstructorInitializer, ForField) {
" Baz foo_;"
" Baz bar_;"
"};";
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasType(recordDecl(hasName("Baz"))))))));
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasName("foo_"))))));
- EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
forField(hasType(recordDecl(hasName("Bar"))))))));
}
@@ -2017,9 +2205,9 @@ TEST(HasAnyConstructorInitializer, WithInitializer) {
" Foo() : foo_(0) { }"
" int foo_;"
"};";
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(0)))))));
- EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
withInitializer(integerLiteral(equals(1)))))));
}
@@ -2031,16 +2219,40 @@ TEST(HasAnyConstructorInitializer, IsWritten) {
" Bar foo_;"
" Bar bar_;"
"};";
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("foo_")), isWritten())))));
- EXPECT_TRUE(notMatches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("bar_")), isWritten())))));
- EXPECT_TRUE(matches(Code, constructorDecl(hasAnyConstructorInitializer(
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
allOf(forField(hasName("bar_")), unless(isWritten()))))));
}
+TEST(HasAnyConstructorInitializer, IsBaseInitializer) {
+ static const char Code[] =
+ "struct B {};"
+ "struct D : B {"
+ " int I;"
+ " D(int i) : I(i) {}"
+ "};"
+ "struct E : B {"
+ " E() : B() {}"
+ "};";
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
+ hasName("E")))));
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
+ hasName("D")))));
+ EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
+ hasName("D")))));
+ EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(
+ hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
+ hasName("E")))));
+}
+
TEST(Matcher, NewExpression) {
- StatementMatcher New = newExpr();
+ StatementMatcher New = cxxNewExpr();
EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }", New));
EXPECT_TRUE(
@@ -2051,7 +2263,7 @@ TEST(Matcher, NewExpression) {
}
TEST(Matcher, NewExpressionArgument) {
- StatementMatcher New = constructExpr(
+ StatementMatcher New = cxxConstructExpr(
hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
@@ -2064,7 +2276,7 @@ TEST(Matcher, NewExpressionArgument) {
notMatches("class X { public: X(int); }; void x() { int z; new X(z); }",
New));
- StatementMatcher WrongIndex = constructExpr(
+ StatementMatcher WrongIndex = cxxConstructExpr(
hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
EXPECT_TRUE(
notMatches("class X { public: X(int); }; void x() { int y; new X(y); }",
@@ -2072,7 +2284,7 @@ TEST(Matcher, NewExpressionArgument) {
}
TEST(Matcher, NewExpressionArgumentCount) {
- StatementMatcher New = constructExpr(argumentCountIs(1));
+ StatementMatcher New = cxxConstructExpr(argumentCountIs(1));
EXPECT_TRUE(
matches("class X { public: X(int); }; void x() { new X(0); }", New));
@@ -2083,11 +2295,11 @@ TEST(Matcher, NewExpressionArgumentCount) {
TEST(Matcher, DeleteExpression) {
EXPECT_TRUE(matches("struct A {}; void f(A* a) { delete a; }",
- deleteExpr()));
+ cxxDeleteExpr()));
}
TEST(Matcher, DefaultArgument) {
- StatementMatcher Arg = defaultArgExpr();
+ StatementMatcher Arg = cxxDefaultArgExpr();
EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));
EXPECT_TRUE(
@@ -2152,7 +2364,7 @@ TEST(Matcher, FloatLiterals) {
}
TEST(Matcher, NullPtrLiteral) {
- EXPECT_TRUE(matches("int* i = nullptr;", nullPtrLiteralExpr()));
+ EXPECT_TRUE(matches("int* i = nullptr;", cxxNullPtrLiteralExpr()));
}
TEST(Matcher, GNUNullExpr) {
@@ -2164,7 +2376,8 @@ TEST(Matcher, AsmStatement) {
}
TEST(Matcher, Conditions) {
- StatementMatcher Condition = ifStmt(hasCondition(boolLiteral(equals(true))));
+ StatementMatcher Condition =
+ ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
EXPECT_TRUE(matches("void x() { if (true) {} }", Condition));
EXPECT_TRUE(notMatches("void x() { if (false) {} }", Condition));
@@ -2175,13 +2388,13 @@ TEST(Matcher, Conditions) {
TEST(IfStmt, ChildTraversalMatchers) {
EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
- ifStmt(hasThen(boolLiteral(equals(true))))));
+ ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
- ifStmt(hasThen(boolLiteral(equals(true))))));
+ ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
- ifStmt(hasElse(boolLiteral(equals(true))))));
+ ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
- ifStmt(hasElse(boolLiteral(equals(true))))));
+ ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
}
TEST(MatchBinaryOperator, HasOperatorName) {
@@ -2193,17 +2406,22 @@ TEST(MatchBinaryOperator, HasOperatorName) {
TEST(MatchBinaryOperator, HasLHSAndHasRHS) {
StatementMatcher OperatorTrueFalse =
- binaryOperator(hasLHS(boolLiteral(equals(true))),
- hasRHS(boolLiteral(equals(false))));
+ binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),
+ hasRHS(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));
EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));
EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse));
+
+ StatementMatcher OperatorIntPointer = arraySubscriptExpr(
+ hasLHS(hasType(isInteger())), hasRHS(hasType(pointsTo(qualType()))));
+ EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer));
+ EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer));
}
TEST(MatchBinaryOperator, HasEitherOperand) {
StatementMatcher HasOperand =
- binaryOperator(hasEitherOperand(boolLiteral(equals(false))));
+ binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));
EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));
@@ -2320,7 +2538,7 @@ TEST(MatchUnaryOperator, HasOperatorName) {
TEST(MatchUnaryOperator, HasUnaryOperand) {
StatementMatcher OperatorOnFalse =
- unaryOperator(hasUnaryOperand(boolLiteral(equals(false))));
+ unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));
EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));
@@ -2363,15 +2581,15 @@ TEST(Matcher, UnaryOperatorTypes) {
TEST(Matcher, ConditionalOperator) {
StatementMatcher Conditional = conditionalOperator(
- hasCondition(boolLiteral(equals(true))),
- hasTrueExpression(boolLiteral(equals(false))));
+ hasCondition(cxxBoolLiteral(equals(true))),
+ hasTrueExpression(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true ? false : true; }", Conditional));
EXPECT_TRUE(notMatches("void x() { false ? false : true; }", Conditional));
EXPECT_TRUE(notMatches("void x() { true ? true : false; }", Conditional));
StatementMatcher ConditionalFalse = conditionalOperator(
- hasFalseExpression(boolLiteral(equals(false))));
+ hasFalseExpression(cxxBoolLiteral(equals(false))));
EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));
EXPECT_TRUE(
@@ -2478,13 +2696,13 @@ TEST(Matcher, IsDefinition) {
EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
DeclarationMatcher DefinitionOfMethodA =
- methodDecl(hasName("a"), isDefinition());
+ cxxMethodDecl(hasName("a"), isDefinition());
EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
}
TEST(Matcher, OfClass) {
- StatementMatcher Constructor = constructExpr(hasDeclaration(methodDecl(
+ StatementMatcher Constructor = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
ofClass(hasName("X")))));
EXPECT_TRUE(
@@ -2502,7 +2720,7 @@ TEST(Matcher, VisitsTemplateInstantiations) {
"class A { public: void x(); };"
"template <typename T> class B { public: void y() { T t; t.x(); } };"
"void f() { B<A> b; b.y(); }",
- callExpr(callee(methodDecl(hasName("x"))))));
+ callExpr(callee(cxxMethodDecl(hasName("x"))))));
EXPECT_TRUE(matches(
"class A { public: void x(); };"
@@ -2513,8 +2731,8 @@ TEST(Matcher, VisitsTemplateInstantiations) {
"void f() {"
" C::B<A> b; b.y();"
"}",
- recordDecl(hasName("C"),
- hasDescendant(callExpr(callee(methodDecl(hasName("x"))))))));
+ recordDecl(hasName("C"), hasDescendant(callExpr(
+ callee(cxxMethodDecl(hasName("x"))))))));
}
TEST(Matcher, HandlesNullQualTypes) {
@@ -2607,10 +2825,10 @@ TEST(For, ForLoopInternals) {
TEST(For, ForRangeLoopInternals) {
EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
- forRangeStmt(hasLoopVariable(anything()))));
+ cxxForRangeStmt(hasLoopVariable(anything()))));
EXPECT_TRUE(matches(
"void f(){ int a[] {1, 2}; for (int i : a); }",
- forRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
+ cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
}
TEST(For, NegativeForLoopInternals) {
@@ -2650,7 +2868,7 @@ TEST(HasBody, FindsBodyOfForWhileDoLoops) {
EXPECT_TRUE(matches("void f() { do {} while(true); }",
doStmt(hasBody(compoundStmt()))));
EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
- forRangeStmt(hasBody(compoundStmt()))));
+ cxxForRangeStmt(hasBody(compoundStmt()))));
}
TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
@@ -2771,16 +2989,16 @@ TEST(Member, MatchesMemberAllocationFunction) {
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"));
+ cxxMethodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
EXPECT_TRUE(matches("class X { void operator delete(void*); };",
- methodDecl(ofClass(hasName("X")))));
+ cxxMethodDecl(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"));
+ cxxMethodDecl(ofClass(hasName("X"))), true, "-std=gnu++98"));
}
TEST(HasObjectExpression, DoesNotMatchMember) {
@@ -2822,6 +3040,15 @@ TEST(Field, MatchesField) {
EXPECT_TRUE(matches("class X { int m; };", fieldDecl(hasName("m"))));
}
+TEST(IsVolatileQualified, QualifiersMatch) {
+ EXPECT_TRUE(matches("volatile int i = 42;",
+ varDecl(hasType(isVolatileQualified()))));
+ EXPECT_TRUE(notMatches("volatile int *i;",
+ varDecl(hasType(isVolatileQualified()))));
+ EXPECT_TRUE(matches("typedef volatile int v_int; v_int i = 42;",
+ varDecl(hasType(isVolatileQualified()))));
+}
+
TEST(IsConstQualified, MatchesConstInt) {
EXPECT_TRUE(matches("const int i = 42;",
varDecl(hasType(isConstQualified()))));
@@ -2868,59 +3095,59 @@ TEST(CastExpression, DoesNotMatchNonCasts) {
TEST(ReinterpretCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
}
TEST(ReinterpretCast, DoesNotMatchOtherCasts) {
- EXPECT_TRUE(notMatches("char* p = (char*)(&p);", reinterpretCastExpr()));
+ EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxReinterpretCastExpr()));
EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
EXPECT_TRUE(notMatches("void* p = static_cast<void*>(&p);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- reinterpretCastExpr()));
+ cxxReinterpretCastExpr()));
}
TEST(FunctionalCast, MatchesSimpleCase) {
std::string foo_class = "class Foo { public: Foo(const char*); };";
EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello world\"); }",
- functionalCastExpr()));
+ cxxFunctionalCastExpr()));
}
TEST(FunctionalCast, DoesNotMatchOtherCasts) {
std::string FooClass = "class Foo { public: Foo(const char*); };";
EXPECT_TRUE(
notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
- functionalCastExpr()));
+ cxxFunctionalCastExpr()));
EXPECT_TRUE(
notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
- functionalCastExpr()));
+ cxxFunctionalCastExpr()));
}
TEST(DynamicCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- dynamicCastExpr()));
+ cxxDynamicCastExpr()));
}
TEST(StaticCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("void* p(static_cast<void*>(&p));",
- staticCastExpr()));
+ cxxStaticCastExpr()));
}
TEST(StaticCast, DoesNotMatchOtherCasts) {
- EXPECT_TRUE(notMatches("char* p = (char*)(&p);", staticCastExpr()));
+ EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxStaticCastExpr()));
EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",
- staticCastExpr()));
+ cxxStaticCastExpr()));
EXPECT_TRUE(notMatches("void* p = reinterpret_cast<char*>(&p);",
- staticCastExpr()));
+ cxxStaticCastExpr()));
EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
"B b;"
"D* p = dynamic_cast<D*>(&b);",
- staticCastExpr()));
+ cxxStaticCastExpr()));
}
TEST(CStyleCast, MatchesSimpleCase) {
@@ -2939,7 +3166,7 @@ TEST(CStyleCast, DoesNotMatchOtherCasts) {
TEST(HasDestinationType, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
- staticCastExpr(hasDestinationType(
+ cxxStaticCastExpr(hasDestinationType(
pointsTo(TypeMatcher(anything()))))));
}
@@ -3142,7 +3369,7 @@ TEST(HasSourceExpression, MatchesImplicitCasts) {
EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
"void r() {string a_string; URL url = a_string; }",
implicitCastExpr(
- hasSourceExpression(constructExpr()))));
+ hasSourceExpression(cxxConstructExpr()))));
}
TEST(HasSourceExpression, MatchesExplicitCasts) {
@@ -3314,21 +3541,26 @@ TEST(SwitchCase, MatchesEachCase) {
TEST(ForEachConstructorInitializer, MatchesInitializers) {
EXPECT_TRUE(matches(
"struct X { X() : i(42), j(42) {} int i, j; };",
- constructorDecl(forEachConstructorInitializer(ctorInitializer()))));
+ cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
}
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 { } catch(int X) { }", cxxCatchStmt()));
+ EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxTryStmt()));
+ EXPECT_TRUE(
+ notMatches("void foo() try { } catch(int X) { }", cxxThrowExpr()));
EXPECT_TRUE(matches("void foo() try { throw; } catch(int X) { }",
- throwExpr()));
+ cxxThrowExpr()));
EXPECT_TRUE(matches("void foo() try { throw 5;} catch(int X) { }",
- throwExpr()));
+ cxxThrowExpr()));
EXPECT_TRUE(matches("void foo() try { throw; } catch(...) { }",
- catchStmt(isCatchAll())));
+ cxxCatchStmt(isCatchAll())));
EXPECT_TRUE(notMatches("void foo() try { throw; } catch(int) { }",
- catchStmt(isCatchAll())));
+ cxxCatchStmt(isCatchAll())));
+ EXPECT_TRUE(matches("void foo() try {} catch(int X) { }",
+ varDecl(isExceptionVariable())));
+ EXPECT_TRUE(notMatches("void foo() try { int X; } catch (...) { }",
+ varDecl(isExceptionVariable())));
}
TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
@@ -3460,12 +3692,12 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class X { void f(); void g(); };",
- recordDecl(decl().bind("x"), hasMethod(hasName("g"))),
+ cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class X { X() : a(1), b(2) {} double a; int b; };",
recordDecl(decl().bind("x"),
- has(constructorDecl(
+ has(cxxConstructorDecl(
hasAnyConstructorInitializer(forField(hasName("b")))))),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
@@ -3489,12 +3721,12 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A{}; class B{}; class C : B, A {};",
- recordDecl(decl().bind("x"), isDerivedFrom("::A")),
+ cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A")),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A{}; typedef A B; typedef A C; typedef A D;"
"class E : A {};",
- recordDecl(decl().bind("x"), isDerivedFrom("C")),
+ cxxRecordDecl(decl().bind("x"), isDerivedFrom("C")),
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A { class B { void f() {} }; };",
@@ -3513,8 +3745,8 @@ TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
new VerifyIdIsBoundTo<Decl>("x", 1)));
EXPECT_TRUE(matchAndVerifyResultTrue(
"class A { A() : s(), i(42) {} const char *s; int i; };",
- constructorDecl(hasName("::A::A"), decl().bind("x"),
- forEachConstructorInitializer(forField(hasName("i")))),
+ cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),
+ forEachConstructorInitializer(forField(hasName("i")))),
new VerifyIdIsBoundTo<Decl>("x", 1)));
}
@@ -3588,11 +3820,11 @@ TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> class X {}; class A {}; X<A> x;",
- recordDecl(hasName("::X"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
EXPECT_TRUE(matches(
"template <typename T> class X { T t; }; class A {}; X<A> x;",
- recordDecl(isTemplateInstantiation(), hasDescendant(
+ cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
fieldDecl(hasType(recordDecl(hasName("A"))))))));
}
@@ -3607,7 +3839,7 @@ TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
EXPECT_TRUE(matches(
"template <typename T> class X { T t; }; class A {};"
"template class X<A>;",
- recordDecl(isTemplateInstantiation(), hasDescendant(
+ cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
fieldDecl(hasType(recordDecl(hasName("A"))))))));
}
@@ -3616,7 +3848,7 @@ TEST(IsTemplateInstantiation,
EXPECT_TRUE(matches(
"template <typename T> class X {};"
"template <typename T> class X<T*> {}; class A {}; X<A*> x;",
- recordDecl(hasName("::X"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation,
@@ -3627,7 +3859,7 @@ TEST(IsTemplateInstantiation,
" template <typename U> class Y { U u; };"
" Y<A> y;"
"};",
- recordDecl(hasName("::X::Y"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
@@ -3640,31 +3872,31 @@ TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
" template <typename U> class Y { U u; };"
" Y<T> y;"
"}; X<A> x;",
- recordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
+ cxxRecordDecl(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;",
- recordDecl(hasName("::X"), isTemplateInstantiation())));
+ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
}
TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
EXPECT_TRUE(notMatches(
"class A {}; class Y { A a; };",
- recordDecl(isTemplateInstantiation())));
+ cxxRecordDecl(isTemplateInstantiation())));
}
TEST(IsInstantiated, MatchesInstantiation) {
EXPECT_TRUE(
matches("template<typename T> class A { T i; }; class Y { A<int> a; };",
- recordDecl(isInstantiated())));
+ cxxRecordDecl(isInstantiated())));
}
TEST(IsInstantiated, NotMatchesDefinition) {
EXPECT_TRUE(notMatches("template<typename T> class A { T i; };",
- recordDecl(isInstantiated())));
+ cxxRecordDecl(isInstantiated())));
}
TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) {
@@ -3716,7 +3948,7 @@ TEST(IsExplicitTemplateSpecialization,
DoesNotMatchPrimaryTemplate) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {};",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t);",
functionDecl(isExplicitTemplateSpecialization())));
@@ -3727,7 +3959,7 @@ TEST(IsExplicitTemplateSpecialization,
EXPECT_TRUE(notMatches(
"template <typename T> class X {};"
"template class X<int>; extern template class X<long>;",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t) {}"
"template void f(int t); extern template void f(long t);",
@@ -3738,7 +3970,7 @@ TEST(IsExplicitTemplateSpecialization,
DoesNotMatchImplicitTemplateInstantiations) {
EXPECT_TRUE(notMatches(
"template <typename T> class X {}; X<int> x;",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(notMatches(
"template <typename T> void f(T t); void g() { f(10); }",
functionDecl(isExplicitTemplateSpecialization())));
@@ -3749,7 +3981,7 @@ TEST(IsExplicitTemplateSpecialization,
EXPECT_TRUE(matches(
"template <typename T> class X {};"
"template<> class X<int> {};",
- recordDecl(isExplicitTemplateSpecialization())));
+ cxxRecordDecl(isExplicitTemplateSpecialization())));
EXPECT_TRUE(matches(
"template <typename T> void f(T t) {}"
"template<> void f(int t) {}",
@@ -3831,7 +4063,7 @@ TEST(HasAncestor, MatchesInTemplateInstantiations) {
TEST(HasAncestor, MatchesInImplicitCode) {
EXPECT_TRUE(matches(
"struct X {}; struct A { A() {} X x; };",
- constructorDecl(
+ cxxConstructorDecl(
hasAnyConstructorInitializer(withInitializer(expr(
hasAncestor(recordDecl(hasName("A")))))))));
}
@@ -3854,8 +4086,9 @@ TEST(HasAncestor, MatchesAllAncestors) {
"void t() { C<int>::f(); }",
integerLiteral(
equals(42),
- allOf(hasAncestor(recordDecl(isTemplateInstantiation())),
- hasAncestor(recordDecl(unless(isTemplateInstantiation())))))));
+ allOf(
+ hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
+ hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
}
TEST(HasParent, MatchesAllParents) {
@@ -3865,23 +4098,23 @@ TEST(HasParent, MatchesAllParents) {
integerLiteral(
equals(42),
hasParent(compoundStmt(hasParent(functionDecl(
- hasParent(recordDecl(isTemplateInstantiation())))))))));
- EXPECT_TRUE(matches(
- "template <typename T> struct C { static void f() { 42; } };"
- "void t() { C<int>::f(); }",
- integerLiteral(
- equals(42),
- hasParent(compoundStmt(hasParent(functionDecl(
- hasParent(recordDecl(unless(isTemplateInstantiation()))))))))));
+ hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));
+ EXPECT_TRUE(
+ matches("template <typename T> struct C { static void f() { 42; } };"
+ "void t() { C<int>::f(); }",
+ integerLiteral(
+ equals(42),
+ hasParent(compoundStmt(hasParent(functionDecl(hasParent(
+ cxxRecordDecl(unless(isTemplateInstantiation()))))))))));
EXPECT_TRUE(matches(
"template <typename T> struct C { static void f() { 42; } };"
"void t() { C<int>::f(); }",
integerLiteral(equals(42),
- hasParent(compoundStmt(allOf(
- hasParent(functionDecl(
- hasParent(recordDecl(isTemplateInstantiation())))),
- hasParent(functionDecl(hasParent(recordDecl(
- unless(isTemplateInstantiation())))))))))));
+ hasParent(compoundStmt(
+ allOf(hasParent(functionDecl(hasParent(
+ cxxRecordDecl(isTemplateInstantiation())))),
+ hasParent(functionDecl(hasParent(cxxRecordDecl(
+ unless(isTemplateInstantiation())))))))))));
EXPECT_TRUE(
notMatches("template <typename T> struct C { static void f() {} };"
"void t() { C<int>::f(); }",
@@ -3913,9 +4146,16 @@ TEST(TypeMatching, MatchesTypes) {
EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
}
+TEST(TypeMatching, MatchesBool) {
+ EXPECT_TRUE(matches("struct S { bool func(); };",
+ cxxMethodDecl(returns(booleanType()))));
+ EXPECT_TRUE(notMatches("struct S { void func(); };",
+ cxxMethodDecl(returns(booleanType()))));
+}
+
TEST(TypeMatching, MatchesVoid) {
- EXPECT_TRUE(
- matches("struct S { void func(); };", methodDecl(returns(voidType()))));
+ EXPECT_TRUE(matches("struct S { void func(); };",
+ cxxMethodDecl(returns(voidType()))));
}
TEST(TypeMatching, MatchesArrayTypes) {
@@ -3952,6 +4192,11 @@ TEST(TypeMatching, MatchesArrayTypes) {
EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger())));
}
+TEST(TypeMatching, DecayedType) {
+ EXPECT_TRUE(matches("void f(int i[]);", valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))));
+ EXPECT_TRUE(notMatches("int i[7];", decayedType()));
+}
+
TEST(TypeMatching, MatchesComplexTypes) {
EXPECT_TRUE(matches("_Complex float f;", complexType()));
EXPECT_TRUE(matches(
@@ -4247,6 +4492,18 @@ TEST(ElaboratedTypeNarrowing, namesType) {
elaboratedType(elaboratedType(namesType(typedefType())))));
}
+TEST(TypeMatching, MatchesSubstTemplateTypeParmType) {
+ const std::string code = "template <typename T>"
+ "int F() {"
+ " return 1 + T();"
+ "}"
+ "int i = F<int>();";
+ EXPECT_FALSE(matches(code, binaryOperator(hasLHS(
+ expr(hasType(substTemplateTypeParmType()))))));
+ EXPECT_TRUE(matches(code, binaryOperator(hasRHS(
+ expr(hasType(substTemplateTypeParmType()))))));
+}
+
TEST(NNS, MatchesNestedNameSpecifiers) {
EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;",
nestedNameSpecifier()));
@@ -4254,6 +4511,8 @@ TEST(NNS, MatchesNestedNameSpecifiers) {
nestedNameSpecifier()));
EXPECT_TRUE(matches("struct A { void f(); }; void A::f() {}",
nestedNameSpecifier()));
+ EXPECT_TRUE(matches("namespace a { namespace b {} } namespace ab = a::b;",
+ nestedNameSpecifier()));
EXPECT_TRUE(matches(
"struct A { static void f() {} }; void g() { A::f(); }",
@@ -4268,6 +4527,16 @@ TEST(NullStatement, SimpleCases) {
EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt()));
}
+TEST(NS, Anonymous) {
+ EXPECT_TRUE(notMatches("namespace N {}", namespaceDecl(isAnonymous())));
+ EXPECT_TRUE(matches("namespace {}", namespaceDecl(isAnonymous())));
+}
+
+TEST(NS, Alias) {
+ EXPECT_TRUE(matches("namespace test {} namespace alias = ::test;",
+ namespaceAliasDecl(hasName("alias"))));
+}
+
TEST(NNS, MatchesTypes) {
NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
specifiesType(hasDeclaration(recordDecl(hasName("A")))));
@@ -4480,6 +4749,16 @@ public:
decl(has(decl(equalsNode(TypedNode)))).bind(""))),
*Node, Context)) != nullptr;
}
+ bool verify(const BoundNodes &Nodes, ASTContext &Context, const Type *Node) {
+ // Use the original typed pointer to verify we can pass pointers to subtypes
+ // to equalsNode.
+ const T *TypedNode = cast<T>(Node);
+ const auto *Dec = Nodes.getNodeAs<FieldDecl>("decl");
+ return selectFirst<T>(
+ "", match(fieldDecl(hasParent(decl(has(fieldDecl(
+ hasType(type(equalsNode(TypedNode)).bind(""))))))),
+ *Dec, Context)) != nullptr;
+ }
};
TEST(IsEqualTo, MatchesNodesByIdentity) {
@@ -4489,6 +4768,10 @@ TEST(IsEqualTo, MatchesNodesByIdentity) {
EXPECT_TRUE(matchAndVerifyResultTrue(
"void f() { if (true) if(true) {} }", ifStmt().bind(""),
new VerifyAncestorHasChildIsEqual<IfStmt>()));
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ "class X { class Y {} y; };",
+ fieldDecl(hasName("y"), hasType(type().bind(""))).bind("decl"),
+ new VerifyAncestorHasChildIsEqual<Type>()));
}
TEST(MatchFinder, CheckProfiling) {
@@ -4656,12 +4939,12 @@ TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
"void f(StringRef v) {"
" v.data();"
"}",
- memberCallExpr(
- callee(methodDecl(hasName("data"))),
- on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
- .bind("var")))),
- unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
- callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
+ cxxMemberCallExpr(
+ callee(cxxMethodDecl(hasName("data"))),
+ on(declRefExpr(to(
+ varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
+ unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
+ callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
.bind("data"),
new VerifyIdIsBoundTo<Expr>("data", 1)));
@@ -4672,12 +4955,12 @@ TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
" v.data();"
" v.size();"
"}",
- memberCallExpr(
- callee(methodDecl(hasName("data"))),
- on(declRefExpr(to(varDecl(hasType(recordDecl(hasName("StringRef"))))
- .bind("var")))),
- unless(hasAncestor(stmt(hasDescendant(memberCallExpr(
- callee(methodDecl(anyOf(hasName("size"), hasName("length")))),
+ cxxMemberCallExpr(
+ callee(cxxMethodDecl(hasName("data"))),
+ on(declRefExpr(to(
+ varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
+ unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
+ callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
.bind("data")));
}
@@ -4687,6 +4970,13 @@ TEST(TypeDefDeclMatcher, Match) {
typedefDecl(hasName("typedefDeclTest"))));
}
+TEST(IsInlineMatcher, IsInline) {
+ EXPECT_TRUE(matches("void g(); inline void f();",
+ functionDecl(isInline(), hasName("f"))));
+ EXPECT_TRUE(matches("namespace n { inline namespace m {} }",
+ namespaceDecl(isInline(), hasName("m"))));
+}
+
// FIXME: Figure out how to specify paths so the following tests pass on Windows.
#ifndef LLVM_ON_WIN32
@@ -4774,6 +5064,9 @@ TEST(ObjCMessageExprMatcher, SimpleExprs) {
objcMessageExpr(hasSelector("contents"), hasUnarySelector())));
EXPECT_TRUE(matchesObjC(
Objc1String,
+ objcMessageExpr(hasSelector("contents"), numSelectorArgs(0))));
+ EXPECT_TRUE(matchesObjC(
+ Objc1String,
objcMessageExpr(matchesSelector("uppercase*"),
argumentCountIs(0)
)));
OpenPOWER on IntegriCloud