2891 lines · cpp
1//== unittests/ASTMatchers/ASTMatchersNodeTest.cpp - AST matcher unit tests ==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ASTMatchersTest.h"10#include "clang/AST/PrettyPrinter.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/ASTMatchers/ASTMatchers.h"13#include "clang/Tooling/Tooling.h"14#include "llvm/TargetParser/Host.h"15#include "llvm/TargetParser/Triple.h"16#include "gtest/gtest.h"17 18namespace clang {19namespace ast_matchers {20 21TEST_P(ASTMatchersTest, Decl_CXX) {22 if (!GetParam().isCXX()) {23 // FIXME: Add a test for `decl()` that does not depend on C++.24 return;25 }26 EXPECT_TRUE(notMatches("", decl(usingDecl())));27 EXPECT_TRUE(28 matches("namespace x { class X {}; } using x::X;", decl(usingDecl())));29}30 31TEST_P(ASTMatchersTest, NameableDeclaration_MatchesVariousDecls) {32 DeclarationMatcher NamedX = namedDecl(hasName("X"));33 EXPECT_TRUE(matches("typedef int X;", NamedX));34 EXPECT_TRUE(matches("int X;", NamedX));35 EXPECT_TRUE(matches("void foo() { int X; }", NamedX));36 EXPECT_TRUE(matches("enum X { A, B, C };", NamedX));37 38 EXPECT_TRUE(notMatches("#define X 1", NamedX));39}40 41TEST_P(ASTMatchersTest, NamedDecl_CXX) {42 if (!GetParam().isCXX()) {43 return;44 }45 DeclarationMatcher NamedX = namedDecl(hasName("X"));46 EXPECT_TRUE(matches("class foo { virtual void X(); };", NamedX));47 EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", NamedX));48 EXPECT_TRUE(matches("namespace X { }", NamedX));49}50 51TEST_P(ASTMatchersTest, MatchesNameRE) {52 DeclarationMatcher NamedX = namedDecl(matchesName("::X"));53 EXPECT_TRUE(matches("typedef int Xa;", NamedX));54 EXPECT_TRUE(matches("int Xb;", NamedX));55 EXPECT_TRUE(matches("void foo() { int Xgh; }", NamedX));56 EXPECT_TRUE(matches("enum X { A, B, C };", NamedX));57 58 EXPECT_TRUE(notMatches("#define Xkl 1", NamedX));59 60 DeclarationMatcher StartsWithNo = namedDecl(matchesName("::no"));61 EXPECT_TRUE(matches("int no_foo;", StartsWithNo));62 63 DeclarationMatcher Abc = namedDecl(matchesName("a.*b.*c"));64 EXPECT_TRUE(matches("int abc;", Abc));65 EXPECT_TRUE(matches("int aFOObBARc;", Abc));66 EXPECT_TRUE(notMatches("int cab;", Abc));67 EXPECT_TRUE(matches("int cabc;", Abc));68 69 DeclarationMatcher StartsWithK = namedDecl(matchesName(":k[^:]*$"));70 EXPECT_TRUE(matches("int k;", StartsWithK));71 EXPECT_TRUE(matches("int kAbc;", StartsWithK));72}73 74TEST_P(ASTMatchersTest, MatchesNameRE_CXX) {75 if (!GetParam().isCXX()) {76 return;77 }78 DeclarationMatcher NamedX = namedDecl(matchesName("::X"));79 EXPECT_TRUE(matches("class foo { virtual void Xc(); };", NamedX));80 EXPECT_TRUE(matches("void foo() try { } catch(int Xdef) { }", NamedX));81 EXPECT_TRUE(matches("namespace Xij { }", NamedX));82 83 DeclarationMatcher StartsWithNo = namedDecl(matchesName("::no"));84 EXPECT_TRUE(matches("class foo { virtual void nobody(); };", StartsWithNo));85 86 DeclarationMatcher StartsWithK = namedDecl(matchesName(":k[^:]*$"));87 EXPECT_TRUE(matches("namespace x { int kTest; }", StartsWithK));88 EXPECT_TRUE(matches("class C { int k; };", StartsWithK));89 EXPECT_TRUE(notMatches("class C { int ckc; };", StartsWithK));90 EXPECT_TRUE(notMatches("int K;", StartsWithK));91 92 DeclarationMatcher StartsWithKIgnoreCase =93 namedDecl(matchesName(":k[^:]*$", llvm::Regex::IgnoreCase));94 EXPECT_TRUE(matches("int k;", StartsWithKIgnoreCase));95 EXPECT_TRUE(matches("int K;", StartsWithKIgnoreCase));96}97 98TEST_P(ASTMatchersTest, DeclarationMatcher_MatchClass) {99 if (!GetParam().isCXX()) {100 return;101 }102 103 DeclarationMatcher ClassX = recordDecl(recordDecl(hasName("X")));104 EXPECT_TRUE(matches("class X;", ClassX));105 EXPECT_TRUE(matches("class X {};", ClassX));106 EXPECT_TRUE(matches("template<class T> class X {};", ClassX));107 EXPECT_TRUE(notMatches("", ClassX));108}109 110TEST_P(ASTMatchersTest, TranslationUnitDecl) {111 if (!GetParam().isCXX()) {112 // FIXME: Add a test for `translationUnitDecl()` that does not depend on113 // C++.114 return;115 }116 StringRef Code = "int MyVar1;\n"117 "namespace NameSpace {\n"118 "int MyVar2;\n"119 "} // namespace NameSpace\n";120 EXPECT_TRUE(matches(121 Code, varDecl(hasName("MyVar1"), hasDeclContext(translationUnitDecl()))));122 EXPECT_FALSE(matches(123 Code, varDecl(hasName("MyVar2"), hasDeclContext(translationUnitDecl()))));124 EXPECT_TRUE(matches(125 Code,126 varDecl(hasName("MyVar2"),127 hasDeclContext(decl(hasDeclContext(translationUnitDecl()))))));128}129 130TEST_P(ASTMatchersTest, LinkageSpecDecl) {131 if (!GetParam().isCXX()) {132 return;133 }134 EXPECT_TRUE(matches("extern \"C\" { void foo() {}; }", linkageSpecDecl()));135 EXPECT_TRUE(notMatches("void foo() {};", linkageSpecDecl()));136}137 138TEST_P(ASTMatchersTest, ClassTemplateDecl_DoesNotMatchClass) {139 if (!GetParam().isCXX()) {140 return;141 }142 DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));143 EXPECT_TRUE(notMatches("class X;", ClassX));144 EXPECT_TRUE(notMatches("class X {};", ClassX));145}146 147TEST_P(ASTMatchersTest, ClassTemplateDecl_MatchesClassTemplate) {148 if (!GetParam().isCXX()) {149 return;150 }151 DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));152 EXPECT_TRUE(matches("template<typename T> class X {};", ClassX));153 EXPECT_TRUE(matches("class Z { template<class T> class X {}; };", ClassX));154}155 156TEST_P(ASTMatchersTest,157 ClassTemplateDecl_DoesNotMatchClassTemplateExplicitSpecialization) {158 if (!GetParam().isCXX()) {159 return;160 }161 EXPECT_TRUE(notMatches(162 "template<typename T> class X { };"163 "template<> class X<int> { int a; };",164 classTemplateDecl(hasName("X"), hasDescendant(fieldDecl(hasName("a"))))));165}166 167TEST_P(ASTMatchersTest,168 ClassTemplateDecl_DoesNotMatchClassTemplatePartialSpecialization) {169 if (!GetParam().isCXX()) {170 return;171 }172 EXPECT_TRUE(notMatches(173 "template<typename T, typename U> class X { };"174 "template<typename T> class X<T, int> { int a; };",175 classTemplateDecl(hasName("X"), hasDescendant(fieldDecl(hasName("a"))))));176}177 178TEST(ASTMatchersTestCUDA, CUDAKernelCallExpr) {179 EXPECT_TRUE(matchesWithCuda("__global__ void f() { }"180 "void g() { f<<<1, 2>>>(); }",181 cudaKernelCallExpr()));182 EXPECT_TRUE(notMatchesWithCuda("void f() {}", cudaKernelCallExpr()));183}184 185TEST(ASTMatchersTestCUDA, HasAttrCUDA) {186 EXPECT_TRUE(matchesWithCuda("__attribute__((device)) void f() {}",187 hasAttr(clang::attr::CUDADevice)));188 EXPECT_FALSE(notMatchesWithCuda("__attribute__((global)) void f() {}",189 hasAttr(clang::attr::CUDAGlobal)));190}191 192TEST_P(ASTMatchersTest, ExportDecl) {193 if (!GetParam().isCXX20OrLater()) {194 return;195 }196 const std::string moduleHeader = "module;export module ast_matcher_test;";197 EXPECT_TRUE(matches(moduleHeader + "export void foo();",198 exportDecl(has(functionDecl()))));199 EXPECT_TRUE(matches(moduleHeader + "export { void foo(); int v; }",200 exportDecl(has(functionDecl()))));201 EXPECT_TRUE(matches(moduleHeader + "export { void foo(); int v; }",202 exportDecl(has(varDecl()))));203 EXPECT_TRUE(matches(moduleHeader + "export namespace aa { void foo(); }",204 exportDecl(has(namespaceDecl()))));205}206 207TEST_P(ASTMatchersTest, ValueDecl) {208 if (!GetParam().isCXX()) {209 // FIXME: Fix this test in non-C++ language modes.210 return;211 }212 EXPECT_TRUE(matches("enum EnumType { EnumValue };",213 valueDecl(hasType(asString("enum EnumType")))));214 EXPECT_TRUE(matches("void FunctionDecl();",215 valueDecl(hasType(asString("void (void)")))));216}217 218TEST_P(ASTMatchersTest, FriendDecl) {219 if (!GetParam().isCXX()) {220 return;221 }222 EXPECT_TRUE(matches("class Y { friend class X; };",223 friendDecl(hasType(asString("class X")))));224 EXPECT_TRUE(matches("class Y { friend class X; };",225 friendDecl(hasType(recordDecl(hasName("X"))))));226 227 EXPECT_TRUE(matches("class Y { friend void f(); };",228 functionDecl(hasName("f"), hasParent(friendDecl()))));229}230 231TEST_P(ASTMatchersTest, EnumDecl_DoesNotMatchClasses) {232 if (!GetParam().isCXX()) {233 return;234 }235 EXPECT_TRUE(notMatches("class X {};", enumDecl(hasName("X"))));236}237 238TEST_P(ASTMatchersTest, EnumDecl_MatchesEnums) {239 if (!GetParam().isCXX()) {240 // FIXME: Fix this test in non-C++ language modes.241 return;242 }243 EXPECT_TRUE(matches("enum X {};", enumDecl(hasName("X"))));244}245 246TEST_P(ASTMatchersTest, EnumConstantDecl) {247 if (!GetParam().isCXX()) {248 // FIXME: Fix this test in non-C++ language modes.249 return;250 }251 DeclarationMatcher Matcher = enumConstantDecl(hasName("A"));252 EXPECT_TRUE(matches("enum X{ A };", Matcher));253 EXPECT_TRUE(notMatches("enum X{ B };", Matcher));254 EXPECT_TRUE(notMatches("enum X {};", Matcher));255}256 257TEST_P(ASTMatchersTest, TagDecl) {258 if (!GetParam().isCXX()) {259 // FIXME: Fix this test in non-C++ language modes.260 return;261 }262 EXPECT_TRUE(matches("struct X {};", tagDecl(hasName("X"))));263 EXPECT_TRUE(matches("union U {};", tagDecl(hasName("U"))));264 EXPECT_TRUE(matches("enum E {};", tagDecl(hasName("E"))));265}266 267TEST_P(ASTMatchersTest, TagDecl_CXX) {268 if (!GetParam().isCXX()) {269 return;270 }271 EXPECT_TRUE(matches("class C {};", tagDecl(hasName("C"))));272}273 274TEST_P(ASTMatchersTest, UnresolvedLookupExpr) {275 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {276 // FIXME: Fix this test to work with delayed template parsing.277 return;278 }279 280 EXPECT_TRUE(matches("template<typename T>"281 "T foo() { T a; return a; }"282 "template<typename T>"283 "void bar() {"284 " foo<T>();"285 "}",286 unresolvedLookupExpr()));287}288 289TEST_P(ASTMatchersTest, UsesADL) {290 if (!GetParam().isCXX()) {291 return;292 }293 294 StatementMatcher ADLMatch = callExpr(usesADL());295 StatementMatcher ADLMatchOper = cxxOperatorCallExpr(usesADL());296 StringRef NS_Str = R"cpp(297 namespace NS {298 struct X {};299 void f(X);300 void operator+(X, X);301 }302 struct MyX {};303 void f(...);304 void operator+(MyX, MyX);305)cpp";306 307 auto MkStr = [&](StringRef Body) {308 return (NS_Str + "void test_fn() { " + Body + " }").str();309 };310 311 EXPECT_TRUE(matches(MkStr("NS::X x; f(x);"), ADLMatch));312 EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::f(x);"), ADLMatch));313 EXPECT_TRUE(notMatches(MkStr("MyX x; f(x);"), ADLMatch));314 EXPECT_TRUE(notMatches(MkStr("NS::X x; using NS::f; f(x);"), ADLMatch));315 316 // Operator call expressions317 EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatch));318 EXPECT_TRUE(matches(MkStr("NS::X x; x + x;"), ADLMatchOper));319 EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatch));320 EXPECT_TRUE(notMatches(MkStr("MyX x; x + x;"), ADLMatchOper));321 EXPECT_TRUE(matches(MkStr("NS::X x; operator+(x, x);"), ADLMatch));322 EXPECT_TRUE(notMatches(MkStr("NS::X x; NS::operator+(x, x);"), ADLMatch));323}324 325TEST_P(ASTMatchersTest, CallExpr_CXX) {326 if (!GetParam().isCXX()) {327 // FIXME: Add a test for `callExpr()` that does not depend on C++.328 return;329 }330 // FIXME: Do we want to overload Call() to directly take331 // Matcher<Decl>, too?332 StatementMatcher MethodX =333 callExpr(hasDeclaration(cxxMethodDecl(hasName("x"))));334 335 EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));336 EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));337 338 StatementMatcher MethodOnY =339 cxxMemberCallExpr(on(hasType(recordDecl(hasName("Y")))));340 341 EXPECT_TRUE(matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",342 MethodOnY));343 EXPECT_TRUE(matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",344 MethodOnY));345 EXPECT_TRUE(notMatches(346 "class Y { public: void x(); }; void z(Y *&y) { y->x(); }", MethodOnY));347 EXPECT_TRUE(notMatches(348 "class Y { public: void x(); }; void z(Y y[]) { y->x(); }", MethodOnY));349 EXPECT_TRUE(notMatches(350 "class Y { public: void x(); }; void z() { Y *y; y->x(); }", MethodOnY));351 352 StatementMatcher MethodOnYPointer =353 cxxMemberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));354 355 EXPECT_TRUE(356 matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",357 MethodOnYPointer));358 EXPECT_TRUE(359 matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",360 MethodOnYPointer));361 EXPECT_TRUE(362 matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",363 MethodOnYPointer));364 EXPECT_TRUE(365 notMatches("class Y { public: void x(); }; void z() { Y y; y.x(); }",366 MethodOnYPointer));367 EXPECT_TRUE(368 notMatches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",369 MethodOnYPointer));370}371 372TEST_P(ASTMatchersTest, LambdaExpr) {373 if (!GetParam().isCXX11OrLater()) {374 return;375 }376 EXPECT_TRUE(matches("auto f = [] (int i) { return i; };", lambdaExpr()));377}378 379TEST_P(ASTMatchersTest, CXXForRangeStmt) {380 EXPECT_TRUE(381 notMatches("void f() { for (int i; i<5; ++i); }", cxxForRangeStmt()));382}383 384TEST_P(ASTMatchersTest, CXXForRangeStmt_CXX11) {385 if (!GetParam().isCXX11OrLater()) {386 return;387 }388 EXPECT_TRUE(matches("int as[] = { 1, 2, 3 };"389 "void f() { for (auto &a : as); }",390 cxxForRangeStmt()));391}392 393TEST_P(ASTMatchersTest, SubstNonTypeTemplateParmExpr) {394 if (!GetParam().isCXX()) {395 return;396 }397 EXPECT_FALSE(matches("template<int N>\n"398 "struct A { static const int n = 0; };\n"399 "struct B : public A<42> {};",400 traverse(TK_AsIs, substNonTypeTemplateParmExpr())));401 EXPECT_TRUE(matches("template<int N>\n"402 "struct A { static const int n = N; };\n"403 "struct B : public A<42> {};",404 traverse(TK_AsIs, substNonTypeTemplateParmExpr())));405}406 407TEST_P(ASTMatchersTest, NonTypeTemplateParmDecl) {408 if (!GetParam().isCXX()) {409 return;410 }411 EXPECT_TRUE(matches("template <int N> void f();",412 nonTypeTemplateParmDecl(hasName("N"))));413 EXPECT_TRUE(414 notMatches("template <typename T> void f();", nonTypeTemplateParmDecl()));415}416 417TEST_P(ASTMatchersTest, TemplateTypeParmDecl) {418 if (!GetParam().isCXX()) {419 return;420 }421 EXPECT_TRUE(matches("template <typename T> void f();",422 templateTypeParmDecl(hasName("T"))));423 EXPECT_TRUE(notMatches("template <int N> void f();", templateTypeParmDecl()));424}425 426TEST_P(ASTMatchersTest, TemplateTemplateParmDecl) {427 if (!GetParam().isCXX())428 return;429 EXPECT_TRUE(matches("template <template <typename> class Z> void f();",430 templateTemplateParmDecl(hasName("Z"))));431 EXPECT_TRUE(notMatches("template <typename, int> void f();",432 templateTemplateParmDecl()));433}434 435TEST_P(ASTMatchersTest, UserDefinedLiteral) {436 if (!GetParam().isCXX11OrLater()) {437 return;438 }439 EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"440 " return i + 1;"441 "}"442 "char c = 'a'_inc;",443 userDefinedLiteral()));444}445 446TEST_P(ASTMatchersTest, FlowControl) {447 EXPECT_TRUE(matches("void f() { while(1) { break; } }", breakStmt()));448 EXPECT_TRUE(matches("void f() { while(1) { continue; } }", continueStmt()));449 EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", gotoStmt()));450 EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}",451 labelStmt(hasDeclaration(labelDecl(hasName("FOO"))))));452 EXPECT_TRUE(matches("void f() { FOO: ; void *ptr = &&FOO; goto *ptr; }",453 addrLabelExpr()));454 EXPECT_TRUE(matches("void f() { return; }", returnStmt()));455}456 457TEST_P(ASTMatchersTest, CXXOperatorCallExpr) {458 if (!GetParam().isCXX()) {459 return;460 }461 462 StatementMatcher OpCall = cxxOperatorCallExpr();463 // Unary operator464 EXPECT_TRUE(matches("class Y { }; "465 "bool operator!(Y x) { return false; }; "466 "Y y; bool c = !y;",467 OpCall));468 // No match -- special operators like "new", "delete"469 // FIXME: operator new takes size_t, for which we need stddef.h, for which470 // we need to figure out include paths in the test.471 // EXPECT_TRUE(NotMatches("#include <stddef.h>\n"472 // "class Y { }; "473 // "void *operator new(size_t size) { return 0; } "474 // "Y *y = new Y;", OpCall));475 EXPECT_TRUE(notMatches("class Y { }; "476 "void operator delete(void *p) { } "477 "void a() {Y *y = new Y; delete y;}",478 OpCall));479 // Binary operator480 EXPECT_TRUE(matches("class Y { }; "481 "bool operator&&(Y x, Y y) { return true; }; "482 "Y a; Y b; bool c = a && b;",483 OpCall));484 // No match -- normal operator, not an overloaded one.485 EXPECT_TRUE(notMatches("bool x = true, y = true; bool t = x && y;", OpCall));486 EXPECT_TRUE(notMatches("int t = 5 << 2;", OpCall));487}488 489TEST_P(ASTMatchersTest, FoldExpr) {490 if (!GetParam().isCXX() || !GetParam().isCXX17OrLater()) {491 return;492 }493 494 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "495 "return (0 + ... + args); }",496 cxxFoldExpr()));497 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "498 "return (args + ...); }",499 cxxFoldExpr()));500}501 502TEST_P(ASTMatchersTest, ThisPointerType) {503 if (!GetParam().isCXX()) {504 return;505 }506 507 StatementMatcher MethodOnY = traverse(508 TK_AsIs, cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y")))));509 510 EXPECT_TRUE(matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",511 MethodOnY));512 EXPECT_TRUE(matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",513 MethodOnY));514 EXPECT_TRUE(matches(515 "class Y { public: void x(); }; void z(Y *&y) { y->x(); }", MethodOnY));516 EXPECT_TRUE(matches(517 "class Y { public: void x(); }; void z(Y y[]) { y->x(); }", MethodOnY));518 EXPECT_TRUE(matches(519 "class Y { public: void x(); }; void z() { Y *y; y->x(); }", MethodOnY));520 521 EXPECT_TRUE(matches("class Y {"522 " public: virtual void x();"523 "};"524 "class X : public Y {"525 " public: virtual void x();"526 "};"527 "void z() { X *x; x->Y::x(); }",528 MethodOnY));529}530 531TEST_P(ASTMatchersTest, DeclRefExpr) {532 if (!GetParam().isCXX()) {533 // FIXME: Add a test for `declRefExpr()` that does not depend on C++.534 return;535 }536 StatementMatcher Reference = declRefExpr(to(varDecl(hasInitializer(537 cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));538 539 EXPECT_TRUE(matches("class Y {"540 " public:"541 " bool x() const;"542 "};"543 "void z(const Y &y) {"544 " bool b = y.x();"545 " if (b) {}"546 "}",547 Reference));548 549 EXPECT_TRUE(notMatches("class Y {"550 " public:"551 " bool x() const;"552 "};"553 "void z(const Y &y) {"554 " bool b = y.x();"555 "}",556 Reference));557}558 559TEST_P(ASTMatchersTest, DependentScopeDeclRefExpr) {560 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {561 // FIXME: Fix this test to work with delayed template parsing.562 return;563 }564 565 EXPECT_TRUE(matches("template <class T> class X : T { void f() { T::v; } };",566 dependentScopeDeclRefExpr()));567 568 EXPECT_TRUE(569 matches("template <typename T> struct S { static T Foo; };"570 "template <typename T> void declToImport() { (void)S<T>::Foo; }",571 dependentScopeDeclRefExpr()));572}573 574TEST_P(ASTMatchersTest, CXXMemberCallExpr) {575 if (!GetParam().isCXX()) {576 return;577 }578 StatementMatcher CallOnVariableY =579 cxxMemberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));580 581 EXPECT_TRUE(matches("class Y { public: void x() { Y y; y.x(); } };",582 CallOnVariableY));583 EXPECT_TRUE(matches("class Y { public: void x() const { Y y; y.x(); } };",584 CallOnVariableY));585 EXPECT_TRUE(matches("class Y { public: void x(); };"586 "class X : public Y { void z() { X y; y.x(); } };",587 CallOnVariableY));588 EXPECT_TRUE(matches("class Y { public: void x(); };"589 "class X : public Y { void z() { X *y; y->x(); } };",590 CallOnVariableY));591 EXPECT_TRUE(notMatches(592 "class Y { public: void x(); };"593 "class X : public Y { void z() { unsigned long y; ((X*)y)->x(); } };",594 CallOnVariableY));595}596 597TEST_P(ASTMatchersTest, UnaryExprOrTypeTraitExpr) {598 EXPECT_TRUE(599 matches("void x() { int a = sizeof(a); }", unaryExprOrTypeTraitExpr()));600}601 602TEST_P(ASTMatchersTest, AlignOfExpr) {603 EXPECT_TRUE(604 notMatches("void x() { int a = sizeof(a); }", alignOfExpr(anything())));605 // FIXME: Uncomment once alignof is enabled.606 // EXPECT_TRUE(matches("void x() { int a = alignof(a); }",607 // unaryExprOrTypeTraitExpr()));608 // EXPECT_TRUE(notMatches("void x() { int a = alignof(a); }",609 // sizeOfExpr()));610}611 612TEST_P(ASTMatchersTest, MemberExpr_DoesNotMatchClasses) {613 if (!GetParam().isCXX()) {614 return;615 }616 EXPECT_TRUE(notMatches("class Y { void x() {} };", memberExpr()));617 EXPECT_TRUE(notMatches("class Y { void x() {} };", unresolvedMemberExpr()));618 EXPECT_TRUE(619 notMatches("class Y { void x() {} };", cxxDependentScopeMemberExpr()));620}621 622TEST_P(ASTMatchersTest, MemberExpr_MatchesMemberFunctionCall) {623 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {624 // FIXME: Fix this test to work with delayed template parsing.625 return;626 }627 EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr()));628 EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };",629 unresolvedMemberExpr()));630 EXPECT_TRUE(matches("template <class T> void x() { T t; t.f(); }",631 cxxDependentScopeMemberExpr()));632}633 634TEST_P(ASTMatchersTest, MemberExpr_MatchesVariable) {635 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {636 // FIXME: Fix this test to work with delayed template parsing.637 return;638 }639 EXPECT_TRUE(640 matches("class Y { void x() { this->y; } int y; };", memberExpr()));641 EXPECT_TRUE(matches("class Y { void x() { y; } int y; };", memberExpr()));642 EXPECT_TRUE(643 matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));644 EXPECT_TRUE(matches("template <class T>"645 "class X : T { void f() { this->T::v; } };",646 cxxDependentScopeMemberExpr()));647 EXPECT_TRUE(matches("template <class T> class X : T { void f() { T::v; } };",648 dependentScopeDeclRefExpr()));649 EXPECT_TRUE(matches("template <class T> void x() { T t; t.v; }",650 cxxDependentScopeMemberExpr()));651}652 653TEST_P(ASTMatchersTest, MemberExpr_MatchesStaticVariable) {654 if (!GetParam().isCXX()) {655 return;656 }657 EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",658 memberExpr()));659 EXPECT_TRUE(660 notMatches("class Y { void x() { y; } static int y; };", memberExpr()));661 EXPECT_TRUE(notMatches("class Y { void x() { Y::y; } static int y; };",662 memberExpr()));663}664 665TEST_P(ASTMatchersTest, FunctionDecl) {666 StatementMatcher CallFunctionF = callExpr(callee(functionDecl(hasName("f"))));667 668 EXPECT_TRUE(matches("void f() { f(); }", CallFunctionF));669 EXPECT_TRUE(notMatches("void f() { }", CallFunctionF));670 671 EXPECT_TRUE(notMatches("void f(int);", functionDecl(isVariadic())));672 EXPECT_TRUE(notMatches("void f();", functionDecl(isVariadic())));673 EXPECT_TRUE(matches("void f(int, ...);", functionDecl(parameterCountIs(1))));674}675 676TEST_P(ASTMatchersTest, FunctionDecl_C) {677 if (!GetParam().isC()) {678 return;679 }680 EXPECT_TRUE(notMatches("void f();", functionDecl(isVariadic())));681 EXPECT_TRUE(matches("void f();", functionDecl(parameterCountIs(0))));682}683 684TEST_P(ASTMatchersTest, FunctionDecl_CXX) {685 if (!GetParam().isCXX()) {686 return;687 }688 689 StatementMatcher CallFunctionF = callExpr(callee(functionDecl(hasName("f"))));690 691 if (!GetParam().hasDelayedTemplateParsing()) {692 // FIXME: Fix this test to work with delayed template parsing.693 // Dependent contexts, but a non-dependent call.694 EXPECT_TRUE(695 matches("void f(); template <int N> void g() { f(); }", CallFunctionF));696 EXPECT_TRUE(697 matches("void f(); template <int N> struct S { void g() { f(); } };",698 CallFunctionF));699 }700 701 // Dependent calls don't match.702 EXPECT_TRUE(703 notMatches("void f(int); template <typename T> void g(T t) { f(t); }",704 CallFunctionF));705 EXPECT_TRUE(706 notMatches("void f(int);"707 "template <typename T> struct S { void g(T t) { f(t); } };",708 CallFunctionF));709 710 EXPECT_TRUE(matches("void f(...);", functionDecl(isVariadic())));711 EXPECT_TRUE(matches("void f(...);", functionDecl(parameterCountIs(0))));712}713 714TEST_P(ASTMatchersTest, FunctionDecl_CXX11) {715 if (!GetParam().isCXX11OrLater()) {716 return;717 }718 719 EXPECT_TRUE(notMatches("template <typename... Ts> void f(Ts...);",720 functionDecl(isVariadic())));721}722 723TEST_P(ASTMatchersTest,724 FunctionTemplateDecl_MatchesFunctionTemplateDeclarations) {725 if (!GetParam().isCXX()) {726 return;727 }728 EXPECT_TRUE(matches("template <typename T> void f(T t) {}",729 functionTemplateDecl(hasName("f"))));730}731 732TEST_P(ASTMatchersTest, FunctionTemplate_DoesNotMatchFunctionDeclarations) {733 EXPECT_TRUE(734 notMatches("void f(double d);", functionTemplateDecl(hasName("f"))));735 EXPECT_TRUE(736 notMatches("void f(int t) {}", functionTemplateDecl(hasName("f"))));737}738 739TEST_P(ASTMatchersTest,740 FunctionTemplateDecl_DoesNotMatchFunctionTemplateSpecializations) {741 if (!GetParam().isCXX()) {742 return;743 }744 EXPECT_TRUE(notMatches(745 "void g(); template <typename T> void f(T t) {}"746 "template <> void f(int t) { g(); }",747 functionTemplateDecl(hasName("f"), hasDescendant(declRefExpr(to(748 functionDecl(hasName("g"))))))));749}750 751TEST_P(ASTMatchersTest, ClassTemplateSpecializationDecl) {752 if (!GetParam().isCXX()) {753 return;754 }755 EXPECT_TRUE(matches("template<typename T> struct A {};"756 "template<> struct A<int> {};",757 classTemplateSpecializationDecl()));758 EXPECT_TRUE(matches("template<typename T> struct A {}; A<int> a;",759 classTemplateSpecializationDecl()));760 EXPECT_TRUE(notMatches("template<typename T> struct A {};",761 classTemplateSpecializationDecl()));762}763 764TEST_P(ASTMatchersTest, DeclaratorDecl) {765 EXPECT_TRUE(matches("int x;", declaratorDecl()));766 EXPECT_TRUE(notMatches("struct A {};", declaratorDecl()));767}768 769TEST_P(ASTMatchersTest, DeclaratorDecl_CXX) {770 if (!GetParam().isCXX()) {771 return;772 }773 EXPECT_TRUE(notMatches("class A {};", declaratorDecl()));774}775 776TEST_P(ASTMatchersTest, ParmVarDecl) {777 EXPECT_TRUE(matches("void f(int x);", parmVarDecl()));778 EXPECT_TRUE(notMatches("void f();", parmVarDecl()));779}780 781TEST_P(ASTMatchersTest, StaticAssertDecl) {782 if (!GetParam().isCXX11OrLater())783 return;784 785 EXPECT_TRUE(matches("static_assert(true, \"\");", staticAssertDecl()));786 EXPECT_TRUE(787 notMatches("constexpr bool staticassert(bool B, const char *M) "788 "{ return true; };\n void f() { staticassert(true, \"\"); }",789 staticAssertDecl()));790}791 792TEST_P(ASTMatchersTest, Matcher_ConstructorCall) {793 if (!GetParam().isCXX()) {794 return;795 }796 797 StatementMatcher Constructor = traverse(TK_AsIs, cxxConstructExpr());798 799 EXPECT_TRUE(800 matches("class X { public: X(); }; void x() { X x; }", Constructor));801 EXPECT_TRUE(matches("class X { public: X(); }; void x() { X x = X(); }",802 Constructor));803 EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x = 0; }",804 Constructor));805 EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor));806}807 808TEST_P(ASTMatchersTest, Match_ConstructorInitializers) {809 if (!GetParam().isCXX()) {810 return;811 }812 EXPECT_TRUE(matches("class C { int i; public: C(int ii) : i(ii) {} };",813 cxxCtorInitializer(forField(hasName("i")))));814}815 816TEST_P(ASTMatchersTest, Matcher_ThisExpr) {817 if (!GetParam().isCXX()) {818 return;819 }820 EXPECT_TRUE(821 matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));822 EXPECT_TRUE(823 notMatches("struct X { int f () { int a; return a; } };", cxxThisExpr()));824}825 826TEST_P(ASTMatchersTest, Matcher_BindTemporaryExpression) {827 if (!GetParam().isCXX()) {828 return;829 }830 831 StatementMatcher TempExpression = traverse(TK_AsIs, cxxBindTemporaryExpr());832 833 StringRef ClassString = "class string { public: string(); ~string(); }; ";834 835 EXPECT_TRUE(matches(836 ClassString + "string GetStringByValue();"837 "void FunctionTakesString(string s);"838 "void run() { FunctionTakesString(GetStringByValue()); }",839 TempExpression));840 841 EXPECT_TRUE(notMatches(ClassString +842 "string* GetStringPointer(); "843 "void FunctionTakesStringPtr(string* s);"844 "void run() {"845 " string* s = GetStringPointer();"846 " FunctionTakesStringPtr(GetStringPointer());"847 " FunctionTakesStringPtr(s);"848 "}",849 TempExpression));850 851 EXPECT_TRUE(notMatches("class no_dtor {};"852 "no_dtor GetObjByValue();"853 "void ConsumeObj(no_dtor param);"854 "void run() { ConsumeObj(GetObjByValue()); }",855 TempExpression));856}857 858TEST_P(ASTMatchersTest, MaterializeTemporaryExpr_MatchesTemporaryCXX11CXX14) {859 if (GetParam().Language != Lang_CXX11 && GetParam().Language != Lang_CXX14) {860 return;861 }862 863 StatementMatcher TempExpression =864 traverse(TK_AsIs, materializeTemporaryExpr());865 866 EXPECT_TRUE(matches("class string { public: string(); }; "867 "string GetStringByValue();"868 "void FunctionTakesString(string s);"869 "void run() { FunctionTakesString(GetStringByValue()); }",870 TempExpression));871}872 873TEST_P(ASTMatchersTest, MaterializeTemporaryExpr_MatchesTemporary) {874 if (!GetParam().isCXX()) {875 return;876 }877 878 StringRef ClassString = "class string { public: string(); int length(); }; ";879 StatementMatcher TempExpression =880 traverse(TK_AsIs, materializeTemporaryExpr());881 882 EXPECT_TRUE(notMatches(ClassString +883 "string* GetStringPointer(); "884 "void FunctionTakesStringPtr(string* s);"885 "void run() {"886 " string* s = GetStringPointer();"887 " FunctionTakesStringPtr(GetStringPointer());"888 " FunctionTakesStringPtr(s);"889 "}",890 TempExpression));891 892 EXPECT_TRUE(matches(ClassString +893 "string GetStringByValue();"894 "void run() { int k = GetStringByValue().length(); }",895 TempExpression));896 897 EXPECT_TRUE(notMatches(ClassString + "string GetStringByValue();"898 "void run() { GetStringByValue(); }",899 TempExpression));900}901 902TEST_P(ASTMatchersTest, Matcher_NewExpression) {903 if (!GetParam().isCXX()) {904 return;905 }906 907 StatementMatcher New = cxxNewExpr();908 909 EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }", New));910 EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X(); }", New));911 EXPECT_TRUE(912 matches("class X { public: X(int); }; void x() { new X(0); }", New));913 EXPECT_TRUE(matches("class X {}; void x(int) { new X; }", New));914}915 916TEST_P(ASTMatchersTest, Matcher_DeleteExpression) {917 if (!GetParam().isCXX()) {918 return;919 }920 EXPECT_TRUE(921 matches("struct A {}; void f(A* a) { delete a; }", cxxDeleteExpr()));922}923 924TEST_P(ASTMatchersTest, Matcher_NoexceptExpression) {925 if (!GetParam().isCXX11OrLater()) {926 return;927 }928 StatementMatcher NoExcept = cxxNoexceptExpr();929 EXPECT_TRUE(matches("void foo(); bool bar = noexcept(foo());", NoExcept));930 EXPECT_TRUE(931 matches("void foo() noexcept; bool bar = noexcept(foo());", NoExcept));932 EXPECT_TRUE(notMatches("void foo() noexcept;", NoExcept));933 EXPECT_TRUE(notMatches("void foo() noexcept(0+1);", NoExcept));934 EXPECT_TRUE(matches("void foo() noexcept(noexcept(1+1));", NoExcept));935}936 937TEST_P(ASTMatchersTest, Matcher_DefaultArgument) {938 if (!GetParam().isCXX()) {939 return;940 }941 StatementMatcher Arg = cxxDefaultArgExpr();942 EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));943 EXPECT_TRUE(944 matches("class X { void x(int, int = 0) { int y; x(y); } };", Arg));945 EXPECT_TRUE(notMatches("void x(int, int = 0) { int y; x(y, 0); }", Arg));946}947 948TEST_P(ASTMatchersTest, StringLiteral) {949 StatementMatcher Literal = stringLiteral();950 EXPECT_TRUE(matches("const char *s = \"string\";", Literal));951 // with escaped characters952 EXPECT_TRUE(matches("const char *s = \"\x05five\";", Literal));953 // no matching -- though the data type is the same, there is no string literal954 EXPECT_TRUE(notMatches("const char s[1] = {'a'};", Literal));955}956 957TEST_P(ASTMatchersTest, StringLiteral_CXX) {958 if (!GetParam().isCXX()) {959 return;960 }961 EXPECT_TRUE(matches("const wchar_t *s = L\"string\";", stringLiteral()));962}963 964TEST_P(ASTMatchersTest, CharacterLiteral) {965 EXPECT_TRUE(matches("const char c = 'c';", characterLiteral()));966 EXPECT_TRUE(notMatches("const char c = 0x1;", characterLiteral()));967}968 969TEST_P(ASTMatchersTest, CharacterLiteral_CXX) {970 if (!GetParam().isCXX()) {971 return;972 }973 // wide character974 EXPECT_TRUE(matches("const char c = L'c';", characterLiteral()));975 // wide character, Hex encoded, NOT MATCHED!976 EXPECT_TRUE(notMatches("const wchar_t c = 0x2126;", characterLiteral()));977}978 979TEST_P(ASTMatchersTest, IntegerLiteral) {980 StatementMatcher HasIntLiteral = integerLiteral();981 EXPECT_TRUE(matches("int i = 10;", HasIntLiteral));982 EXPECT_TRUE(matches("int i = 0x1AB;", HasIntLiteral));983 EXPECT_TRUE(matches("int i = 10L;", HasIntLiteral));984 EXPECT_TRUE(matches("int i = 10U;", HasIntLiteral));985 986 // Non-matching cases (character literals, float and double)987 EXPECT_TRUE(notMatches("int i = L'a';",988 HasIntLiteral)); // this is actually a character989 // literal cast to int990 EXPECT_TRUE(notMatches("int i = 'a';", HasIntLiteral));991 EXPECT_TRUE(notMatches("int i = 1e10;", HasIntLiteral));992 EXPECT_TRUE(notMatches("int i = 10.0;", HasIntLiteral));993 994 // Negative integers.995 EXPECT_TRUE(996 matches("int i = -10;",997 unaryOperator(hasOperatorName("-"),998 hasUnaryOperand(integerLiteral(equals(10))))));999}1000 1001TEST_P(ASTMatchersTest, FloatLiteral) {1002 StatementMatcher HasFloatLiteral = floatLiteral();1003 EXPECT_TRUE(matches("float i = 10.0;", HasFloatLiteral));1004 EXPECT_TRUE(matches("float i = 10.0f;", HasFloatLiteral));1005 EXPECT_TRUE(matches("double i = 10.0;", HasFloatLiteral));1006 EXPECT_TRUE(matches("double i = 10.0L;", HasFloatLiteral));1007 EXPECT_TRUE(matches("double i = 1e10;", HasFloatLiteral));1008 EXPECT_TRUE(matches("double i = 5.0;", floatLiteral(equals(5.0))));1009 EXPECT_TRUE(matches("double i = 5.0;", floatLiteral(equals(5.0f))));1010 EXPECT_TRUE(1011 matches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(5.0)))));1012 1013 EXPECT_TRUE(notMatches("float i = 10;", HasFloatLiteral));1014 EXPECT_TRUE(notMatches("double i = 5.0;", floatLiteral(equals(6.0))));1015 EXPECT_TRUE(notMatches("double i = 5.0;", floatLiteral(equals(6.0f))));1016 EXPECT_TRUE(1017 notMatches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(6.0)))));1018}1019 1020TEST_P(ASTMatchersTest, FixedPointLiterals) {1021 StatementMatcher HasFixedPointLiteral = fixedPointLiteral();1022 EXPECT_TRUE(matchesWithFixedpoint("_Fract i = 0.25r;", HasFixedPointLiteral));1023 EXPECT_TRUE(1024 matchesWithFixedpoint("_Fract i = 0.25hr;", HasFixedPointLiteral));1025 EXPECT_TRUE(1026 matchesWithFixedpoint("_Fract i = 0.25uhr;", HasFixedPointLiteral));1027 EXPECT_TRUE(1028 matchesWithFixedpoint("_Fract i = 0.25ur;", HasFixedPointLiteral));1029 EXPECT_TRUE(1030 matchesWithFixedpoint("_Fract i = 0.25lr;", HasFixedPointLiteral));1031 EXPECT_TRUE(1032 matchesWithFixedpoint("_Fract i = 0.25ulr;", HasFixedPointLiteral));1033 EXPECT_TRUE(matchesWithFixedpoint("_Accum i = 1.25k;", HasFixedPointLiteral));1034 EXPECT_TRUE(1035 matchesWithFixedpoint("_Accum i = 1.25hk;", HasFixedPointLiteral));1036 EXPECT_TRUE(1037 matchesWithFixedpoint("_Accum i = 1.25uhk;", HasFixedPointLiteral));1038 EXPECT_TRUE(1039 matchesWithFixedpoint("_Accum i = 1.25uk;", HasFixedPointLiteral));1040 EXPECT_TRUE(1041 matchesWithFixedpoint("_Accum i = 1.25lk;", HasFixedPointLiteral));1042 EXPECT_TRUE(1043 matchesWithFixedpoint("_Accum i = 1.25ulk;", HasFixedPointLiteral));1044 EXPECT_TRUE(matchesWithFixedpoint("_Accum decexp1 = 1.575e1k;",1045 HasFixedPointLiteral));1046 EXPECT_TRUE(1047 matchesWithFixedpoint("_Accum hex = 0x1.25fp2k;", HasFixedPointLiteral));1048 EXPECT_TRUE(matchesWithFixedpoint("_Sat long _Fract i = 0.25r;",1049 HasFixedPointLiteral));1050 EXPECT_TRUE(matchesWithFixedpoint("_Sat short _Accum i = 256.0k;",1051 HasFixedPointLiteral));1052 EXPECT_TRUE(matchesWithFixedpoint(1053 "_Accum i = 256.0k;",1054 fixedPointLiteral(equals(llvm::APInt(32, 0x800000, true)))));1055 EXPECT_TRUE(matchesWithFixedpoint(1056 "_Fract i = 0.25ulr;",1057 fixedPointLiteral(equals(llvm::APInt(32, 0x40000000, false)))));1058 EXPECT_TRUE(matchesWithFixedpoint(1059 "_Fract i = 0.5hr;",1060 fixedPointLiteral(equals(llvm::APInt(8, 0x40, true)))));1061 1062 EXPECT_TRUE(1063 notMatchesWithFixedpoint("short _Accum i = 2u;", HasFixedPointLiteral));1064 EXPECT_TRUE(1065 notMatchesWithFixedpoint("short _Accum i = 2;", HasFixedPointLiteral));1066 EXPECT_TRUE(1067 notMatchesWithFixedpoint("_Accum i = 1.25;", HasFixedPointLiteral));1068 EXPECT_TRUE(notMatchesWithFixedpoint("_Accum i = (double)(1.25 * 4.5i);",1069 HasFixedPointLiteral));1070 EXPECT_TRUE(notMatchesWithFixedpoint(1071 "_Accum i = 256.0k;",1072 fixedPointLiteral(equals(llvm::APInt(32, 0x800001, true)))));1073 EXPECT_TRUE(notMatchesWithFixedpoint(1074 "_Fract i = 0.25ulr;",1075 fixedPointLiteral(equals(llvm::APInt(32, 0x40000001, false)))));1076 EXPECT_TRUE(notMatchesWithFixedpoint(1077 "_Fract i = 0.5hr;",1078 fixedPointLiteral(equals(llvm::APInt(8, 0x41, true)))));1079}1080 1081TEST_P(ASTMatchersTest, CXXNullPtrLiteralExpr) {1082 if (!GetParam().isCXX11OrLater()) {1083 return;1084 }1085 EXPECT_TRUE(matches("int* i = nullptr;", cxxNullPtrLiteralExpr()));1086}1087 1088TEST_P(ASTMatchersTest, ChooseExpr) {1089 EXPECT_TRUE(matches("void f() { (void)__builtin_choose_expr(1, 2, 3); }",1090 chooseExpr()));1091}1092 1093TEST_P(ASTMatchersTest, ConvertVectorExpr) {1094 EXPECT_TRUE(matches(1095 "typedef double vector4double __attribute__((__vector_size__(32)));"1096 "typedef float vector4float __attribute__((__vector_size__(16)));"1097 "vector4float vf;"1098 "void f() { (void)__builtin_convertvector(vf, vector4double); }",1099 convertVectorExpr()));1100 EXPECT_TRUE(notMatches("void f() { (void)__builtin_choose_expr(1, 2, 3); }",1101 convertVectorExpr()));1102}1103 1104TEST_P(ASTMatchersTest, GNUNullExpr) {1105 if (!GetParam().isCXX()) {1106 return;1107 }1108 EXPECT_TRUE(matches("int* i = __null;", gnuNullExpr()));1109}1110 1111TEST_P(ASTMatchersTest, GenericSelectionExpr) {1112 EXPECT_TRUE(matches("void f() { (void)_Generic(1, int: 1, float: 2.0); }",1113 genericSelectionExpr()));1114}1115 1116TEST_P(ASTMatchersTest, AtomicExpr) {1117 EXPECT_TRUE(matches("void foo() { int *ptr; __atomic_load_n(ptr, 1); }",1118 atomicExpr()));1119}1120 1121TEST_P(ASTMatchersTest, Initializers_C99) {1122 if (!GetParam().isC99OrLater()) {1123 return;1124 }1125 EXPECT_TRUE(matches(1126 "void foo() { struct point { double x; double y; };"1127 " struct point ptarray[10] = "1128 " { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",1129 initListExpr(hasSyntacticForm(initListExpr(1130 has(designatedInitExpr(designatorCountIs(2),1131 hasDescendant(floatLiteral(equals(1.0))),1132 hasDescendant(integerLiteral(equals(2))))),1133 has(designatedInitExpr(designatorCountIs(2),1134 hasDescendant(floatLiteral(equals(2.0))),1135 hasDescendant(integerLiteral(equals(2))))),1136 has(designatedInitExpr(1137 designatorCountIs(2), hasDescendant(floatLiteral(equals(1.0))),1138 hasDescendant(integerLiteral(equals(0))))))))));1139}1140 1141TEST_P(ASTMatchersTest, Initializers_CXX) {1142 if (GetParam().Language != Lang_CXX03) {1143 // FIXME: Make this test pass with other C++ standard versions.1144 return;1145 }1146 EXPECT_TRUE(matches(1147 "void foo() { struct point { double x; double y; };"1148 " struct point ptarray[10] = "1149 " { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",1150 initListExpr(1151 has(cxxConstructExpr(requiresZeroInitialization())),1152 has(initListExpr(1153 hasType(asString("struct point")), has(floatLiteral(equals(1.0))),1154 has(implicitValueInitExpr(hasType(asString("double")))))),1155 has(initListExpr(hasType(asString("struct point")),1156 has(floatLiteral(equals(2.0))),1157 has(floatLiteral(equals(1.0))))))));1158}1159 1160TEST_P(ASTMatchersTest, ParenListExpr) {1161 if (!GetParam().isCXX()) {1162 return;1163 }1164 EXPECT_TRUE(1165 matches("template<typename T> class foo { void bar() { foo X(*this); } };"1166 "template class foo<int>;",1167 varDecl(hasInitializer(parenListExpr(has(unaryOperator()))))));1168}1169 1170TEST_P(ASTMatchersTest, StmtExpr) {1171 EXPECT_TRUE(matches("void declToImport() { int C = ({int X=4; X;}); }",1172 varDecl(hasInitializer(stmtExpr()))));1173}1174 1175TEST_P(ASTMatchersTest, PredefinedExpr) {1176 // __func__ expands as StringLiteral("foo")1177 EXPECT_TRUE(matches("void foo() { __func__; }",1178 predefinedExpr(hasType(asString("const char[4]")),1179 has(stringLiteral()))));1180}1181 1182TEST_P(ASTMatchersTest, FileScopeAsmDecl) {1183 EXPECT_TRUE(matches("__asm(\"nop\");", fileScopeAsmDecl()));1184 EXPECT_TRUE(1185 notMatches("void f() { __asm(\"mov al, 2\"); }", fileScopeAsmDecl()));1186}1187 1188TEST_P(ASTMatchersTest, AsmStatement) {1189 EXPECT_TRUE(matches("void foo() { __asm(\"mov al, 2\"); }", asmStmt()));1190}1191 1192TEST_P(ASTMatchersTest, HasConditionVariableStatement) {1193 if (!GetParam().isCXX()) {1194 // FIXME: Add a test for `hasConditionVariableStatement()` that does not1195 // depend on C++.1196 return;1197 }1198 1199 StatementMatcher IfCondition =1200 ifStmt(hasConditionVariableStatement(declStmt()));1201 1202 EXPECT_TRUE(matches("void x() { if (int* a = 0) {} }", IfCondition));1203 EXPECT_TRUE(notMatches("void x() { if (true) {} }", IfCondition));1204 EXPECT_TRUE(notMatches("void x() { int x; if ((x = 42)) {} }", IfCondition));1205 1206 StatementMatcher SwitchCondition =1207 switchStmt(hasConditionVariableStatement(declStmt()));1208 1209 EXPECT_TRUE(matches("void x() { switch (int a = 0) {} }", SwitchCondition));1210 if (GetParam().isCXX17OrLater()) {1211 EXPECT_TRUE(1212 notMatches("void x() { switch (int a = 0; a) {} }", SwitchCondition));1213 }1214 1215 StatementMatcher ForCondition =1216 forStmt(hasConditionVariableStatement(declStmt()));1217 1218 EXPECT_TRUE(matches("void x() { for (; int a = 0; ) {} }", ForCondition));1219 EXPECT_TRUE(notMatches("void x() { for (int a = 0; ; ) {} }", ForCondition));1220 1221 EXPECT_TRUE(matches("void x() { while (int a = 0) {} }",1222 whileStmt(hasConditionVariableStatement(declStmt()))));1223}1224 1225TEST_P(ASTMatchersTest, HasCondition) {1226 if (!GetParam().isCXX()) {1227 // FIXME: Add a test for `hasCondition()` that does not depend on C++.1228 return;1229 }1230 1231 StatementMatcher Condition =1232 ifStmt(hasCondition(cxxBoolLiteral(equals(true))));1233 1234 EXPECT_TRUE(matches("void x() { if (true) {} }", Condition));1235 EXPECT_TRUE(notMatches("void x() { if (false) {} }", Condition));1236 EXPECT_TRUE(notMatches("void x() { bool a = true; if (a) {} }", Condition));1237 EXPECT_TRUE(notMatches("void x() { if (true || false) {} }", Condition));1238 EXPECT_TRUE(notMatches("void x() { if (1) {} }", Condition));1239}1240 1241TEST_P(ASTMatchersTest, ConditionalOperator) {1242 if (!GetParam().isCXX()) {1243 // FIXME: Add a test for `conditionalOperator()` that does not depend on1244 // C++.1245 return;1246 }1247 1248 StatementMatcher Conditional =1249 conditionalOperator(hasCondition(cxxBoolLiteral(equals(true))),1250 hasTrueExpression(cxxBoolLiteral(equals(false))));1251 1252 EXPECT_TRUE(matches("void x() { true ? false : true; }", Conditional));1253 EXPECT_TRUE(notMatches("void x() { false ? false : true; }", Conditional));1254 EXPECT_TRUE(notMatches("void x() { true ? true : false; }", Conditional));1255 1256 StatementMatcher ConditionalFalse =1257 conditionalOperator(hasFalseExpression(cxxBoolLiteral(equals(false))));1258 1259 EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));1260 EXPECT_TRUE(1261 notMatches("void x() { true ? false : true; }", ConditionalFalse));1262 1263 EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));1264 EXPECT_TRUE(1265 notMatches("void x() { true ? false : true; }", ConditionalFalse));1266}1267 1268TEST_P(ASTMatchersTest, BinaryConditionalOperator) {1269 if (!GetParam().isCXX()) {1270 // FIXME: This test should work in non-C++ language modes.1271 return;1272 }1273 1274 StatementMatcher AlwaysOne = traverse(1275 TK_AsIs, binaryConditionalOperator(1276 hasCondition(implicitCastExpr(has(opaqueValueExpr(1277 hasSourceExpression((integerLiteral(equals(1)))))))),1278 hasFalseExpression(integerLiteral(equals(0)))));1279 1280 EXPECT_TRUE(matches("void x() { 1 ?: 0; }", AlwaysOne));1281 1282 StatementMatcher FourNotFive = binaryConditionalOperator(1283 hasTrueExpression(1284 opaqueValueExpr(hasSourceExpression((integerLiteral(equals(4)))))),1285 hasFalseExpression(integerLiteral(equals(5))));1286 1287 EXPECT_TRUE(matches("void x() { 4 ?: 5; }", FourNotFive));1288}1289 1290TEST_P(ASTMatchersTest, ArraySubscriptExpr) {1291 EXPECT_TRUE(1292 matches("int i[2]; void f() { i[1] = 1; }", arraySubscriptExpr()));1293 EXPECT_TRUE(notMatches("int i; void f() { i = 1; }", arraySubscriptExpr()));1294}1295 1296TEST_P(ASTMatchersTest, ForStmt) {1297 EXPECT_TRUE(matches("void f() { for(;;); }", forStmt()));1298 EXPECT_TRUE(matches("void f() { if(1) for(;;); }", forStmt()));1299}1300 1301TEST_P(ASTMatchersTest, ForStmt_CXX11) {1302 if (!GetParam().isCXX11OrLater()) {1303 return;1304 }1305 EXPECT_TRUE(notMatches("int as[] = { 1, 2, 3 };"1306 "void f() { for (auto &a : as); }",1307 forStmt()));1308}1309 1310TEST_P(ASTMatchersTest, ForStmt_NoFalsePositives) {1311 EXPECT_TRUE(notMatches("void f() { ; }", forStmt()));1312 EXPECT_TRUE(notMatches("void f() { if(1); }", forStmt()));1313}1314 1315TEST_P(ASTMatchersTest, CompoundStatement) {1316 EXPECT_TRUE(notMatches("void f();", compoundStmt()));1317 EXPECT_TRUE(matches("void f() {}", compoundStmt()));1318 EXPECT_TRUE(matches("void f() {{}}", compoundStmt()));1319}1320 1321TEST_P(ASTMatchersTest, CompoundStatement_DoesNotMatchEmptyStruct) {1322 if (!GetParam().isCXX()) {1323 // FIXME: Add a similar test that does not depend on C++.1324 return;1325 }1326 // It's not a compound statement just because there's "{}" in the source1327 // text. This is an AST search, not grep.1328 EXPECT_TRUE(notMatches("namespace n { struct S {}; }", compoundStmt()));1329 EXPECT_TRUE(1330 matches("namespace n { struct S { void f() {{}} }; }", compoundStmt()));1331}1332 1333TEST_P(ASTMatchersTest, CastExpr_MatchesExplicitCasts) {1334 EXPECT_TRUE(matches("void *p = (void *)(&p);", castExpr()));1335}1336 1337TEST_P(ASTMatchersTest, CastExpr_MatchesExplicitCasts_CXX) {1338 if (!GetParam().isCXX()) {1339 return;1340 }1341 EXPECT_TRUE(matches("char *p = reinterpret_cast<char *>(&p);", castExpr()));1342 EXPECT_TRUE(matches("char q, *p = const_cast<char *>(&q);", castExpr()));1343 EXPECT_TRUE(matches("char c = char(0);", castExpr()));1344}1345 1346TEST_P(ASTMatchersTest, CastExpression_MatchesImplicitCasts) {1347 // This test creates an implicit cast from int to char.1348 EXPECT_TRUE(matches("char c = 0;", traverse(TK_AsIs, castExpr())));1349 // This test creates an implicit cast from lvalue to rvalue.1350 EXPECT_TRUE(matches("void f() { char c = 0, d = c; }",1351 traverse(TK_AsIs, castExpr())));1352}1353 1354TEST_P(ASTMatchersTest, CastExpr_DoesNotMatchNonCasts) {1355 if (GetParam().isC()) {1356 // This does have a cast in C1357 EXPECT_TRUE(matches("char c = '0';", implicitCastExpr()));1358 } else {1359 EXPECT_TRUE(notMatches("char c = '0';", castExpr()));1360 }1361 EXPECT_TRUE(notMatches("int i = (0);", castExpr()));1362 EXPECT_TRUE(notMatches("int i = 0;", castExpr()));1363}1364 1365TEST_P(ASTMatchersTest, CastExpr_DoesNotMatchNonCasts_CXX) {1366 if (!GetParam().isCXX()) {1367 return;1368 }1369 EXPECT_TRUE(notMatches("char c, &q = c;", castExpr()));1370}1371 1372TEST_P(ASTMatchersTest, CXXReinterpretCastExpr) {1373 if (!GetParam().isCXX()) {1374 return;1375 }1376 EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",1377 cxxReinterpretCastExpr()));1378}1379 1380TEST_P(ASTMatchersTest, CXXReinterpretCastExpr_DoesNotMatchOtherCasts) {1381 if (!GetParam().isCXX()) {1382 return;1383 }1384 EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxReinterpretCastExpr()));1385 EXPECT_TRUE(notMatches("char q, *p = const_cast<char*>(&q);",1386 cxxReinterpretCastExpr()));1387 EXPECT_TRUE(notMatches("void* p = static_cast<void*>(&p);",1388 cxxReinterpretCastExpr()));1389 EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"1390 "B b;"1391 "D* p = dynamic_cast<D*>(&b);",1392 cxxReinterpretCastExpr()));1393}1394 1395TEST_P(ASTMatchersTest, CXXFunctionalCastExpr_MatchesSimpleCase) {1396 if (!GetParam().isCXX()) {1397 return;1398 }1399 StringRef foo_class = "class Foo { public: Foo(const char*); };";1400 EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello world\"); }",1401 cxxFunctionalCastExpr()));1402}1403 1404TEST_P(ASTMatchersTest, CXXFunctionalCastExpr_DoesNotMatchOtherCasts) {1405 if (!GetParam().isCXX()) {1406 return;1407 }1408 StringRef FooClass = "class Foo { public: Foo(const char*); };";1409 EXPECT_TRUE(1410 notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",1411 cxxFunctionalCastExpr()));1412 EXPECT_TRUE(notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",1413 cxxFunctionalCastExpr()));1414}1415 1416TEST_P(ASTMatchersTest, CXXDynamicCastExpr) {1417 if (!GetParam().isCXX()) {1418 return;1419 }1420 EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"1421 "B b;"1422 "D* p = dynamic_cast<D*>(&b);",1423 cxxDynamicCastExpr()));1424}1425 1426TEST_P(ASTMatchersTest, CXXStaticCastExpr_MatchesSimpleCase) {1427 if (!GetParam().isCXX()) {1428 return;1429 }1430 EXPECT_TRUE(matches("void* p(static_cast<void*>(&p));", cxxStaticCastExpr()));1431}1432 1433TEST_P(ASTMatchersTest, CXXStaticCastExpr_DoesNotMatchOtherCasts) {1434 if (!GetParam().isCXX()) {1435 return;1436 }1437 EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxStaticCastExpr()));1438 EXPECT_TRUE(1439 notMatches("char q, *p = const_cast<char*>(&q);", cxxStaticCastExpr()));1440 EXPECT_TRUE(notMatches("void* p = reinterpret_cast<char*>(&p);",1441 cxxStaticCastExpr()));1442 EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"1443 "B b;"1444 "D* p = dynamic_cast<D*>(&b);",1445 cxxStaticCastExpr()));1446}1447 1448TEST_P(ASTMatchersTest, CStyleCastExpr_MatchesSimpleCase) {1449 EXPECT_TRUE(matches("int i = (int) 2.2f;", cStyleCastExpr()));1450}1451 1452TEST_P(ASTMatchersTest, CStyleCastExpr_DoesNotMatchOtherCasts) {1453 if (!GetParam().isCXX()) {1454 return;1455 }1456 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);"1457 "char q, *r = const_cast<char*>(&q);"1458 "void* s = reinterpret_cast<char*>(&s);"1459 "struct B { virtual ~B() {} }; struct D : B {};"1460 "B b;"1461 "D* t = dynamic_cast<D*>(&b);",1462 cStyleCastExpr()));1463}1464 1465TEST_P(ASTMatchersTest, ImplicitCastExpr_MatchesSimpleCase) {1466 // This test creates an implicit const cast.1467 EXPECT_TRUE(1468 matches("void f() { int x = 0; const int y = x; }",1469 traverse(TK_AsIs, varDecl(hasInitializer(implicitCastExpr())))));1470 // This test creates an implicit cast from int to char.1471 EXPECT_TRUE(1472 matches("char c = 0;",1473 traverse(TK_AsIs, varDecl(hasInitializer(implicitCastExpr())))));1474 // This test creates an implicit array-to-pointer cast.1475 EXPECT_TRUE(1476 matches("int arr[6]; int *p = arr;",1477 traverse(TK_AsIs, varDecl(hasInitializer(implicitCastExpr())))));1478}1479 1480TEST_P(ASTMatchersTest, ImplicitCastExpr_DoesNotMatchIncorrectly) {1481 // This test verifies that implicitCastExpr() matches exactly when implicit1482 // casts are present, and that it ignores explicit and paren casts.1483 1484 // These two test cases have no casts.1485 EXPECT_TRUE(1486 notMatches("int x = 0;", varDecl(hasInitializer(implicitCastExpr()))));1487 EXPECT_TRUE(1488 notMatches("int x = (0);", varDecl(hasInitializer(implicitCastExpr()))));1489 EXPECT_TRUE(notMatches("void f() { int x = 0; double d = (double) x; }",1490 varDecl(hasInitializer(implicitCastExpr()))));1491}1492 1493TEST_P(ASTMatchersTest, ImplicitCastExpr_DoesNotMatchIncorrectly_CXX) {1494 if (!GetParam().isCXX()) {1495 return;1496 }1497 EXPECT_TRUE(notMatches("int x = 0, &y = x;",1498 varDecl(hasInitializer(implicitCastExpr()))));1499 EXPECT_TRUE(notMatches("const int *p; int *q = const_cast<int *>(p);",1500 varDecl(hasInitializer(implicitCastExpr()))));1501}1502 1503TEST_P(ASTMatchersTest, Stmt_DoesNotMatchDeclarations) {1504 EXPECT_TRUE(notMatches("struct X {};", stmt()));1505}1506 1507TEST_P(ASTMatchersTest, Stmt_MatchesCompoundStatments) {1508 EXPECT_TRUE(matches("void x() {}", stmt()));1509}1510 1511TEST_P(ASTMatchersTest, DeclStmt_DoesNotMatchCompoundStatements) {1512 EXPECT_TRUE(notMatches("void x() {}", declStmt()));1513}1514 1515TEST_P(ASTMatchersTest, DeclStmt_MatchesVariableDeclarationStatements) {1516 EXPECT_TRUE(matches("void x() { int a; }", declStmt()));1517}1518 1519TEST_P(ASTMatchersTest, ExprWithCleanups_MatchesExprWithCleanups) {1520 if (!GetParam().isCXX()) {1521 return;1522 }1523 EXPECT_TRUE(1524 matches("struct Foo { ~Foo(); };"1525 "const Foo f = Foo();",1526 traverse(TK_AsIs, varDecl(hasInitializer(exprWithCleanups())))));1527 EXPECT_FALSE(1528 matches("struct Foo { }; Foo a;"1529 "const Foo f = a;",1530 traverse(TK_AsIs, varDecl(hasInitializer(exprWithCleanups())))));1531}1532 1533TEST_P(ASTMatchersTest, InitListExpr) {1534 EXPECT_TRUE(matches("int a[] = { 1, 2 };",1535 initListExpr(hasType(asString("int[2]")))));1536 EXPECT_TRUE(matches("struct B { int x, y; }; struct B b = { 5, 6 };",1537 initListExpr(hasType(recordDecl(hasName("B"))))));1538 EXPECT_TRUE(1539 matches("int i[1] = {42, [0] = 43};", integerLiteral(equals(42))));1540}1541 1542TEST_P(ASTMatchersTest, InitListExpr_CXX) {1543 if (!GetParam().isCXX()) {1544 return;1545 }1546 EXPECT_TRUE(matches("struct S { S(void (*a)()); };"1547 "void f();"1548 "S s[1] = { &f };",1549 declRefExpr(to(functionDecl(hasName("f"))))));1550}1551 1552TEST_P(ASTMatchersTest,1553 CXXStdInitializerListExpression_MatchesCXXStdInitializerListExpression) {1554 if (!GetParam().isCXX11OrLater()) {1555 return;1556 }1557 StringRef code = "namespace std {"1558 "template <typename E> class initializer_list {"1559 " public: const E *a, *b;"1560 "};"1561 "}"1562 "struct A {"1563 " A(std::initializer_list<int>) {}"1564 "};";1565 EXPECT_TRUE(matches(1566 code + "A a{0};",1567 traverse(TK_AsIs, cxxConstructExpr(has(cxxStdInitializerListExpr()),1568 hasDeclaration(cxxConstructorDecl(1569 ofClass(hasName("A"))))))));1570 EXPECT_TRUE(matches(1571 code + "A a = {0};",1572 traverse(TK_AsIs, cxxConstructExpr(has(cxxStdInitializerListExpr()),1573 hasDeclaration(cxxConstructorDecl(1574 ofClass(hasName("A"))))))));1575 1576 EXPECT_TRUE(notMatches("int a[] = { 1, 2 };", cxxStdInitializerListExpr()));1577 EXPECT_TRUE(notMatches("struct B { int x, y; }; B b = { 5, 6 };",1578 cxxStdInitializerListExpr()));1579}1580 1581TEST_P(ASTMatchersTest, UsingDecl_MatchesUsingDeclarations) {1582 if (!GetParam().isCXX()) {1583 return;1584 }1585 EXPECT_TRUE(matches("namespace X { int x; } using X::x;", usingDecl()));1586}1587 1588TEST_P(ASTMatchersTest, UsingDecl_MatchesShadowUsingDelcarations) {1589 if (!GetParam().isCXX()) {1590 return;1591 }1592 EXPECT_TRUE(matches("namespace f { int a; } using f::a;",1593 usingDecl(hasAnyUsingShadowDecl(hasName("a")))));1594}1595 1596TEST_P(ASTMatchersTest, UsingEnumDecl_MatchesUsingEnumDeclarations) {1597 if (!GetParam().isCXX20OrLater()) {1598 return;1599 }1600 EXPECT_TRUE(1601 matches("namespace X { enum x {}; } using enum X::x;", usingEnumDecl()));1602}1603 1604TEST_P(ASTMatchersTest, UsingEnumDecl_MatchesShadowUsingDeclarations) {1605 if (!GetParam().isCXX20OrLater()) {1606 return;1607 }1608 EXPECT_TRUE(matches("namespace f { enum a {b}; } using enum f::a;",1609 usingEnumDecl(hasAnyUsingShadowDecl(hasName("b")))));1610}1611 1612TEST_P(ASTMatchersTest, UsingDirectiveDecl_MatchesUsingNamespace) {1613 if (!GetParam().isCXX()) {1614 return;1615 }1616 EXPECT_TRUE(matches("namespace X { int x; } using namespace X;",1617 usingDirectiveDecl()));1618 EXPECT_FALSE(1619 matches("namespace X { int x; } using X::x;", usingDirectiveDecl()));1620}1621 1622TEST_P(ASTMatchersTest, WhileStmt) {1623 EXPECT_TRUE(notMatches("void x() {}", whileStmt()));1624 EXPECT_TRUE(matches("void x() { while(1); }", whileStmt()));1625 EXPECT_TRUE(notMatches("void x() { do {} while(1); }", whileStmt()));1626}1627 1628TEST_P(ASTMatchersTest, DoStmt_MatchesDoLoops) {1629 EXPECT_TRUE(matches("void x() { do {} while(1); }", doStmt()));1630 EXPECT_TRUE(matches("void x() { do ; while(0); }", doStmt()));1631}1632 1633TEST_P(ASTMatchersTest, DoStmt_DoesNotMatchWhileLoops) {1634 EXPECT_TRUE(notMatches("void x() { while(1) {} }", doStmt()));1635}1636 1637TEST_P(ASTMatchersTest, SwitchCase_MatchesCase) {1638 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }", switchCase()));1639 EXPECT_TRUE(matches("void x() { switch(42) { default:; } }", switchCase()));1640 EXPECT_TRUE(matches("void x() { switch(42) default:; }", switchCase()));1641 EXPECT_TRUE(notMatches("void x() { switch(42) {} }", switchCase()));1642}1643 1644TEST_P(ASTMatchersTest, SwitchCase_MatchesSwitch) {1645 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }", switchStmt()));1646 EXPECT_TRUE(matches("void x() { switch(42) { default:; } }", switchStmt()));1647 EXPECT_TRUE(matches("void x() { switch(42) default:; }", switchStmt()));1648 EXPECT_TRUE(notMatches("void x() {}", switchStmt()));1649}1650 1651TEST_P(ASTMatchersTest, CxxExceptionHandling_SimpleCases) {1652 if (!GetParam().isCXX()) {1653 return;1654 }1655 EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxCatchStmt()));1656 EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxTryStmt()));1657 EXPECT_TRUE(1658 notMatches("void foo() try { } catch(int X) { }", cxxThrowExpr()));1659 EXPECT_TRUE(1660 matches("void foo() try { throw; } catch(int X) { }", cxxThrowExpr()));1661 EXPECT_TRUE(1662 matches("void foo() try { throw 5;} catch(int X) { }", cxxThrowExpr()));1663 EXPECT_TRUE(matches("void foo() try { throw; } catch(...) { }",1664 cxxCatchStmt(isCatchAll())));1665 EXPECT_TRUE(notMatches("void foo() try { throw; } catch(int) { }",1666 cxxCatchStmt(isCatchAll())));1667 EXPECT_TRUE(matches("void foo() try {} catch(int X) { }",1668 varDecl(isExceptionVariable())));1669 EXPECT_TRUE(notMatches("void foo() try { int X; } catch (...) { }",1670 varDecl(isExceptionVariable())));1671}1672 1673TEST_P(ASTMatchersTest, ParenExpr_SimpleCases) {1674 EXPECT_TRUE(matches("int i = (3);", traverse(TK_AsIs, parenExpr())));1675 EXPECT_TRUE(matches("int i = (3 + 7);", traverse(TK_AsIs, parenExpr())));1676 EXPECT_TRUE(notMatches("int i = 3;", traverse(TK_AsIs, parenExpr())));1677 EXPECT_TRUE(notMatches("int f() { return 1; }; void g() { int a = f(); }",1678 traverse(TK_AsIs, parenExpr())));1679}1680 1681TEST_P(ASTMatchersTest, IgnoringParens) {1682 EXPECT_FALSE(matches("const char* str = (\"my-string\");",1683 traverse(TK_AsIs, implicitCastExpr(hasSourceExpression(1684 stringLiteral())))));1685 EXPECT_TRUE(1686 matches("const char* str = (\"my-string\");",1687 traverse(TK_AsIs, implicitCastExpr(hasSourceExpression(1688 ignoringParens(stringLiteral()))))));1689}1690 1691TEST_P(ASTMatchersTest, QualType) {1692 EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));1693}1694 1695TEST_P(ASTMatchersTest, ConstantArrayType) {1696 EXPECT_TRUE(matches("int a[2];", constantArrayType()));1697 EXPECT_TRUE(notMatches("void f() { int a[] = { 2, 3 }; int b[a[0]]; }",1698 constantArrayType(hasElementType(builtinType()))));1699 1700 EXPECT_TRUE(matches("int a[42];", constantArrayType(hasSize(42))));1701 EXPECT_TRUE(matches("int b[2*21];", constantArrayType(hasSize(42))));1702 EXPECT_TRUE(notMatches("int c[41], d[43];", constantArrayType(hasSize(42))));1703}1704 1705TEST_P(ASTMatchersTest, DependentSizedArrayType) {1706 if (!GetParam().isCXX()) {1707 return;1708 }1709 EXPECT_TRUE(1710 matches("template <typename T, int Size> class array { T data[Size]; };",1711 dependentSizedArrayType()));1712 EXPECT_TRUE(1713 notMatches("int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }",1714 dependentSizedArrayType()));1715}1716 1717TEST_P(ASTMatchersTest, DependentSizedExtVectorType) {1718 if (!GetParam().isCXX()) {1719 return;1720 }1721 EXPECT_TRUE(matches("template<typename T, int Size>"1722 "class vector {"1723 " typedef T __attribute__((ext_vector_type(Size))) type;"1724 "};",1725 dependentSizedExtVectorType()));1726 EXPECT_TRUE(1727 notMatches("int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }",1728 dependentSizedExtVectorType()));1729}1730 1731TEST_P(ASTMatchersTest, IncompleteArrayType) {1732 EXPECT_TRUE(matches("int a[] = { 2, 3 };", incompleteArrayType()));1733 EXPECT_TRUE(matches("void f(int a[]) {}", incompleteArrayType()));1734 1735 EXPECT_TRUE(notMatches("int a[42]; void f() { int b[a[0]]; }",1736 incompleteArrayType()));1737}1738 1739TEST_P(ASTMatchersTest, VariableArrayType) {1740 EXPECT_TRUE(matches("void f(int b) { int a[b]; }", variableArrayType()));1741 EXPECT_TRUE(notMatches("int a[] = {2, 3}; int b[42];", variableArrayType()));1742 1743 EXPECT_TRUE(matches("void f(int b) { int a[b]; }",1744 variableArrayType(hasSizeExpr(ignoringImpCasts(1745 declRefExpr(to(varDecl(hasName("b")))))))));1746}1747 1748TEST_P(ASTMatchersTest, AtomicType) {1749 if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getOS() !=1750 llvm::Triple::Win32) {1751 // FIXME: Make this work for MSVC.1752 EXPECT_TRUE(matches("_Atomic(int) i;", atomicType()));1753 1754 EXPECT_TRUE(1755 matches("_Atomic(int) i;", atomicType(hasValueType(isInteger()))));1756 EXPECT_TRUE(1757 notMatches("_Atomic(float) f;", atomicType(hasValueType(isInteger()))));1758 }1759}1760 1761TEST_P(ASTMatchersTest, AutoType) {1762 if (!GetParam().isCXX11OrLater()) {1763 return;1764 }1765 EXPECT_TRUE(matches("auto i = 2;", autoType()));1766 EXPECT_TRUE(matches("int v[] = { 2, 3 }; void f() { for (int i : v) {} }",1767 autoType()));1768 1769 EXPECT_TRUE(matches("auto i = 2;", varDecl(hasType(isInteger()))));1770 EXPECT_TRUE(matches("struct X{}; auto x = X{};",1771 varDecl(hasType(recordDecl(hasName("X"))))));1772 1773 // FIXME: Matching against the type-as-written can't work here, because the1774 // type as written was not deduced.1775 // EXPECT_TRUE(matches("auto a = 1;",1776 // autoType(hasDeducedType(isInteger()))));1777 // EXPECT_TRUE(notMatches("auto b = 2.0;",1778 // autoType(hasDeducedType(isInteger()))));1779}1780 1781TEST_P(ASTMatchersTest, DecltypeType) {1782 if (!GetParam().isCXX11OrLater()) {1783 return;1784 }1785 EXPECT_TRUE(matches("decltype(1 + 1) sum = 1 + 1;", decltypeType()));1786 EXPECT_TRUE(matches("decltype(1 + 1) sum = 1 + 1;",1787 decltypeType(hasUnderlyingType(isInteger()))));1788}1789 1790TEST_P(ASTMatchersTest, FunctionType) {1791 EXPECT_TRUE(matches("int (*f)(int);", functionType()));1792 EXPECT_TRUE(matches("void f(int i) {}", functionType()));1793}1794 1795TEST_P(ASTMatchersTest, IgnoringParens_Type) {1796 EXPECT_TRUE(1797 notMatches("void (*fp)(void);", pointerType(pointee(functionType()))));1798 EXPECT_TRUE(matches("void (*fp)(void);",1799 pointerType(pointee(ignoringParens(functionType())))));1800}1801 1802TEST_P(ASTMatchersTest, FunctionProtoType) {1803 EXPECT_TRUE(matches("int (*f)(int);", functionProtoType()));1804 EXPECT_TRUE(matches("void f(int i);", functionProtoType()));1805 EXPECT_TRUE(matches("void f(void);", functionProtoType(parameterCountIs(0))));1806}1807 1808TEST_P(ASTMatchersTest, FunctionProtoType_C) {1809 if (!GetParam().isCOrEarlier(17)) {1810 return;1811 }1812 EXPECT_TRUE(notMatches("void f();", functionProtoType()));1813}1814 1815TEST_P(ASTMatchersTest, FunctionProtoType_CXX) {1816 if (!GetParam().isCXX()) {1817 return;1818 }1819 EXPECT_TRUE(matches("void f();", functionProtoType(parameterCountIs(0))));1820}1821 1822TEST_P(ASTMatchersTest, ParenType) {1823 EXPECT_TRUE(1824 matches("int (*array)[4];", varDecl(hasType(pointsTo(parenType())))));1825 EXPECT_TRUE(notMatches("int *array[4];", varDecl(hasType(parenType()))));1826 1827 EXPECT_TRUE(matches(1828 "int (*ptr_to_func)(int);",1829 varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));1830 EXPECT_TRUE(notMatches(1831 "int (*ptr_to_array)[4];",1832 varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));1833}1834 1835TEST_P(ASTMatchersTest, PointerType) {1836 // FIXME: Reactive when these tests can be more specific (not matching1837 // implicit code on certain platforms), likely when we have hasDescendant for1838 // Types/TypeLocs.1839 // EXPECT_TRUE(matchAndVerifyResultTrue(1840 // "int* a;",1841 // pointerTypeLoc(pointeeLoc(typeLoc().bind("loc"))),1842 // std::make_unique<VerifyIdIsBoundTo<TypeLoc>>("loc", 1)));1843 // EXPECT_TRUE(matchAndVerifyResultTrue(1844 // "int* a;",1845 // pointerTypeLoc().bind("loc"),1846 // std::make_unique<VerifyIdIsBoundTo<TypeLoc>>("loc", 1)));1847 EXPECT_TRUE(matches("int** a;", loc(pointerType(pointee(qualType())))));1848 EXPECT_TRUE(matches("int** a;", loc(pointerType(pointee(pointerType())))));1849 EXPECT_TRUE(matches("int* b; int* * const a = &b;",1850 loc(qualType(isConstQualified(), pointerType()))));1851 1852 StringRef Fragment = "int *ptr;";1853 EXPECT_TRUE(notMatches(Fragment,1854 varDecl(hasName("ptr"), hasType(blockPointerType()))));1855 EXPECT_TRUE(notMatches(1856 Fragment, varDecl(hasName("ptr"), hasType(memberPointerType()))));1857 EXPECT_TRUE(1858 matches(Fragment, varDecl(hasName("ptr"), hasType(pointerType()))));1859 EXPECT_TRUE(1860 notMatches(Fragment, varDecl(hasName("ptr"), hasType(referenceType()))));1861}1862 1863TEST_P(ASTMatchersTest, PointerType_CXX) {1864 if (!GetParam().isCXX()) {1865 return;1866 }1867 StringRef Fragment = "struct A { int i; }; int A::* ptr = &A::i;";1868 EXPECT_TRUE(notMatches(Fragment,1869 varDecl(hasName("ptr"), hasType(blockPointerType()))));1870 EXPECT_TRUE(1871 matches(Fragment, varDecl(hasName("ptr"), hasType(memberPointerType()))));1872 EXPECT_TRUE(1873 notMatches(Fragment, varDecl(hasName("ptr"), hasType(pointerType()))));1874 EXPECT_TRUE(1875 notMatches(Fragment, varDecl(hasName("ptr"), hasType(referenceType()))));1876 EXPECT_TRUE(notMatches(1877 Fragment, varDecl(hasName("ptr"), hasType(lValueReferenceType()))));1878 EXPECT_TRUE(notMatches(1879 Fragment, varDecl(hasName("ptr"), hasType(rValueReferenceType()))));1880 1881 Fragment = "int a; int &ref = a;";1882 EXPECT_TRUE(notMatches(Fragment,1883 varDecl(hasName("ref"), hasType(blockPointerType()))));1884 EXPECT_TRUE(notMatches(1885 Fragment, varDecl(hasName("ref"), hasType(memberPointerType()))));1886 EXPECT_TRUE(1887 notMatches(Fragment, varDecl(hasName("ref"), hasType(pointerType()))));1888 EXPECT_TRUE(1889 matches(Fragment, varDecl(hasName("ref"), hasType(referenceType()))));1890 EXPECT_TRUE(matches(Fragment,1891 varDecl(hasName("ref"), hasType(lValueReferenceType()))));1892 EXPECT_TRUE(notMatches(1893 Fragment, varDecl(hasName("ref"), hasType(rValueReferenceType()))));1894}1895 1896TEST_P(ASTMatchersTest, PointerType_CXX11) {1897 if (!GetParam().isCXX11OrLater()) {1898 return;1899 }1900 StringRef Fragment = "int &&ref = 2;";1901 EXPECT_TRUE(notMatches(Fragment,1902 varDecl(hasName("ref"), hasType(blockPointerType()))));1903 EXPECT_TRUE(notMatches(1904 Fragment, varDecl(hasName("ref"), hasType(memberPointerType()))));1905 EXPECT_TRUE(1906 notMatches(Fragment, varDecl(hasName("ref"), hasType(pointerType()))));1907 EXPECT_TRUE(1908 matches(Fragment, varDecl(hasName("ref"), hasType(referenceType()))));1909 EXPECT_TRUE(notMatches(1910 Fragment, varDecl(hasName("ref"), hasType(lValueReferenceType()))));1911 EXPECT_TRUE(matches(Fragment,1912 varDecl(hasName("ref"), hasType(rValueReferenceType()))));1913}1914 1915TEST_P(ASTMatchersTest, AutoRefTypes) {1916 if (!GetParam().isCXX11OrLater()) {1917 return;1918 }1919 1920 StringRef Fragment = "auto a = 1;"1921 "auto b = a;"1922 "auto &c = a;"1923 "auto &&d = c;"1924 "auto &&e = 2;";1925 EXPECT_TRUE(1926 notMatches(Fragment, varDecl(hasName("a"), hasType(referenceType()))));1927 EXPECT_TRUE(1928 notMatches(Fragment, varDecl(hasName("b"), hasType(referenceType()))));1929 EXPECT_TRUE(1930 matches(Fragment, varDecl(hasName("c"), hasType(referenceType()))));1931 EXPECT_TRUE(1932 matches(Fragment, varDecl(hasName("c"), hasType(lValueReferenceType()))));1933 EXPECT_TRUE(notMatches(1934 Fragment, varDecl(hasName("c"), hasType(rValueReferenceType()))));1935 EXPECT_TRUE(1936 matches(Fragment, varDecl(hasName("d"), hasType(referenceType()))));1937 EXPECT_TRUE(1938 matches(Fragment, varDecl(hasName("d"), hasType(lValueReferenceType()))));1939 EXPECT_TRUE(notMatches(1940 Fragment, varDecl(hasName("d"), hasType(rValueReferenceType()))));1941 EXPECT_TRUE(1942 matches(Fragment, varDecl(hasName("e"), hasType(referenceType()))));1943 EXPECT_TRUE(notMatches(1944 Fragment, varDecl(hasName("e"), hasType(lValueReferenceType()))));1945 EXPECT_TRUE(1946 matches(Fragment, varDecl(hasName("e"), hasType(rValueReferenceType()))));1947}1948 1949TEST_P(ASTMatchersTest, EnumType) {1950 EXPECT_TRUE(1951 matches("enum Color { Green }; enum Color color;", loc(enumType())));1952}1953 1954TEST_P(ASTMatchersTest, EnumType_CXX) {1955 if (!GetParam().isCXX()) {1956 return;1957 }1958 EXPECT_TRUE(matches("enum Color { Green }; Color color;", loc(enumType())));1959}1960 1961TEST_P(ASTMatchersTest, EnumType_CXX11) {1962 if (!GetParam().isCXX11OrLater()) {1963 return;1964 }1965 EXPECT_TRUE(1966 matches("enum class Color { Green }; Color color;", loc(enumType())));1967}1968 1969TEST_P(ASTMatchersTest, PointerType_MatchesPointersToConstTypes) {1970 EXPECT_TRUE(matches("int b; int * const a = &b;", loc(pointerType())));1971 EXPECT_TRUE(matches("int b; int * const a = &b;", loc(pointerType())));1972 EXPECT_TRUE(matches("int b; const int * a = &b;",1973 loc(pointerType(pointee(builtinType())))));1974 EXPECT_TRUE(matches("int b; const int * a = &b;",1975 pointerType(pointee(builtinType()))));1976}1977 1978TEST_P(ASTMatchersTest, TypedefType) {1979 EXPECT_TRUE(matches("typedef int X; X a;",1980 varDecl(hasName("a"), hasType(typedefType()))));1981}1982 1983TEST_P(ASTMatchersTest, MacroQualifiedType) {1984 EXPECT_TRUE(matches(1985 R"(1986 #define CDECL __attribute__((cdecl))1987 typedef void (CDECL *X)();1988 )",1989 typedefDecl(hasType(pointerType(pointee(macroQualifiedType()))))));1990 EXPECT_TRUE(notMatches(1991 R"(1992 typedef void (__attribute__((cdecl)) *Y)();1993 )",1994 typedefDecl(hasType(pointerType(pointee(macroQualifiedType()))))));1995}1996 1997TEST_P(ASTMatchersTest, TemplateSpecializationType) {1998 if (!GetParam().isCXX()) {1999 return;2000 }2001 EXPECT_TRUE(matches("template <typename T> class A{}; A<int> a;",2002 templateSpecializationType()));2003}2004 2005TEST_P(ASTMatchersTest, DeducedTemplateSpecializationType) {2006 if (!GetParam().isCXX17OrLater()) {2007 return;2008 }2009 EXPECT_TRUE(2010 matches("template <typename T> class A{ public: A(T) {} }; A a(1);",2011 deducedTemplateSpecializationType()));2012}2013 2014TEST_P(ASTMatchersTest, DependentNameType) {2015 if (!GetParam().isCXX()) {2016 return;2017 }2018 2019 EXPECT_TRUE(matches(2020 R"(2021 template <typename T> struct declToImport {2022 typedef typename T::type dependent_name;2023 };2024 )",2025 dependentNameType()));2026}2027 2028TEST_P(ASTMatchersTest, DependentTemplateSpecializationType) {2029 if (!GetParam().isCXX()) {2030 return;2031 }2032 2033 EXPECT_TRUE(matches(2034 R"(2035 template<typename T> struct A;2036 template<typename T> struct declToImport {2037 typename A<T>::template B<T> a;2038 };2039 )",2040 templateSpecializationType()));2041}2042 2043TEST_P(ASTMatchersTest, RecordType) {2044 EXPECT_TRUE(matches("struct S {}; struct S s;",2045 recordType(hasDeclaration(recordDecl(hasName("S"))))));2046 EXPECT_TRUE(notMatches("int i;",2047 recordType(hasDeclaration(recordDecl(hasName("S"))))));2048}2049 2050TEST_P(ASTMatchersTest, RecordType_CXX) {2051 if (!GetParam().isCXX()) {2052 return;2053 }2054 EXPECT_TRUE(matches("class C {}; C c;", recordType()));2055 EXPECT_TRUE(matches("struct S {}; S s;",2056 recordType(hasDeclaration(recordDecl(hasName("S"))))));2057}2058 2059TEST_P(ASTMatchersTest, SubstTemplateTypeParmType) {2060 if (!GetParam().isCXX()) {2061 return;2062 }2063 StringRef code = "template <typename T>"2064 "int F() {"2065 " return 1 + T();"2066 "}"2067 "int i = F<int>();";2068 EXPECT_FALSE(matches(code, binaryOperator(hasLHS(2069 expr(hasType(substTemplateTypeParmType()))))));2070 EXPECT_TRUE(matches(code, binaryOperator(hasRHS(2071 expr(hasType(substTemplateTypeParmType()))))));2072}2073 2074TEST_P(ASTMatchersTest, NestedNameSpecifier) {2075 if (!GetParam().isCXX()) {2076 return;2077 }2078 EXPECT_TRUE(2079 matches("namespace ns { struct A {}; } ns::A a;", nestedNameSpecifier()));2080 EXPECT_TRUE(matches("template <typename T> class A { typename T::B b; };",2081 nestedNameSpecifier()));2082 EXPECT_TRUE(2083 matches("struct A { void f(); }; void A::f() {}", nestedNameSpecifier()));2084 EXPECT_TRUE(matches("namespace a { namespace b {} } namespace ab = a::b;",2085 nestedNameSpecifier()));2086 2087 EXPECT_TRUE(matches("struct A { static void f() {} }; void g() { A::f(); }",2088 nestedNameSpecifier()));2089 EXPECT_TRUE(2090 notMatches("struct A { static void f() {} }; void g(A* a) { a->f(); }",2091 nestedNameSpecifier()));2092}2093 2094TEST_P(ASTMatchersTest, Attr) {2095 // Windows adds some implicit attributes.2096 bool AutomaticAttributes = StringRef(GetParam().Target).contains("win32");2097 if (GetParam().isCXX11OrLater()) {2098 EXPECT_TRUE(matches("struct [[clang::warn_unused_result]] F{};", attr()));2099 2100 // Unknown attributes are not parsed into an AST node.2101 if (!AutomaticAttributes) {2102 EXPECT_TRUE(notMatches("int x [[unknownattr]];", attr()));2103 }2104 }2105 if (GetParam().isCXX17OrLater()) {2106 EXPECT_TRUE(matches("struct [[nodiscard]] F{};", attr()));2107 }2108 EXPECT_TRUE(matches("int x(int * __attribute__((nonnull)) );", attr()));2109 if (!AutomaticAttributes) {2110 EXPECT_TRUE(notMatches("struct F{}; int x(int *);", attr()));2111 // Some known attributes are not parsed into an AST node.2112 EXPECT_TRUE(notMatches("typedef int x __attribute__((ext_vector_type(1)));",2113 attr()));2114 }2115}2116 2117TEST_P(ASTMatchersTest, NullStmt) {2118 EXPECT_TRUE(matches("void f() {int i;;}", nullStmt()));2119 EXPECT_TRUE(notMatches("void f() {int i;}", nullStmt()));2120}2121 2122TEST_P(ASTMatchersTest, NamespaceAliasDecl) {2123 if (!GetParam().isCXX()) {2124 return;2125 }2126 EXPECT_TRUE(matches("namespace test {} namespace alias = ::test;",2127 namespaceAliasDecl(hasName("alias"))));2128}2129 2130TEST_P(ASTMatchersTest, NestedNameSpecifier_MatchesTypes) {2131 if (!GetParam().isCXX()) {2132 return;2133 }2134 NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(2135 specifiesType(hasDeclaration(recordDecl(hasName("A")))));2136 EXPECT_TRUE(matches("struct A { struct B {}; }; A::B b;", Matcher));2137 EXPECT_TRUE(2138 matches("struct A { struct B { struct C {}; }; }; A::B::C c;", Matcher));2139 EXPECT_TRUE(notMatches("namespace A { struct B {}; } A::B b;", Matcher));2140}2141 2142TEST_P(ASTMatchersTest, NestedNameSpecifier_MatchesNamespaceDecls) {2143 if (!GetParam().isCXX()) {2144 return;2145 }2146 NestedNameSpecifierMatcher Matcher =2147 nestedNameSpecifier(specifiesNamespace(hasName("ns")));2148 EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;", Matcher));2149 EXPECT_TRUE(notMatches("namespace xx { struct A {}; } xx::A a;", Matcher));2150 EXPECT_TRUE(notMatches("struct ns { struct A {}; }; ns::A a;", Matcher));2151}2152 2153TEST_P(ASTMatchersTest,2154 NestedNameSpecifier_MatchesNestedNameSpecifierPrefixes) {2155 if (!GetParam().isCXX()) {2156 return;2157 }2158 EXPECT_TRUE(2159 matches("struct A { struct B { struct C {}; }; }; A::B::C c;",2160 nestedNameSpecifier(hasPrefix(specifiesType(asString("A"))))));2161 EXPECT_TRUE(matches("struct A { struct B { struct C {}; }; }; A::B::C c;",2162 nestedNameSpecifierLoc(hasPrefix(2163 specifiesTypeLoc(loc(qualType(asString("A"))))))));2164 EXPECT_TRUE(matches(2165 "namespace N { struct A { struct B { struct C {}; }; }; } N::A::B::C c;",2166 nestedNameSpecifierLoc(2167 hasPrefix(specifiesTypeLoc(loc(qualType(asString("N::A"))))))));2168}2169 2170template <typename T>2171class VerifyAncestorHasChildIsEqual : public BoundNodesCallback {2172public:2173 bool run(const BoundNodes *Nodes, ASTContext *Context) override {2174 const T *Node = Nodes->getNodeAs<T>("");2175 return verify(*Nodes, *Context, Node);2176 }2177 2178 bool verify(const BoundNodes &Nodes, ASTContext &Context, const Stmt *Node) {2179 // Use the original typed pointer to verify we can pass pointers to subtypes2180 // to equalsNode.2181 const T *TypedNode = cast<T>(Node);2182 return selectFirst<T>(2183 "", match(stmt(hasParent(2184 stmt(has(stmt(equalsNode(TypedNode)))).bind(""))),2185 *Node, Context)) != nullptr;2186 }2187 bool verify(const BoundNodes &Nodes, ASTContext &Context, const Decl *Node) {2188 // Use the original typed pointer to verify we can pass pointers to subtypes2189 // to equalsNode.2190 const T *TypedNode = cast<T>(Node);2191 return selectFirst<T>(2192 "", match(decl(hasParent(2193 decl(has(decl(equalsNode(TypedNode)))).bind(""))),2194 *Node, Context)) != nullptr;2195 }2196 bool verify(const BoundNodes &Nodes, ASTContext &Context, const Type *Node) {2197 // Use the original typed pointer to verify we can pass pointers to subtypes2198 // to equalsNode.2199 const T *TypedNode = cast<T>(Node);2200 const auto *Dec = Nodes.getNodeAs<FieldDecl>("decl");2201 return selectFirst<T>(2202 "", match(fieldDecl(hasParent(decl(has(fieldDecl(2203 hasType(type(equalsNode(TypedNode)).bind(""))))))),2204 *Dec, Context)) != nullptr;2205 }2206};2207 2208TEST_P(ASTMatchersTest, IsEqualTo_MatchesNodesByIdentity) {2209 EXPECT_TRUE(matchAndVerifyResultTrue(2210 "void f() { if (1) if(1) {} }", ifStmt().bind(""),2211 std::make_unique<VerifyAncestorHasChildIsEqual<IfStmt>>()));2212}2213 2214TEST_P(ASTMatchersTest, IsEqualTo_MatchesNodesByIdentity_Cxx) {2215 if (!GetParam().isCXX()) {2216 return;2217 }2218 EXPECT_TRUE(matchAndVerifyResultTrue(2219 "class X { class Y {}; };", recordDecl(hasName("::X::Y")).bind(""),2220 std::make_unique<VerifyAncestorHasChildIsEqual<CXXRecordDecl>>()));2221 EXPECT_TRUE(matchAndVerifyResultTrue(2222 "class X { class Y {} y; };",2223 fieldDecl(hasName("y"), hasType(type().bind(""))).bind("decl"),2224 std::make_unique<VerifyAncestorHasChildIsEqual<Type>>()));2225}2226 2227TEST_P(ASTMatchersTest, TypedefDecl) {2228 EXPECT_TRUE(matches("typedef int typedefDeclTest;",2229 typedefDecl(hasName("typedefDeclTest"))));2230}2231 2232TEST_P(ASTMatchersTest, TypedefDecl_Cxx) {2233 if (!GetParam().isCXX11OrLater()) {2234 return;2235 }2236 EXPECT_TRUE(notMatches("using typedefDeclTest = int;",2237 typedefDecl(hasName("typedefDeclTest"))));2238}2239 2240TEST_P(ASTMatchersTest, TypeAliasDecl) {2241 EXPECT_TRUE(notMatches("typedef int typeAliasTest;",2242 typeAliasDecl(hasName("typeAliasTest"))));2243}2244 2245TEST_P(ASTMatchersTest, TypeAliasDecl_CXX) {2246 if (!GetParam().isCXX11OrLater()) {2247 return;2248 }2249 EXPECT_TRUE(matches("using typeAliasTest = int;",2250 typeAliasDecl(hasName("typeAliasTest"))));2251}2252 2253TEST_P(ASTMatchersTest, TypedefNameDecl) {2254 EXPECT_TRUE(matches("typedef int typedefNameDeclTest1;",2255 typedefNameDecl(hasName("typedefNameDeclTest1"))));2256}2257 2258TEST_P(ASTMatchersTest, TypedefNameDecl_CXX) {2259 if (!GetParam().isCXX11OrLater()) {2260 return;2261 }2262 EXPECT_TRUE(matches("using typedefNameDeclTest = int;",2263 typedefNameDecl(hasName("typedefNameDeclTest"))));2264}2265 2266TEST_P(ASTMatchersTest, TypeAliasTemplateDecl) {2267 if (!GetParam().isCXX11OrLater()) {2268 return;2269 }2270 StringRef Code = R"(2271 template <typename T>2272 class X { T t; };2273 2274 template <typename T>2275 using typeAliasTemplateDecl = X<T>;2276 2277 using typeAliasDecl = X<int>;2278 )";2279 EXPECT_TRUE(2280 matches(Code, typeAliasTemplateDecl(hasName("typeAliasTemplateDecl"))));2281 EXPECT_TRUE(2282 notMatches(Code, typeAliasTemplateDecl(hasName("typeAliasDecl"))));2283}2284 2285TEST_P(ASTMatchersTest, QualifiedTypeLocTest_BindsToConstIntVarDecl) {2286 EXPECT_TRUE(matches("const int x = 0;",2287 qualifiedTypeLoc(loc(asString("const int")))));2288}2289 2290TEST_P(ASTMatchersTest, QualifiedTypeLocTest_BindsToConstIntFunctionDecl) {2291 EXPECT_TRUE(matches("const int f() { return 5; }",2292 qualifiedTypeLoc(loc(asString("const int")))));2293}2294 2295TEST_P(ASTMatchersTest, QualifiedTypeLocTest_DoesNotBindToUnqualifiedVarDecl) {2296 EXPECT_TRUE(notMatches("int x = 0;", qualifiedTypeLoc(loc(asString("int")))));2297}2298 2299TEST_P(ASTMatchersTest, QualifiedTypeLocTest_IntDoesNotBindToConstIntDecl) {2300 EXPECT_TRUE(2301 notMatches("const int x = 0;", qualifiedTypeLoc(loc(asString("int")))));2302}2303 2304TEST_P(ASTMatchersTest, QualifiedTypeLocTest_IntDoesNotBindToConstFloatDecl) {2305 EXPECT_TRUE(2306 notMatches("const float x = 0;", qualifiedTypeLoc(loc(asString("int")))));2307}2308 2309TEST_P(ASTMatchersTest, PointerTypeLocTest_BindsToAnyPointerTypeLoc) {2310 auto matcher = varDecl(hasName("x"), hasTypeLoc(pointerTypeLoc()));2311 EXPECT_TRUE(matches("int* x;", matcher));2312 EXPECT_TRUE(matches("float* x;", matcher));2313 EXPECT_TRUE(matches("char* x;", matcher));2314 EXPECT_TRUE(matches("void* x;", matcher));2315}2316 2317TEST_P(ASTMatchersTest, PointerTypeLocTest_DoesNotBindToNonPointerTypeLoc) {2318 auto matcher = varDecl(hasName("x"), hasTypeLoc(pointerTypeLoc()));2319 EXPECT_TRUE(notMatches("int x;", matcher));2320 EXPECT_TRUE(notMatches("float x;", matcher));2321 EXPECT_TRUE(notMatches("char x;", matcher));2322}2323 2324TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyReferenceTypeLoc) {2325 if (!GetParam().isCXX()) {2326 return;2327 }2328 auto matcher = varDecl(hasName("r"), hasTypeLoc(referenceTypeLoc()));2329 EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher));2330 EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher));2331 EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher));2332 EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher));2333 EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher));2334}2335 2336TEST_P(ASTMatchersTest, ReferenceTypeLocTest_DoesNotBindToNonReferenceTypeLoc) {2337 auto matcher = varDecl(hasName("r"), hasTypeLoc(referenceTypeLoc()));2338 EXPECT_TRUE(notMatches("int r;", matcher));2339 EXPECT_TRUE(notMatches("int r = 3;", matcher));2340 EXPECT_TRUE(notMatches("const int r = 3;", matcher));2341 EXPECT_TRUE(notMatches("int* r;", matcher));2342 EXPECT_TRUE(notMatches("float r;", matcher));2343 EXPECT_TRUE(notMatches("char r;", matcher));2344}2345 2346TEST_P(ASTMatchersTest, ReferenceTypeLocTest_BindsToAnyRvalueReferenceTypeLoc) {2347 if (!GetParam().isCXX()) {2348 return;2349 }2350 auto matcher = varDecl(hasName("r"), hasTypeLoc(referenceTypeLoc()));2351 EXPECT_TRUE(matches("int&& r = 3;", matcher));2352 EXPECT_TRUE(matches("auto&& r = 3;", matcher));2353 EXPECT_TRUE(matches("float&& r = 3.0;", matcher));2354}2355 2356TEST_P(ASTMatchersTest, ArrayTypeLocTest_BindsToAnyArrayTypeLoc) {2357 auto matcher = varDecl(hasName("x"), hasTypeLoc(arrayTypeLoc()));2358 EXPECT_TRUE(matches("int x[3];", matcher));2359 EXPECT_TRUE(matches("float x[3];", matcher));2360 EXPECT_TRUE(matches("char x[3];", matcher));2361 EXPECT_TRUE(matches("void* x[3];", matcher));2362 EXPECT_TRUE(matches("const int x[3] = {1, 2, 3};", matcher));2363 EXPECT_TRUE(matches("int x[3][4];", matcher));2364 EXPECT_TRUE(matches("void foo(int x[]);", matcher));2365 EXPECT_TRUE(matches("int a[] = {1, 2}; void foo() {int x[a[0]];}", matcher));2366}2367 2368TEST_P(ASTMatchersTest, ArrayTypeLocTest_DoesNotBindToNonArrayTypeLoc) {2369 auto matcher = varDecl(hasName("x"), hasTypeLoc(arrayTypeLoc()));2370 EXPECT_TRUE(notMatches("int x;", matcher));2371 EXPECT_TRUE(notMatches("float x;", matcher));2372 EXPECT_TRUE(notMatches("char x;", matcher));2373 EXPECT_TRUE(notMatches("void* x;", matcher));2374}2375 2376TEST_P(ASTMatchersTest,2377 TemplateSpecializationTypeLocTest_BindsToVarDeclTemplateSpecialization) {2378 if (!GetParam().isCXX()) {2379 return;2380 }2381 EXPECT_TRUE(matches(2382 "template <typename T> class C {}; C<char> var;",2383 varDecl(hasName("var"), hasTypeLoc(templateSpecializationTypeLoc()))));2384}2385 2386TEST_P(2387 ASTMatchersTest,2388 TemplateSpecializationTypeLocTest_DoesNotBindToNonTemplateSpecialization) {2389 if (!GetParam().isCXX()) {2390 return;2391 }2392 EXPECT_TRUE(notMatches(2393 "class C {}; C var;",2394 varDecl(hasName("var"), hasTypeLoc(templateSpecializationTypeLoc()))));2395}2396 2397TEST_P(ASTMatchersTest, LambdaCaptureTest) {2398 if (!GetParam().isCXX11OrLater()) {2399 return;2400 }2401 EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",2402 lambdaExpr(hasAnyCapture(lambdaCapture()))));2403}2404 2405TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfVarDecl) {2406 if (!GetParam().isCXX11OrLater()) {2407 return;2408 }2409 auto matcher = lambdaExpr(2410 hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"))))));2411 EXPECT_TRUE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",2412 matcher));2413 EXPECT_TRUE(matches("int main() { int cc; auto f = [&cc](){ return cc; }; }",2414 matcher));2415 EXPECT_TRUE(2416 matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));2417 EXPECT_TRUE(2418 matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));2419 EXPECT_TRUE(matches(2420 "void f(int a) { int cc[a]; auto f = [&](){ return cc;}; }", matcher));2421}2422 2423TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureWithInitializer) {2424 if (!GetParam().isCXX14OrLater()) {2425 return;2426 }2427 auto matcher = lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(2428 varDecl(hasName("cc"), hasInitializer(integerLiteral(equals(1))))))));2429 EXPECT_TRUE(2430 matches("int main() { auto lambda = [cc = 1] {return cc;}; }", matcher));2431 EXPECT_TRUE(2432 matches("int main() { int cc = 2; auto lambda = [cc = 1] {return cc;}; }",2433 matcher));2434}2435 2436TEST_P(ASTMatchersTest, LambdaCaptureTest_DoesNotBindToCaptureOfVarDecl) {2437 if (!GetParam().isCXX11OrLater()) {2438 return;2439 }2440 auto matcher = lambdaExpr(2441 hasAnyCapture(lambdaCapture(capturesVar(varDecl(hasName("cc"))))));2442 EXPECT_FALSE(matches("int main() { auto f = [](){ return 5; }; }", matcher));2443 EXPECT_FALSE(matches("int main() { int xx; auto f = [xx](){ return xx; }; }",2444 matcher));2445}2446 2447TEST_P(ASTMatchersTest,2448 LambdaCaptureTest_DoesNotBindToCaptureWithInitializerAndDifferentName) {2449 if (!GetParam().isCXX14OrLater()) {2450 return;2451 }2452 EXPECT_FALSE(matches(2453 "int main() { auto lambda = [xx = 1] {return xx;}; }",2454 lambdaExpr(hasAnyCapture(lambdaCapture(capturesVar(varDecl(2455 hasName("cc"), hasInitializer(integerLiteral(equals(1))))))))));2456}2457 2458TEST_P(ASTMatchersTest, LambdaCaptureTest_BindsToCaptureOfReferenceType) {2459 if (!GetParam().isCXX20OrLater()) {2460 return;2461 }2462 auto matcher = lambdaExpr(hasAnyCapture(2463 lambdaCapture(capturesVar(varDecl(hasType(referenceType()))))));2464 EXPECT_TRUE(matches("template <class ...T> void f(T &...args) {"2465 " [&...args = args] () mutable {"2466 " }();"2467 "}"2468 "int main() {"2469 " int a;"2470 " f(a);"2471 "}",2472 matcher));2473 EXPECT_FALSE(matches("template <class ...T> void f(T &...args) {"2474 " [...args = args] () mutable {"2475 " }();"2476 "}"2477 "int main() {"2478 " int a;"2479 " f(a);"2480 "}",2481 matcher));2482}2483 2484TEST_P(ASTMatchersTest, IsDerivedFromRecursion) {2485 if (!GetParam().isCXX11OrLater())2486 return;2487 2488 // Check we don't crash on cycles in the traversal and inheritance hierarchy.2489 // Clang will normally enforce there are no cycles, but matchers opted to2490 // traverse primary template for dependent specializations, spuriously2491 // creating the cycles.2492 DeclarationMatcher matcher = cxxRecordDecl(isDerivedFrom("X"));2493 EXPECT_TRUE(notMatches(R"cpp(2494 template <typename T1, typename T2>2495 struct M;2496 2497 template <typename T1>2498 struct M<T1, void> {};2499 2500 template <typename T1, typename T2>2501 struct L : M<T1, T2> {};2502 2503 template <typename T1, typename T2>2504 struct M : L<M<T1, T2>, M<T1, T2>> {};2505 )cpp",2506 matcher));2507 2508 // Check the running time is not exponential. The number of subojects to2509 // traverse grows as fibonacci numbers even though the number of bases to2510 // traverse is quadratic.2511 // The test will hang if implementation of matchers traverses all subojects.2512 EXPECT_TRUE(notMatches(R"cpp(2513 template <class T> struct A0 {};2514 template <class T> struct A1 : A0<T> {};2515 template <class T> struct A2 : A1<T>, A0<T> {};2516 template <class T> struct A3 : A2<T>, A1<T> {};2517 template <class T> struct A4 : A3<T>, A2<T> {};2518 template <class T> struct A5 : A4<T>, A3<T> {};2519 template <class T> struct A6 : A5<T>, A4<T> {};2520 template <class T> struct A7 : A6<T>, A5<T> {};2521 template <class T> struct A8 : A7<T>, A6<T> {};2522 template <class T> struct A9 : A8<T>, A7<T> {};2523 template <class T> struct A10 : A9<T>, A8<T> {};2524 template <class T> struct A11 : A10<T>, A9<T> {};2525 template <class T> struct A12 : A11<T>, A10<T> {};2526 template <class T> struct A13 : A12<T>, A11<T> {};2527 template <class T> struct A14 : A13<T>, A12<T> {};2528 template <class T> struct A15 : A14<T>, A13<T> {};2529 template <class T> struct A16 : A15<T>, A14<T> {};2530 template <class T> struct A17 : A16<T>, A15<T> {};2531 template <class T> struct A18 : A17<T>, A16<T> {};2532 template <class T> struct A19 : A18<T>, A17<T> {};2533 template <class T> struct A20 : A19<T>, A18<T> {};2534 template <class T> struct A21 : A20<T>, A19<T> {};2535 template <class T> struct A22 : A21<T>, A20<T> {};2536 template <class T> struct A23 : A22<T>, A21<T> {};2537 template <class T> struct A24 : A23<T>, A22<T> {};2538 template <class T> struct A25 : A24<T>, A23<T> {};2539 template <class T> struct A26 : A25<T>, A24<T> {};2540 template <class T> struct A27 : A26<T>, A25<T> {};2541 template <class T> struct A28 : A27<T>, A26<T> {};2542 template <class T> struct A29 : A28<T>, A27<T> {};2543 template <class T> struct A30 : A29<T>, A28<T> {};2544 template <class T> struct A31 : A30<T>, A29<T> {};2545 template <class T> struct A32 : A31<T>, A30<T> {};2546 template <class T> struct A33 : A32<T>, A31<T> {};2547 template <class T> struct A34 : A33<T>, A32<T> {};2548 template <class T> struct A35 : A34<T>, A33<T> {};2549 template <class T> struct A36 : A35<T>, A34<T> {};2550 template <class T> struct A37 : A36<T>, A35<T> {};2551 template <class T> struct A38 : A37<T>, A36<T> {};2552 template <class T> struct A39 : A38<T>, A37<T> {};2553 template <class T> struct A40 : A39<T>, A38<T> {};2554)cpp",2555 matcher));2556}2557 2558TEST(ASTMatchersTestObjC, ObjCMessageCalees) {2559 StatementMatcher MessagingFoo =2560 objcMessageExpr(callee(objcMethodDecl(hasName("foo"))));2561 2562 EXPECT_TRUE(matchesObjC("@interface I"2563 "+ (void)foo;"2564 "@end\n"2565 "int main() {"2566 " [I foo];"2567 "}",2568 MessagingFoo));2569 EXPECT_TRUE(notMatchesObjC("@interface I"2570 "+ (void)foo;"2571 "+ (void)bar;"2572 "@end\n"2573 "int main() {"2574 " [I bar];"2575 "}",2576 MessagingFoo));2577 EXPECT_TRUE(matchesObjC("@interface I"2578 "- (void)foo;"2579 "- (void)bar;"2580 "@end\n"2581 "int main() {"2582 " I *i;"2583 " [i foo];"2584 "}",2585 MessagingFoo));2586 EXPECT_TRUE(notMatchesObjC("@interface I"2587 "- (void)foo;"2588 "- (void)bar;"2589 "@end\n"2590 "int main() {"2591 " I *i;"2592 " [i bar];"2593 "}",2594 MessagingFoo));2595}2596 2597TEST(ASTMatchersTestObjC, ObjCMessageExpr) {2598 // Don't find ObjCMessageExpr where none are present.2599 EXPECT_TRUE(notMatchesObjC("", objcMessageExpr(anything())));2600 2601 StringRef Objc1String = "@interface Str "2602 " - (Str *)uppercaseString;"2603 "@end "2604 "@interface foo "2605 "- (void)contents;"2606 "- (void)meth:(Str *)text;"2607 "@end "2608 " "2609 "@implementation foo "2610 "- (void) meth:(Str *)text { "2611 " [self contents];"2612 " Str *up = [text uppercaseString];"2613 "} "2614 "@end ";2615 EXPECT_TRUE(matchesObjC(Objc1String, objcMessageExpr(anything())));2616 EXPECT_TRUE(matchesObjC(Objc1String,2617 objcMessageExpr(hasAnySelector({"contents", "meth:"}))2618 2619 ));2620 EXPECT_TRUE(2621 matchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"))));2622 EXPECT_TRUE(matchesObjC(2623 Objc1String, objcMessageExpr(hasAnySelector("contents", "contentsA"))));2624 EXPECT_FALSE(matchesObjC(2625 Objc1String, objcMessageExpr(hasAnySelector("contentsB", "contentsC"))));2626 EXPECT_TRUE(2627 matchesObjC(Objc1String, objcMessageExpr(matchesSelector("cont*"))));2628 EXPECT_FALSE(2629 matchesObjC(Objc1String, objcMessageExpr(matchesSelector("?cont*"))));2630 EXPECT_TRUE(2631 notMatchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"),2632 hasNullSelector())));2633 EXPECT_TRUE(matchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"),2634 hasUnarySelector())));2635 EXPECT_TRUE(matchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"),2636 numSelectorArgs(0))));2637 EXPECT_TRUE(2638 matchesObjC(Objc1String, objcMessageExpr(matchesSelector("uppercase*"),2639 argumentCountIs(0))));2640}2641 2642TEST(ASTMatchersTestObjC, ObjCStringLiteral) {2643 2644 StringRef Objc1String = "@interface NSObject "2645 "@end "2646 "@interface NSString "2647 "@end "2648 "@interface Test : NSObject "2649 "+ (void)someFunction:(NSString *)Desc; "2650 "@end "2651 "@implementation Test "2652 "+ (void)someFunction:(NSString *)Desc { "2653 " return; "2654 "} "2655 "- (void) foo { "2656 " [Test someFunction:@\"Ola!\"]; "2657 "}\n"2658 "@end ";2659 EXPECT_TRUE(matchesObjC(Objc1String, objcStringLiteral()));2660}2661 2662TEST(ASTMatchersTestObjC, ObjCDecls) {2663 StringRef ObjCString = "@protocol Proto "2664 "- (void)protoDidThing; "2665 "@end "2666 "@interface Thing "2667 "@property int enabled; "2668 "@end "2669 "@interface Thing (ABC) "2670 "- (void)abc_doThing; "2671 "@end "2672 "@implementation Thing "2673 "{ id _ivar; } "2674 "- (void)anything {} "2675 "@end "2676 "@implementation Thing (ABC) "2677 "- (void)abc_doThing {} "2678 "@end ";2679 2680 EXPECT_TRUE(matchesObjC(ObjCString, objcProtocolDecl(hasName("Proto"))));2681 EXPECT_TRUE(2682 matchesObjC(ObjCString, objcImplementationDecl(hasName("Thing"))));2683 EXPECT_TRUE(matchesObjC(ObjCString, objcCategoryDecl(hasName("ABC"))));2684 EXPECT_TRUE(matchesObjC(ObjCString, objcCategoryImplDecl(hasName("ABC"))));2685 EXPECT_TRUE(2686 matchesObjC(ObjCString, objcMethodDecl(hasName("protoDidThing"))));2687 EXPECT_TRUE(matchesObjC(ObjCString, objcMethodDecl(hasName("abc_doThing"))));2688 EXPECT_TRUE(matchesObjC(ObjCString, objcMethodDecl(hasName("anything"))));2689 EXPECT_TRUE(matchesObjC(ObjCString, objcIvarDecl(hasName("_ivar"))));2690 EXPECT_TRUE(matchesObjC(ObjCString, objcPropertyDecl(hasName("enabled"))));2691}2692 2693TEST(ASTMatchersTestObjC, ObjCExceptionStmts) {2694 StringRef ObjCString = "void f(id obj) {"2695 " @try {"2696 " @throw obj;"2697 " } @catch (...) {"2698 " } @finally {}"2699 "}";2700 2701 EXPECT_TRUE(matchesObjC(ObjCString, objcTryStmt()));2702 EXPECT_TRUE(matchesObjC(ObjCString, objcThrowStmt()));2703 EXPECT_TRUE(matchesObjC(ObjCString, objcCatchStmt()));2704 EXPECT_TRUE(matchesObjC(ObjCString, objcFinallyStmt()));2705}2706 2707TEST(ASTMatchersTest, DecompositionDecl) {2708 StringRef Code = R"cpp(2709void foo()2710{2711 int arr[3];2712 auto &[f, s, t] = arr;2713 2714 f = 42;2715}2716 )cpp";2717 EXPECT_TRUE(matchesConditionally(2718 Code, decompositionDecl(hasBinding(0, bindingDecl(hasName("f")))), true,2719 {"-std=c++17"}));2720 EXPECT_FALSE(matchesConditionally(2721 Code, decompositionDecl(hasBinding(42, bindingDecl(hasName("f")))), true,2722 {"-std=c++17"}));2723 EXPECT_FALSE(matchesConditionally(2724 Code, decompositionDecl(hasBinding(0, bindingDecl(hasName("s")))), true,2725 {"-std=c++17"}));2726 EXPECT_TRUE(matchesConditionally(2727 Code, decompositionDecl(hasBinding(1, bindingDecl(hasName("s")))), true,2728 {"-std=c++17"}));2729 2730 EXPECT_TRUE(matchesConditionally(2731 Code,2732 bindingDecl(decl().bind("self"), hasName("f"),2733 forDecomposition(decompositionDecl(2734 hasAnyBinding(bindingDecl(equalsBoundNode("self")))))),2735 true, {"-std=c++17"}));2736}2737 2738TEST(ASTMatchersTestObjC, ObjCAutoreleasePoolStmt) {2739 StringRef ObjCString = "void f() {"2740 "@autoreleasepool {"2741 " int x = 1;"2742 "}"2743 "}";2744 EXPECT_TRUE(matchesObjC(ObjCString, autoreleasePoolStmt()));2745 StringRef ObjCStringNoPool = "void f() { int x = 1; }";2746 EXPECT_FALSE(matchesObjC(ObjCStringNoPool, autoreleasePoolStmt()));2747}2748 2749TEST(ASTMatchersTestOpenMP, OMPExecutableDirective) {2750 auto Matcher = stmt(ompExecutableDirective());2751 2752 StringRef Source0 = R"(2753void x() {2754#pragma omp parallel2755;2756})";2757 EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher));2758 2759 StringRef Source1 = R"(2760void x() {2761#pragma omp taskyield2762;2763})";2764 EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher));2765 2766 StringRef Source2 = R"(2767void x() {2768;2769})";2770 EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher));2771}2772 2773TEST(ASTMatchersTestOpenMP, OMPDefaultClause) {2774 auto Matcher = ompExecutableDirective(hasAnyClause(ompDefaultClause()));2775 2776 StringRef Source0 = R"(2777void x() {2778;2779})";2780 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));2781 2782 StringRef Source1 = R"(2783void x() {2784#pragma omp parallel2785;2786})";2787 EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));2788 2789 StringRef Source2 = R"(2790void x() {2791#pragma omp parallel default(none)2792;2793})";2794 EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher));2795 2796 StringRef Source3 = R"(2797void x() {2798#pragma omp parallel default(shared)2799;2800})";2801 EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher));2802 2803 StringRef Source4 = R"(2804void x() {2805#pragma omp parallel default(firstprivate)2806;2807})";2808 EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));2809 2810 StringRef Source5 = R"(2811void x(int x) {2812#pragma omp parallel num_threads(x)2813;2814})";2815 EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher));2816}2817 2818TEST(ASTMatchersTest, Finder_DynamicOnlyAcceptsSomeMatchers) {2819 MatchFinder Finder;2820 EXPECT_TRUE(Finder.addDynamicMatcher(decl(), nullptr));2821 EXPECT_TRUE(Finder.addDynamicMatcher(callExpr(), nullptr));2822 EXPECT_TRUE(2823 Finder.addDynamicMatcher(constantArrayType(hasSize(42)), nullptr));2824 2825 // Do not accept non-toplevel matchers.2826 EXPECT_FALSE(Finder.addDynamicMatcher(isMain(), nullptr));2827 EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr));2828}2829 2830TEST(MatchFinderAPI, MatchesDynamic) {2831 StringRef SourceCode = "struct A { void f() {} };";2832 auto Matcher = functionDecl(isDefinition()).bind("method");2833 2834 auto astUnit = tooling::buildASTFromCode(SourceCode);2835 2836 auto GlobalBoundNodes = matchDynamic(Matcher, astUnit->getASTContext());2837 2838 EXPECT_EQ(GlobalBoundNodes.size(), 1u);2839 EXPECT_EQ(GlobalBoundNodes[0].getMap().size(), 1u);2840 2841 auto GlobalMethodNode = GlobalBoundNodes[0].getNodeAs<FunctionDecl>("method");2842 EXPECT_TRUE(GlobalMethodNode != nullptr);2843 2844 auto MethodBoundNodes =2845 matchDynamic(Matcher, *GlobalMethodNode, astUnit->getASTContext());2846 EXPECT_EQ(MethodBoundNodes.size(), 1u);2847 EXPECT_EQ(MethodBoundNodes[0].getMap().size(), 1u);2848 2849 auto MethodNode = MethodBoundNodes[0].getNodeAs<FunctionDecl>("method");2850 EXPECT_EQ(MethodNode, GlobalMethodNode);2851}2852 2853static std::vector<TestClangConfig> allTestClangConfigs() {2854 std::vector<TestClangConfig> all_configs;2855 for (TestLanguage lang : {2856#define TESTLANGUAGE(lang, version, std_flag, version_index) \2857 Lang_##lang##version,2858#include "clang/Testing/TestLanguage.def"2859 }) {2860 TestClangConfig config;2861 config.Language = lang;2862 2863 // Use an unknown-unknown triple so we don't instantiate the full system2864 // toolchain. On Linux, instantiating the toolchain involves stat'ing2865 // large portions of /usr/lib, and this slows down not only this test, but2866 // all other tests, via contention in the kernel.2867 //2868 // FIXME: This is a hack to work around the fact that there's no way to do2869 // the equivalent of runToolOnCodeWithArgs without instantiating a full2870 // Driver. We should consider having a function, at least for tests, that2871 // invokes cc1.2872 config.Target = "i386-unknown-unknown";2873 all_configs.push_back(config);2874 2875 // Windows target is interesting to test because it enables2876 // `-fdelayed-template-parsing`.2877 config.Target = "x86_64-pc-win32-msvc";2878 all_configs.push_back(config);2879 }2880 return all_configs;2881}2882 2883INSTANTIATE_TEST_SUITE_P(2884 ASTMatchersTests, ASTMatchersTest, testing::ValuesIn(allTestClangConfigs()),2885 [](const testing::TestParamInfo<TestClangConfig> &Info) {2886 return Info.param.toShortString();2887 });2888 2889} // namespace ast_matchers2890} // namespace clang2891