aboutsummaryrefslogtreecommitdiff
path: root/unittests/ASTMatchers/ASTMatchersTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/ASTMatchers/ASTMatchersTest.cpp')
-rw-r--r--unittests/ASTMatchers/ASTMatchersTest.cpp257
1 files changed, 257 insertions, 0 deletions
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index cf37c7d27a9c..adf0e9479f08 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -1099,6 +1099,12 @@ TEST(Returns, MatchesReturnTypes) {
function(returns(hasDeclaration(record(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())));
+}
+
TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
method(hasAnyParameter(hasType(record(hasName("X")))))));
@@ -2023,6 +2029,28 @@ TEST(IsConstQualified, DoesNotMatchInappropriately) {
variable(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())));
+}
+TEST(CastExpression, MatchesImplicitCasts) {
+ // This test creates an implicit cast from int to char.
+ EXPECT_TRUE(matches("char c = 0;", expression(castExpr())));
+ // This test creates an implicit cast from lvalue to rvalue.
+ EXPECT_TRUE(matches("char c = 0, d = c;", expression(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())));
+}
+
TEST(ReinterpretCast, MatchesSimpleCase) {
EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
expression(reinterpretCast())));
@@ -2089,6 +2117,201 @@ TEST(HasDestinationType, MatchesSimpleCase) {
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())))));
+ // This test creates an implicit array-to-pointer cast.
+ EXPECT_TRUE(matches("int arr[3]; int *p = arr;",
+ expression(implicitCast(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()))))));
+ // This test creates an implicit array-to-pointer cast.
+ EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
+ expression(implicitCast(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()))));
+ // This test creates an implicit cast from int to char.
+ EXPECT_TRUE(matches("char c = 0;",
+ variable(hasInitializer(implicitCast()))));
+ // This test creates an implicit array-to-pointer cast.
+ EXPECT_TRUE(matches("int arr[6]; int *p = arr;",
+ variable(hasInitializer(implicitCast()))));
+}
+
+TEST(ImplicitCast, DoesNotMatchIncorrectly) {
+ // This test verifies that implicitCast() 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()))));
+ EXPECT_TRUE(notMatches("int x = 0, &y = x;",
+ variable(hasInitializer(implicitCast()))));
+
+ EXPECT_TRUE(notMatches("int x = 0; double d = (double) x;",
+ variable(hasInitializer(implicitCast()))));
+ EXPECT_TRUE(notMatches("const int *p; int *q = const_cast<int *>(p);",
+ variable(hasInitializer(implicitCast()))));
+
+ EXPECT_TRUE(notMatches("int x = (0);",
+ variable(hasInitializer(implicitCast()))));
+}
+
+TEST(IgnoringImpCasts, MatchesImpCasts) {
+ // This test checks that ignoringImpCasts matches when implicit casts are
+ // 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")))))))));
+ // This test creates an implict cast from int to char.
+ EXPECT_TRUE(matches("char x = 0;",
+ variable(hasInitializer(ignoringImpCasts(
+ integerLiteral(equals(0)))))));
+}
+
+TEST(IgnoringImpCasts, DoesNotMatchIncorrectly) {
+ // These tests verify that ignoringImpCasts does not match if the inner
+ // 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(
+ unless(anything()))))));
+ EXPECT_TRUE(notMatches("int x; int y = x;",
+ variable(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())))));
+ EXPECT_TRUE(notMatches("int i = (0);",
+ variable(hasInitializer(ignoringImpCasts(
+ integerLiteral())))));
+ EXPECT_TRUE(notMatches("float i = (float)0;",
+ variable(hasInitializer(ignoringImpCasts(
+ integerLiteral())))));
+ EXPECT_TRUE(notMatches("float i = float(0);",
+ variable(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")))))))));
+}
+
+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)))))));
+ EXPECT_TRUE(matches("int x = (((((0)))));",
+ variable(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)))))));
+
+ EXPECT_TRUE(matches("char x = (char)0;",
+ variable(hasInitializer(ignoringParenCasts(
+ integerLiteral(equals(0)))))));
+ EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
+ variable(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)))))));
+}
+
+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(
+ 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(
+ unless(anything()))))));
+
+ EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
+ variable(hasInitializer(ignoringParenCasts(
+ unless(anything()))))));
+}
+
+TEST(IgnoringParenAndImpCasts, MatchesParenImpCasts) {
+ // This test checks that ignoringParenAndImpCasts matches when
+ // parentheses and/or implicit casts are 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(ignoringParenImpCasts(
+ declarationReference(to(variable(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)))))));
+}
+
+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")))))))));
+ EXPECT_TRUE(matches("int x = 0;",
+ variable(hasInitializer(ignoringParenImpCasts(
+ integerLiteral(equals(0)))))));
+}
+
+TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {
+ // These tests verify that ignoringParenImpCasts does not match if
+ // the inner matcher does not match.
+ // This test creates an implicit cast.
+ EXPECT_TRUE(notMatches("char c = ((3));",
+ variable(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())))));
+ EXPECT_TRUE(notMatches("float y = (float)0;",
+ variable(hasInitializer(ignoringParenImpCasts(
+ integerLiteral())))));
+ EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
+ variable(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; }",
@@ -2154,6 +2377,40 @@ TEST(UsingDeclaration, ThroughUsingDeclaration) {
declarationReference(throughUsingDecl(anything()))));
}
+TEST(SingleDecl, IsSingleDecl) {
+ StatementMatcher SingleDeclStmt =
+ declarationStatement(hasSingleDecl(variable(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;}",
+ SingleDeclStmt));
+}
+
+TEST(DeclStmt, ContainsDeclaration) {
+ DeclarationMatcher MatchesInit = variable(hasInitializer(anything()));
+
+ EXPECT_TRUE(matches("void f() {int a = 4;}",
+ declarationStatement(containsDeclaration(0,
+ MatchesInit))));
+ EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
+ declarationStatement(containsDeclaration(0, MatchesInit),
+ containsDeclaration(1,
+ MatchesInit))));
+ unsigned WrongIndex = 42;
+ EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
+ declarationStatement(containsDeclaration(WrongIndex,
+ MatchesInit))));
+}
+
+TEST(DeclCount, DeclCountIsCorrect) {
+ EXPECT_TRUE(matches("void f() {int i,j;}",
+ declarationStatement(declCountIs(2))));
+ EXPECT_TRUE(notMatches("void f() {int i,j; int k;}",
+ declarationStatement(declCountIs(3))));
+ EXPECT_TRUE(notMatches("void f() {int i,j, k, l;}",
+ declarationStatement(declCountIs(3))));
+}
+
TEST(While, MatchesWhileLoops) {
EXPECT_TRUE(notMatches("void x() {}", whileStmt()));
EXPECT_TRUE(matches("void x() { while(true); }", whileStmt()));