6702 lines · cpp
1//= unittests/ASTMatchers/ASTMatchersTraversalTest.cpp - matchers 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/Attrs.inc"11#include "clang/AST/DeclCXX.h"12#include "clang/AST/PrettyPrinter.h"13#include "clang/ASTMatchers/ASTMatchFinder.h"14#include "clang/ASTMatchers/ASTMatchers.h"15#include "clang/Tooling/Tooling.h"16#include "llvm/ADT/StringRef.h"17#include "llvm/TargetParser/Host.h"18#include "llvm/TargetParser/Triple.h"19#include "gtest/gtest.h"20 21namespace clang {22namespace ast_matchers {23 24TEST(DeclarationMatcher, hasMethod) {25 EXPECT_TRUE(matches("class A { void func(); };",26 cxxRecordDecl(hasMethod(hasName("func")))));27 EXPECT_TRUE(notMatches("class A { void func(); };",28 cxxRecordDecl(hasMethod(isPublic()))));29}30 31TEST(DeclarationMatcher, ClassDerivedFromDependentTemplateSpecialization) {32 EXPECT_TRUE(matches(33 "template <typename T> struct A {"34 " template <typename T2> struct F {};"35 "};"36 "template <typename T> struct B : A<T>::template F<T> {};"37 "B<int> b;",38 cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));39}40 41TEST(DeclarationMatcher, hasDeclContext) {42 EXPECT_TRUE(matches(43 "namespace N {"44 " namespace M {"45 " class D {};"46 " }"47 "}",48 recordDecl(hasDeclContext(namespaceDecl(hasName("M"))))));49 EXPECT_TRUE(notMatches(50 "namespace N {"51 " namespace M {"52 " class D {};"53 " }"54 "}",55 recordDecl(hasDeclContext(namespaceDecl(hasName("N"))))));56 57 EXPECT_TRUE(matches("namespace {"58 " namespace M {"59 " class D {};"60 " }"61 "}",62 recordDecl(hasDeclContext(namespaceDecl(63 hasName("M"), hasDeclContext(namespaceDecl()))))));64 65 EXPECT_TRUE(matches("class D{};", decl(hasDeclContext(decl()))));66}67 68TEST(HasDescendant, MatchesDescendantTypes) {69 EXPECT_TRUE(matches("void f() { int i = 3; }",70 decl(hasDescendant(loc(builtinType())))));71 EXPECT_TRUE(matches("void f() { int i = 3; }",72 stmt(hasDescendant(builtinType()))));73 74 EXPECT_TRUE(matches("void f() { int i = 3; }",75 stmt(hasDescendant(loc(builtinType())))));76 EXPECT_TRUE(matches("void f() { int i = 3; }",77 stmt(hasDescendant(qualType(builtinType())))));78 79 EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }",80 stmt(hasDescendant(isInteger()))));81 82 EXPECT_TRUE(matchAndVerifyResultTrue(83 "void f() { int a; float c; int d; int e; }",84 functionDecl(forEachDescendant(85 varDecl(hasDescendant(isInteger())).bind("x"))),86 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 3)));87}88 89TEST(HasDescendant, MatchesDescendantsOfTypes) {90 EXPECT_TRUE(matches("void f() { int*** i; }",91 qualType(hasDescendant(builtinType()))));92 EXPECT_TRUE(matches("void f() { int*** i; }",93 qualType(hasDescendant(94 pointerType(pointee(builtinType()))))));95 EXPECT_TRUE(matches("void f() { int*** i; }",96 typeLoc(hasDescendant(loc(builtinType())))));97 98 EXPECT_TRUE(matchAndVerifyResultTrue(99 "void f() { int*** i; }",100 qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))),101 std::make_unique<VerifyIdIsBoundTo<Type>>("x", 2)));102}103 104 105TEST(Has, MatchesChildrenOfTypes) {106 EXPECT_TRUE(matches("int i;",107 varDecl(hasName("i"), has(isInteger()))));108 EXPECT_TRUE(notMatches("int** i;",109 varDecl(hasName("i"), has(isInteger()))));110 EXPECT_TRUE(matchAndVerifyResultTrue(111 "int (*f)(float, int);",112 qualType(functionType(), forEach(qualType(isInteger()).bind("x"))),113 std::make_unique<VerifyIdIsBoundTo<QualType>>("x", 2)));114}115 116TEST(Has, MatchesChildTypes) {117 EXPECT_TRUE(matches(118 "int* i;",119 varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));120 EXPECT_TRUE(notMatches(121 "int* i;",122 varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));123}124 125TEST(StatementMatcher, Has) {126 StatementMatcher HasVariableI =127 expr(hasType(pointsTo(recordDecl(hasName("X")))),128 has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i")))))));129 130 EXPECT_TRUE(matches(131 "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));132 EXPECT_TRUE(notMatches(133 "class X; X *x(int); void c() { int i; x(42); }", HasVariableI));134}135 136TEST(StatementMatcher, HasDescendant) {137 StatementMatcher HasDescendantVariableI =138 expr(hasType(pointsTo(recordDecl(hasName("X")))),139 hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));140 141 EXPECT_TRUE(matches(142 "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",143 HasDescendantVariableI));144 EXPECT_TRUE(notMatches(145 "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",146 HasDescendantVariableI));147}148 149TEST(TypeMatcher, MatchesClassType) {150 TypeMatcher TypeA = hasDeclaration(recordDecl(hasName("A")));151 152 EXPECT_TRUE(matches("class A { public: A *a; };", TypeA));153 EXPECT_TRUE(notMatches("class A {};", TypeA));154 155 TypeMatcher TypeDerivedFromA =156 hasDeclaration(cxxRecordDecl(isDerivedFrom("A")));157 158 EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",159 TypeDerivedFromA));160 EXPECT_TRUE(notMatches("class A {};", TypeA));161 162 TypeMatcher TypeAHasClassB = hasDeclaration(163 recordDecl(hasName("A"), has(recordDecl(hasName("B")))));164 165 EXPECT_TRUE(166 matches("class A { public: A *a; class B {}; };", TypeAHasClassB));167 168 EXPECT_TRUE(matchesC("struct S {}; void f(void) { struct S s; }",169 varDecl(hasType(namedDecl(hasName("S"))))));170}171 172TEST(TypeMatcher, MatchesDeclTypes) {173 // TypedefType -> TypedefNameDecl174 EXPECT_TRUE(matches("typedef int I; void f(I i);",175 parmVarDecl(hasType(namedDecl(hasName("I"))))));176 // ObjCObjectPointerType177 EXPECT_TRUE(matchesObjC("@interface Foo @end void f(Foo *f);",178 parmVarDecl(hasType(objcObjectPointerType()))));179 // ObjCObjectPointerType -> ObjCInterfaceType -> ObjCInterfaceDecl180 EXPECT_TRUE(matchesObjC(181 "@interface Foo @end void f(Foo *f);",182 parmVarDecl(hasType(pointsTo(objcInterfaceDecl(hasName("Foo")))))));183 // TemplateTypeParmType184 EXPECT_TRUE(matches("template <typename T> void f(T t);",185 parmVarDecl(hasType(templateTypeParmType()))));186 // TemplateTypeParmType -> TemplateTypeParmDecl187 EXPECT_TRUE(matches("template <typename T> void f(T t);",188 parmVarDecl(hasType(namedDecl(hasName("T"))))));189 // InjectedClassNameType190 EXPECT_TRUE(matches("template <typename T> struct S {"191 " void f(S s);"192 "};",193 parmVarDecl(hasType(injectedClassNameType()))));194 EXPECT_TRUE(notMatches("template <typename T> struct S {"195 " void g(S<T> s);"196 "};",197 parmVarDecl(hasType(injectedClassNameType()))));198 // InjectedClassNameType -> CXXRecordDecl199 EXPECT_TRUE(matches("template <typename T> struct S {"200 " void f(S s);"201 "};",202 parmVarDecl(hasType(namedDecl(hasName("S"))))));203 204 static const char Using[] = "template <typename T>"205 "struct Base {"206 " typedef T Foo;"207 "};"208 ""209 "template <typename T>"210 "struct S : private Base<T> {"211 " using typename Base<T>::Foo;"212 " void f(Foo);"213 "};";214 // UnresolvedUsingTypenameDecl215 EXPECT_TRUE(matches(Using, unresolvedUsingTypenameDecl(hasName("Foo"))));216 // UnresolvedUsingTypenameType -> UnresolvedUsingTypenameDecl217 EXPECT_TRUE(matches(Using, parmVarDecl(hasType(namedDecl(hasName("Foo"))))));218}219 220TEST(HasDeclaration, HasDeclarationOfEnumType) {221 EXPECT_TRUE(matches("enum X {}; void y(X *x) { x; }",222 expr(hasType(pointsTo(223 qualType(hasDeclaration(enumDecl(hasName("X")))))))));224}225 226TEST(HasDeclaration, HasGetDeclTraitTest) {227 static_assert(internal::has_getDecl<TypedefType>,228 "Expected TypedefType to have a getDecl.");229 static_assert(!internal::has_getDecl<TemplateSpecializationType>,230 "Expected TemplateSpecializationType to *not* have a getDecl.");231}232 233TEST(HasDeclaration, ElaboratedType) {234 static const char Elaborated[] = "namespace n { struct X {}; }"235 "void f(n::X);";236 EXPECT_TRUE(237 matches(Elaborated,238 parmVarDecl(hasType(qualType(hasDeclaration(cxxRecordDecl()))))));239 EXPECT_TRUE(matches(Elaborated, parmVarDecl(hasType(recordType(240 hasDeclaration(cxxRecordDecl()))))));241}242 243TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) {244 EXPECT_TRUE(matches(245 "typedef int X; X a;",246 varDecl(hasName("a"), hasType(typedefType(hasDeclaration(decl()))))));247 248 // FIXME: Add tests for other types with getDecl() (e.g. RecordType)249}250 251TEST(HasDeclaration, HasDeclarationOfTemplateSpecializationType) {252 EXPECT_TRUE(matches("template <typename T> class A {}; A<int> a;",253 varDecl(hasType(templateSpecializationType(254 hasDeclaration(namedDecl(hasName("A"))))))));255 EXPECT_TRUE(matches("template <typename T> class A {};"256 "template <typename T> class B { A<T> a; };",257 fieldDecl(hasType(templateSpecializationType(258 hasDeclaration(namedDecl(hasName("A"))))))));259 EXPECT_TRUE(matches("template <typename T> class A {}; A<int> a;",260 varDecl(hasType(templateSpecializationType(261 hasDeclaration(cxxRecordDecl()))))));262}263 264TEST(HasDeclaration, HasDeclarationOfCXXNewExpr) {265 EXPECT_TRUE(266 matches("int *A = new int();",267 cxxNewExpr(hasDeclaration(functionDecl(parameterCountIs(1))))));268}269 270TEST(HasDeclaration, HasDeclarationOfTypeAlias) {271 EXPECT_TRUE(matches("template <typename T> using C = T; C<int> c;",272 varDecl(hasType(templateSpecializationType(273 hasDeclaration(typeAliasTemplateDecl()))))));274}275 276TEST(HasDeclaration, HasDeclarationOfObjCInterface) {277 EXPECT_TRUE(matchesObjC("@interface BaseClass @end void f() {BaseClass* b;}",278 varDecl(hasType(objcObjectPointerType(279 pointee(hasDeclaration(objcInterfaceDecl())))))));280}281 282TEST(HasUnqualifiedDesugaredType, DesugarsUsing) {283 EXPECT_TRUE(284 matches("struct A {}; using B = A; B b;",285 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));286 EXPECT_TRUE(287 matches("struct A {}; using B = A; using C = B; C b;",288 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));289}290 291TEST(HasUnderlyingDecl, Matches) {292 EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }"293 "template <class T> void g() { using N::f; f(T()); }",294 unresolvedLookupExpr(hasAnyDeclaration(295 namedDecl(hasUnderlyingDecl(hasName("::N::f")))))));296 EXPECT_TRUE(matches(297 "namespace N { template <class T> void f(T t); }"298 "template <class T> void g() { N::f(T()); }",299 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));300 EXPECT_TRUE(notMatches(301 "namespace N { template <class T> void f(T t); }"302 "template <class T> void g() { using N::f; f(T()); }",303 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));304}305 306TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {307 TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));308 EXPECT_TRUE(309 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));310 EXPECT_TRUE(311 notMatches("class X {}; void y(X *x) { x; }",312 expr(hasType(ClassX))));313 EXPECT_TRUE(314 matches("class X {}; void y(X *x) { x; }",315 expr(hasType(pointsTo(ClassX)))));316}317 318TEST(HasType, TakesQualTypeMatcherAndMatchesValueDecl) {319 TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));320 EXPECT_TRUE(321 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));322 EXPECT_TRUE(323 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));324 EXPECT_TRUE(325 matches("class X {}; void y() { X *x; }",326 varDecl(hasType(pointsTo(ClassX)))));327}328 329TEST(HasType, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier) {330 TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));331 CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX));332 DeclarationMatcher ClassHasBaseClassX =333 cxxRecordDecl(hasDirectBase(BaseClassX));334 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX));335 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX));336}337 338TEST(HasType, TakesDeclMatcherAndMatchesExpr) {339 DeclarationMatcher ClassX = recordDecl(hasName("X"));340 EXPECT_TRUE(341 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));342 EXPECT_TRUE(343 notMatches("class X {}; void y(X *x) { x; }",344 expr(hasType(ClassX))));345}346 347TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {348 DeclarationMatcher ClassX = recordDecl(hasName("X"));349 EXPECT_TRUE(350 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));351 EXPECT_TRUE(352 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));353}354 355TEST(HasType, TakesDeclMatcherAndMatchesCXXBaseSpecifier) {356 DeclarationMatcher ClassX = recordDecl(hasName("X"));357 CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX));358 DeclarationMatcher ClassHasBaseClassX =359 cxxRecordDecl(hasDirectBase(BaseClassX));360 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX));361 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX));362}363 364TEST(HasType, MatchesTypedefDecl) {365 EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));366 EXPECT_TRUE(matches("typedef const int T;",367 typedefDecl(hasType(asString("const int")))));368 EXPECT_TRUE(notMatches("typedef const int T;",369 typedefDecl(hasType(asString("int")))));370 EXPECT_TRUE(matches("typedef int foo; typedef foo bar;",371 typedefDecl(hasType(asString("foo")), hasName("bar"))));372}373 374TEST(HasType, MatchesTypedefNameDecl) {375 EXPECT_TRUE(matches("using X = int;", typedefNameDecl(hasType(asString("int")))));376 EXPECT_TRUE(matches("using T = const int;",377 typedefNameDecl(hasType(asString("const int")))));378 EXPECT_TRUE(notMatches("using T = const int;",379 typedefNameDecl(hasType(asString("int")))));380 EXPECT_TRUE(matches("using foo = int; using bar = foo;",381 typedefNameDecl(hasType(asString("foo")), hasName("bar"))));382}383 384TEST(HasTypeLoc, MatchesBlockDecl) {385 EXPECT_TRUE(matchesConditionally(386 "auto x = ^int (int a, int b) { return a + b; };",387 blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true,388 {"-fblocks"}));389}390 391TEST(HasTypeLoc, MatchesCXXBaseSpecifierAndCtorInitializer) {392 llvm::StringRef code = R"cpp(393 class Foo {};394 class Bar : public Foo {395 Bar() : Foo() {}396 };397 )cpp";398 399 EXPECT_TRUE(matches(400 code, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("Foo")))))));401 EXPECT_TRUE(402 matches(code, cxxCtorInitializer(hasTypeLoc(loc(asString("Foo"))))));403}404 405TEST(HasTypeLoc, MatchesCXXFunctionalCastExpr) {406 EXPECT_TRUE(matches("auto x = int(3);",407 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int"))))));408}409 410TEST(HasTypeLoc, MatchesCXXNewExpr) {411 EXPECT_TRUE(matches("auto* x = new int(3);",412 cxxNewExpr(hasTypeLoc(loc(asString("int"))))));413 EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();",414 cxxNewExpr(hasTypeLoc(loc(asString("Foo"))))));415}416 417TEST(HasTypeLoc, MatchesCXXTemporaryObjectExpr) {418 EXPECT_TRUE(419 matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",420 cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("Foo"))))));421}422 423TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) {424 EXPECT_TRUE(425 matches("template <typename T> T make() { return T(); }",426 cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));427}428 429TEST(HasTypeLoc, MatchesCompoundLiteralExpr) {430 EXPECT_TRUE(431 matches("int* x = (int[2]) { 0, 1 };",432 compoundLiteralExpr(hasTypeLoc(loc(asString("int[2]"))))));433}434 435TEST(HasTypeLoc, MatchesDeclaratorDecl) {436 EXPECT_TRUE(matches("int x;",437 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));438 EXPECT_TRUE(matches("int x(3);",439 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));440 EXPECT_TRUE(matches("struct Foo { Foo(int, int); }; Foo x(1, 2);",441 varDecl(hasName("x"), hasTypeLoc(loc(asString("Foo"))))));442 443 // Make sure we don't crash on implicit constructors.444 EXPECT_TRUE(notMatches("class X {}; X x;",445 declaratorDecl(hasTypeLoc(loc(asString("int"))))));446}447 448TEST(HasTypeLoc, MatchesExplicitCastExpr) {449 EXPECT_TRUE(matches("auto x = (int) 3;",450 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));451 EXPECT_TRUE(matches("auto x = static_cast<int>(3);",452 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));453}454 455TEST(HasTypeLoc, MatchesObjCPropertyDecl) {456 EXPECT_TRUE(matchesObjC(R"objc(457 @interface Foo458 @property int enabled;459 @end460 )objc",461 objcPropertyDecl(hasTypeLoc(loc(asString("int"))))));462}463 464TEST(HasTypeLoc, MatchesTemplateArgumentLoc) {465 EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;",466 templateArgumentLoc(hasTypeLoc(loc(asString("int"))))));467}468 469TEST(HasTypeLoc, MatchesTypedefNameDecl) {470 EXPECT_TRUE(matches("typedef int X;",471 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));472 EXPECT_TRUE(matches("using X = int;",473 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));474}475 476TEST(Callee, MatchesDeclarations) {477 StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x"))));478 479 EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));480 EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));481 482 CallMethodX = traverse(TK_AsIs, callExpr(callee(cxxConversionDecl())));483 EXPECT_TRUE(484 matches("struct Y { operator int() const; }; int i = Y();", CallMethodX));485 EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",486 CallMethodX));487}488 489TEST(Callee, MatchesMemberExpressions) {490 EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",491 callExpr(callee(memberExpr()))));492 EXPECT_TRUE(493 notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));494}495 496TEST(Matcher, Argument) {497 StatementMatcher CallArgumentY = callExpr(498 hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));499 500 EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY));501 EXPECT_TRUE(502 matches("class X { void x(int) { int y; x(y); } };", CallArgumentY));503 EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY));504 505 StatementMatcher WrongIndex = callExpr(506 hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));507 EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex));508}509 510TEST(Matcher, AnyArgument) {511 auto HasArgumentY = hasAnyArgument(512 ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));513 StatementMatcher CallArgumentY = callExpr(HasArgumentY);514 StatementMatcher CtorArgumentY = cxxConstructExpr(HasArgumentY);515 StatementMatcher UnresolvedCtorArgumentY =516 cxxUnresolvedConstructExpr(HasArgumentY);517 StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);518 EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));519 EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));520 EXPECT_TRUE(matches("struct Y { Y(int, int); };"521 "void x() { int y; (void)Y(1, y); }",522 CtorArgumentY));523 EXPECT_TRUE(matches("struct Y { Y(int, int); };"524 "void x() { int y; (void)Y(y, 42); }",525 CtorArgumentY));526 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",527 UnresolvedCtorArgumentY));528 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",529 UnresolvedCtorArgumentY));530 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "531 "void x(I* i) { int y; [i f:y]; }",532 ObjCCallArgumentY));533 EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "534 "void x(I* i) { int z; [i f:z]; }",535 ObjCCallArgumentY));536 EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));537 EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"538 "void x() { int y; (void)Y(1, 2); }",539 CtorArgumentY));540 EXPECT_TRUE(notMatches("template <class Y>"541 "void x() { int y; (void)Y(1, 2); }",542 UnresolvedCtorArgumentY));543 544 StatementMatcher ImplicitCastedArgument =545 traverse(TK_AsIs, callExpr(hasAnyArgument(implicitCastExpr())));546 EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument));547}548 549TEST(Matcher, HasReceiver) {550 EXPECT_TRUE(matchesObjC(551 "@interface NSString @end "552 "void f(NSString *x) {"553 "[x containsString];"554 "}",555 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));556 557 EXPECT_FALSE(matchesObjC(558 "@interface NSString +(NSString *) stringWithFormat; @end "559 "void f() { [NSString stringWithFormat]; }",560 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));561}562 563TEST(Matcher, MatchesMethodsOnLambda) {564 StringRef Code = R"cpp(565struct A {566 ~A() {}567};568void foo()569{570 A a;571 auto l = [a] { };572 auto lCopy = l;573 auto lPtrDecay = +[] { };574 (void)lPtrDecay;575}576)cpp";577 578 EXPECT_TRUE(matches(579 Code, cxxConstructorDecl(580 hasBody(compoundStmt()),581 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),582 isCopyConstructor())));583 EXPECT_TRUE(matches(584 Code, cxxConstructorDecl(585 hasBody(compoundStmt()),586 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),587 isMoveConstructor())));588 EXPECT_TRUE(matches(589 Code, cxxDestructorDecl(590 hasBody(compoundStmt()),591 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))))));592 EXPECT_TRUE(matches(593 Code, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt(594 hasReturnValue(implicitCastExpr()))))),595 hasAncestor(lambdaExpr(hasAncestor(596 varDecl(hasName("lPtrDecay"))))))));597}598 599TEST(Matcher, MatchesCoroutine) {600 FileContentMappings M;601 M.push_back(std::make_pair("/coro_header", R"cpp(602namespace std {603 604template <class... Args>605struct void_t_imp {606 using type = void;607};608template <class... Args>609using void_t = typename void_t_imp<Args...>::type;610 611template <class T, class = void>612struct traits_sfinae_base {};613 614template <class T>615struct traits_sfinae_base<T, void_t<typename T::promise_type>> {616 using promise_type = typename T::promise_type;617};618 619template <class Ret, class... Args>620struct coroutine_traits : public traits_sfinae_base<Ret> {};621} // namespace std622struct awaitable {623 bool await_ready() noexcept;624 template <typename F>625 void await_suspend(F) noexcept;626 void await_resume() noexcept;627} a;628struct promise {629 void get_return_object();630 awaitable initial_suspend();631 awaitable final_suspend() noexcept;632 awaitable yield_value(int); // expected-note 2{{candidate}}633 void return_value(int); // expected-note 2{{here}}634 void unhandled_exception();635};636template <typename... T>637struct std::coroutine_traits<void, T...> { using promise_type = promise; };638namespace std {639template <class PromiseType = void>640struct coroutine_handle {641 static coroutine_handle from_address(void *) noexcept;642};643} // namespace std644)cpp"));645 StringRef CoReturnCode = R"cpp(646#include <coro_header>647void check_match_co_return() {648 co_return 1;649}650)cpp";651 EXPECT_TRUE(matchesConditionally(CoReturnCode,652 coreturnStmt(isExpansionInMainFile()), true,653 {"-std=c++20", "-I/"}, M));654 StringRef CoAwaitCode = R"cpp(655#include <coro_header>656void check_match_co_await() {657 co_await a;658 co_return 1;659}660)cpp";661 EXPECT_TRUE(matchesConditionally(CoAwaitCode,662 coawaitExpr(isExpansionInMainFile()), true,663 {"-std=c++20", "-I/"}, M));664 StringRef CoYieldCode = R"cpp(665#include <coro_header>666void check_match_co_yield() {667 co_yield 1.0;668 co_return 1;669}670)cpp";671 EXPECT_TRUE(matchesConditionally(CoYieldCode,672 coyieldExpr(isExpansionInMainFile()), true,673 {"-std=c++20", "-I/"}, M));674 675 StringRef NonCoroCode = R"cpp(676#include <coro_header>677void non_coro_function() {678}679)cpp";680 681 EXPECT_TRUE(matchesConditionally(CoReturnCode, coroutineBodyStmt(), true,682 {"-std=c++20", "-I/"}, M));683 EXPECT_TRUE(matchesConditionally(CoAwaitCode, coroutineBodyStmt(), true,684 {"-std=c++20", "-I/"}, M));685 EXPECT_TRUE(matchesConditionally(CoYieldCode, coroutineBodyStmt(), true,686 {"-std=c++20", "-I/"}, M));687 688 EXPECT_FALSE(matchesConditionally(NonCoroCode, coroutineBodyStmt(), true,689 {"-std=c++20", "-I/"}, M));690 691 StringRef CoroWithDeclCode = R"cpp(692#include <coro_header>693void coro() {694 int thevar;695 co_return 1;696}697)cpp";698 EXPECT_TRUE(matchesConditionally(699 CoroWithDeclCode,700 coroutineBodyStmt(hasBody(compoundStmt(701 has(declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))),702 true, {"-std=c++20", "-I/"}, M));703 704 StringRef CoroWithTryCatchDeclCode = R"cpp(705#include <coro_header>706void coro() try {707 int thevar;708 co_return 1;709} catch (...) { co_return 1; }710)cpp";711 EXPECT_TRUE(matchesConditionally(712 CoroWithTryCatchDeclCode,713 coroutineBodyStmt(hasBody(compoundStmt(has(cxxTryStmt(has(compoundStmt(has(714 declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))))),715 true, {"-std=c++20", "-I/"}, M));716}717 718TEST(Matcher, isClassMessage) {719 EXPECT_TRUE(matchesObjC(720 "@interface NSString +(NSString *) stringWithFormat; @end "721 "void f() { [NSString stringWithFormat]; }",722 objcMessageExpr(isClassMessage())));723 724 EXPECT_FALSE(matchesObjC(725 "@interface NSString @end "726 "void f(NSString *x) {"727 "[x containsString];"728 "}",729 objcMessageExpr(isClassMessage())));730}731 732TEST(Matcher, isInstanceMessage) {733 EXPECT_TRUE(matchesObjC(734 "@interface NSString @end "735 "void f(NSString *x) {"736 "[x containsString];"737 "}",738 objcMessageExpr(isInstanceMessage())));739 740 EXPECT_FALSE(matchesObjC(741 "@interface NSString +(NSString *) stringWithFormat; @end "742 "void f() { [NSString stringWithFormat]; }",743 objcMessageExpr(isInstanceMessage())));744 745}746 747TEST(Matcher, isClassMethod) {748 EXPECT_TRUE(matchesObjC(749 "@interface Bar + (void)bar; @end",750 objcMethodDecl(isClassMethod())));751 752 EXPECT_TRUE(matchesObjC(753 "@interface Bar @end"754 "@implementation Bar + (void)bar {} @end",755 objcMethodDecl(isClassMethod())));756 757 EXPECT_FALSE(matchesObjC(758 "@interface Foo - (void)foo; @end",759 objcMethodDecl(isClassMethod())));760 761 EXPECT_FALSE(matchesObjC(762 "@interface Foo @end "763 "@implementation Foo - (void)foo {} @end",764 objcMethodDecl(isClassMethod())));765}766 767TEST(Matcher, isInstanceMethod) {768 EXPECT_TRUE(matchesObjC(769 "@interface Foo - (void)foo; @end",770 objcMethodDecl(isInstanceMethod())));771 772 EXPECT_TRUE(matchesObjC(773 "@interface Foo @end "774 "@implementation Foo - (void)foo {} @end",775 objcMethodDecl(isInstanceMethod())));776 777 EXPECT_FALSE(matchesObjC(778 "@interface Bar + (void)bar; @end",779 objcMethodDecl(isInstanceMethod())));780 781 EXPECT_FALSE(matchesObjC(782 "@interface Bar @end"783 "@implementation Bar + (void)bar {} @end",784 objcMethodDecl(isInstanceMethod())));785}786 787TEST(MatcherCXXMemberCallExpr, On) {788 StringRef Snippet1 = R"cc(789 struct Y {790 void m();791 };792 void z(Y y) { y.m(); }793 )cc";794 StringRef Snippet2 = R"cc(795 struct Y {796 void m();797 };798 struct X : public Y {};799 void z(X x) { x.m(); }800 )cc";801 auto MatchesY = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))));802 EXPECT_TRUE(matches(Snippet1, MatchesY));803 EXPECT_TRUE(notMatches(Snippet2, MatchesY));804 805 auto MatchesX = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))));806 EXPECT_TRUE(matches(Snippet2, MatchesX));807 808 // Parens are ignored.809 StringRef Snippet3 = R"cc(810 struct Y {811 void m();812 };813 Y g();814 void z(Y y) { (g()).m(); }815 )cc";816 auto MatchesCall = cxxMemberCallExpr(on(callExpr()));817 EXPECT_TRUE(matches(Snippet3, MatchesCall));818}819 820TEST(MatcherCXXMemberCallExpr, OnImplicitObjectArgument) {821 StringRef Snippet1 = R"cc(822 struct Y {823 void m();824 };825 void z(Y y) { y.m(); }826 )cc";827 StringRef Snippet2 = R"cc(828 struct Y {829 void m();830 };831 struct X : public Y {};832 void z(X x) { x.m(); }833 )cc";834 auto MatchesY = traverse(TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(835 hasType(cxxRecordDecl(hasName("Y"))))));836 EXPECT_TRUE(matches(Snippet1, MatchesY));837 EXPECT_TRUE(matches(Snippet2, MatchesY));838 839 auto MatchesX = traverse(TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(840 hasType(cxxRecordDecl(hasName("X"))))));841 EXPECT_TRUE(notMatches(Snippet2, MatchesX));842 843 // Parens are not ignored.844 StringRef Snippet3 = R"cc(845 struct Y {846 void m();847 };848 Y g();849 void z(Y y) { (g()).m(); }850 )cc";851 auto MatchesCall = traverse(852 TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(callExpr())));853 EXPECT_TRUE(notMatches(Snippet3, MatchesCall));854}855 856TEST(Matcher, HasObjectExpr) {857 StringRef Snippet1 = R"cc(858 struct X {859 int m;860 int f(X x) { return x.m; }861 };862 )cc";863 StringRef Snippet2 = R"cc(864 struct X {865 int m;866 int f(X x) { return m; }867 };868 )cc";869 auto MatchesX =870 memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))));871 EXPECT_TRUE(matches(Snippet1, MatchesX));872 EXPECT_TRUE(notMatches(Snippet2, MatchesX));873 874 auto MatchesXPointer = memberExpr(875 hasObjectExpression(hasType(pointsTo(cxxRecordDecl(hasName("X"))))));876 EXPECT_TRUE(notMatches(Snippet1, MatchesXPointer));877 EXPECT_TRUE(matches(Snippet2, MatchesXPointer));878}879 880TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) {881 StatementMatcher ArgumentY =882 declRefExpr(to(varDecl(hasName("y")))).bind("arg");883 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");884 StatementMatcher CallExpr =885 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));886 887 // IntParam does not match.888 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));889 // ArgumentY does not match.890 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));891}892 893TEST(ForEachArgumentWithParam, MatchesCXXMemberCallExpr) {894 StatementMatcher ArgumentY =895 declRefExpr(to(varDecl(hasName("y")))).bind("arg");896 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");897 StatementMatcher CallExpr =898 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));899 EXPECT_TRUE(matchAndVerifyResultTrue(900 "struct S {"901 " const S& operator[](int i) { return *this; }"902 "};"903 "void f(S S1) {"904 " int y = 1;"905 " S1[y];"906 "}",907 CallExpr, std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 1)));908 909 StatementMatcher CallExpr2 =910 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));911 EXPECT_TRUE(matchAndVerifyResultTrue(912 "struct S {"913 " static void g(int i);"914 "};"915 "void f() {"916 " int y = 1;"917 " S::g(y);"918 "}",919 CallExpr2, std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 1)));920}921 922TEST(ForEachArgumentWithParam, MatchesCallExpr) {923 StatementMatcher ArgumentY =924 declRefExpr(to(varDecl(hasName("y")))).bind("arg");925 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");926 StatementMatcher CallExpr =927 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));928 929 EXPECT_TRUE(930 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,931 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>(932 "param")));933 EXPECT_TRUE(934 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,935 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>(936 "arg")));937 938 EXPECT_TRUE(matchAndVerifyResultTrue(939 "void f(int i, int j) { int y; f(y, y); }", CallExpr,940 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 2)));941 EXPECT_TRUE(matchAndVerifyResultTrue(942 "void f(int i, int j) { int y; f(y, y); }", CallExpr,943 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));944}945 946TEST(ForEachArgumentWithParam, MatchesConstructExpr) {947 StatementMatcher ArgumentY =948 declRefExpr(to(varDecl(hasName("y")))).bind("arg");949 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");950 StatementMatcher ConstructExpr = traverse(951 TK_AsIs, cxxConstructExpr(forEachArgumentWithParam(ArgumentY, IntParam)));952 953 EXPECT_TRUE(matchAndVerifyResultTrue(954 "struct C {"955 " C(int i) {}"956 "};"957 "int y = 0;"958 "C Obj(y);",959 ConstructExpr,960 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param")));961}962 963TEST(ForEachArgumentWithParam, HandlesBoundNodesForNonMatches) {964 EXPECT_TRUE(matchAndVerifyResultTrue(965 "void g(int i, int j) {"966 " int a;"967 " int b;"968 " int c;"969 " g(a, 0);"970 " g(a, b);"971 " g(0, b);"972 "}",973 functionDecl(974 forEachDescendant(varDecl().bind("v")),975 forEachDescendant(callExpr(forEachArgumentWithParam(976 declRefExpr(to(decl(equalsBoundNode("v")))), parmVarDecl())))),977 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));978}979 980TEST_P(ASTMatchersTest,981 ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls) {982 if (!GetParam().isCXX23OrLater()) {983 return;984 }985 986 auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");987 auto SelfParam = parmVarDecl().bind("param");988 StatementMatcher CallExpr =989 callExpr(forEachArgumentWithParam(DeclRef, SelfParam));990 991 StringRef S = R"cpp(992 struct A {993 int operator()(this const A &self);994 };995 A obj;996 int global = obj();997 )cpp";998 999 auto Args = GetParam().getCommandLineArgs();1000 auto Filename = getFilenameForTesting(GetParam().Language);1001 1002 EXPECT_TRUE(matchAndVerifyResultTrue(1003 S, CallExpr,1004 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", "self"), Args,1005 Filename));1006 EXPECT_TRUE(matchAndVerifyResultTrue(1007 S, CallExpr,1008 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args,1009 Filename));1010}1011 1012TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) {1013 StatementMatcher ArgumentY =1014 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1015 TypeMatcher IntType = qualType(isInteger()).bind("type");1016 StatementMatcher CallExpr =1017 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1018 1019 // IntParam does not match.1020 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));1021 // ArgumentY does not match.1022 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));1023}1024 1025TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) {1026 StatementMatcher ArgumentY =1027 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1028 TypeMatcher IntType = qualType(isInteger()).bind("type");1029 StatementMatcher CallExpr =1030 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1031 EXPECT_TRUE(matchAndVerifyResultTrue(1032 "struct S {"1033 " const S& operator[](int i) { return *this; }"1034 "};"1035 "void f(S S1) {"1036 " int y = 1;"1037 " S1[y];"1038 "}",1039 CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));1040 1041 StatementMatcher CallExpr2 =1042 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1043 EXPECT_TRUE(matchAndVerifyResultTrue(1044 "struct S {"1045 " static void g(int i);"1046 "};"1047 "void f() {"1048 " int y = 1;"1049 " S::g(y);"1050 "}",1051 CallExpr2, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));1052}1053 1054TEST(ForEachArgumentWithParamType, MatchesCallExpr) {1055 StatementMatcher ArgumentY =1056 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1057 TypeMatcher IntType = qualType(isInteger()).bind("type");1058 StatementMatcher CallExpr =1059 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1060 1061 EXPECT_TRUE(matchAndVerifyResultTrue(1062 "void f(int i) { int y; f(y); }", CallExpr,1063 std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1064 EXPECT_TRUE(matchAndVerifyResultTrue(1065 "void f(int i) { int y; f(y); }", CallExpr,1066 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1067 1068 EXPECT_TRUE(matchAndVerifyResultTrue(1069 "void f(int i, int j) { int y; f(y, y); }", CallExpr,1070 std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 2)));1071 EXPECT_TRUE(matchAndVerifyResultTrue(1072 "void f(int i, int j) { int y; f(y, y); }", CallExpr,1073 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));1074}1075 1076TEST(ForEachArgumentWithParamType, MatchesConstructExpr) {1077 StatementMatcher ArgumentY =1078 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1079 TypeMatcher IntType = qualType(isInteger()).bind("type");1080 StatementMatcher ConstructExpr =1081 cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType));1082 1083 EXPECT_TRUE(matchAndVerifyResultTrue(1084 "struct C {"1085 " C(int i) {}"1086 "};"1087 "int y = 0;"1088 "C Obj(y);",1089 ConstructExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1090 EXPECT_TRUE(matchAndVerifyResultTrue(1091 "struct C {"1092 " C(int i) {}"1093 "};"1094 "int y = 0;"1095 "C Obj(y);",1096 ConstructExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1097}1098 1099TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) {1100 StatementMatcher ArgumentY =1101 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1102 TypeMatcher IntType = qualType(isInteger()).bind("type");1103 StatementMatcher CallExpr =1104 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1105 1106 EXPECT_TRUE(matchesC("void f();\n"1107 "void call_it(void) { int x, y; f(x, y); }\n"1108 "void f(a, b) int a, b; {}\n"1109 "void call_it2(void) { int x, y; f(x, y); }",1110 CallExpr));1111}1112 1113TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) {1114 EXPECT_TRUE(matchAndVerifyResultTrue(1115 "void g(int i, int j) {"1116 " int a;"1117 " int b;"1118 " int c;"1119 " g(a, 0);"1120 " g(a, b);"1121 " g(0, b);"1122 "}",1123 functionDecl(1124 forEachDescendant(varDecl().bind("v")),1125 forEachDescendant(callExpr(forEachArgumentWithParamType(1126 declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),1127 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));1128}1129 1130TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) {1131 StatementMatcher ArgumentY =1132 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1133 TypeMatcher IntType = qualType(builtinType()).bind("type");1134 StatementMatcher CallExpr =1135 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1136 1137 EXPECT_TRUE(matchAndVerifyResultTrue(1138 "void f(int i) {"1139 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",1140 CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1141 EXPECT_TRUE(matchAndVerifyResultTrue(1142 "void f(int i) {"1143 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",1144 CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1145}1146 1147TEST(ForEachArgumentWithParamType, MatchesMemberFunctionPtrCalls) {1148 StatementMatcher ArgumentY =1149 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1150 TypeMatcher IntType = qualType(builtinType()).bind("type");1151 StatementMatcher CallExpr =1152 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1153 1154 StringRef S = "struct A {\n"1155 " int f(int i) { return i + 1; }\n"1156 " int (A::*x)(int);\n"1157 "};\n"1158 "void f() {\n"1159 " int y = 42;\n"1160 " A a;\n"1161 " a.x = &A::f;\n"1162 " (a.*(a.x))(y);\n"1163 "}";1164 EXPECT_TRUE(matchAndVerifyResultTrue(1165 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1166 EXPECT_TRUE(matchAndVerifyResultTrue(1167 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1168}1169 1170TEST(ForEachArgumentWithParamType, MatchesVariadicFunctionPtrCalls) {1171 StatementMatcher ArgumentY =1172 declRefExpr(to(varDecl(hasName("y")))).bind("arg");1173 TypeMatcher IntType = qualType(builtinType()).bind("type");1174 StatementMatcher CallExpr =1175 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));1176 1177 StringRef S = R"cpp(1178 void fcntl(int fd, int cmd, ...) {}1179 1180 template <typename Func>1181 void f(Func F) {1182 int y = 42;1183 F(y, 1, 3);1184 }1185 1186 void g() { f(fcntl); }1187 )cpp";1188 1189 EXPECT_TRUE(matchAndVerifyResultTrue(1190 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));1191 EXPECT_TRUE(matchAndVerifyResultTrue(1192 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));1193}1194 1195TEST_P(ASTMatchersTest,1196 ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls) {1197 if (!GetParam().isCXX23OrLater()) {1198 return;1199 }1200 1201 auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");1202 auto SelfTy = qualType(asString("const A &")).bind("selfType");1203 StatementMatcher CallExpr =1204 callExpr(forEachArgumentWithParamType(DeclRef, SelfTy));1205 1206 StringRef S = R"cpp(1207 struct A {1208 int operator()(this const A &self);1209 };1210 A obj;1211 int global = obj();1212 )cpp";1213 1214 auto Args = GetParam().getCommandLineArgs();1215 auto Filename = getFilenameForTesting(GetParam().Language);1216 1217 EXPECT_TRUE(matchAndVerifyResultTrue(1218 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("selfType"),1219 Args, Filename));1220 EXPECT_TRUE(matchAndVerifyResultTrue(1221 S, CallExpr,1222 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args,1223 Filename));1224}1225 1226TEST(QualType, hasCanonicalType) {1227 EXPECT_TRUE(notMatches("typedef int &int_ref;"1228 "int a;"1229 "int_ref b = a;",1230 varDecl(hasType(qualType(referenceType())))));1231 EXPECT_TRUE(1232 matches("typedef int &int_ref;"1233 "int a;"1234 "int_ref b = a;",1235 varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));1236}1237 1238TEST(HasParameter, CallsInnerMatcher) {1239 EXPECT_TRUE(matches("class X { void x(int) {} };",1240 cxxMethodDecl(hasParameter(0, varDecl()))));1241 EXPECT_TRUE(notMatches("class X { void x(int) {} };",1242 cxxMethodDecl(hasParameter(0, hasName("x")))));1243 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",1244 objcMethodDecl(hasParameter(0, hasName("x")))));1245 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",1246 blockDecl(hasParameter(0, hasName("p")))));1247}1248 1249TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {1250 EXPECT_TRUE(notMatches("class X { void x(int) {} };",1251 cxxMethodDecl(hasParameter(42, varDecl()))));1252}1253 1254TEST(HasType, MatchesParameterVariableTypesStrictly) {1255 EXPECT_TRUE(matches(1256 "class X { void x(X x) {} };",1257 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));1258 EXPECT_TRUE(notMatches(1259 "class X { void x(const X &x) {} };",1260 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));1261 EXPECT_TRUE(matches("class X { void x(const X *x) {} };",1262 cxxMethodDecl(hasParameter(1263 0, hasType(pointsTo(recordDecl(hasName("X"))))))));1264 EXPECT_TRUE(matches("class X { void x(const X &x) {} };",1265 cxxMethodDecl(hasParameter(1266 0, hasType(references(recordDecl(hasName("X"))))))));1267}1268 1269TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {1270 EXPECT_TRUE(matches(1271 "class Y {}; class X { void x(X x, Y y) {} };",1272 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));1273 EXPECT_TRUE(matches(1274 "class Y {}; class X { void x(Y y, X x) {} };",1275 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));1276 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",1277 objcMethodDecl(hasAnyParameter(hasName("x")))));1278 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",1279 blockDecl(hasAnyParameter(hasName("p")))));1280}1281 1282TEST(Returns, MatchesReturnTypes) {1283 EXPECT_TRUE(matches("class Y { int f() { return 1; } };",1284 functionDecl(returns(asString("int")))));1285 EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",1286 functionDecl(returns(asString("float")))));1287 EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",1288 functionDecl(returns(hasDeclaration(1289 recordDecl(hasName("Y")))))));1290}1291 1292TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {1293 EXPECT_TRUE(notMatches(1294 "class Y {}; class X { void x(int) {} };",1295 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));1296}1297 1298TEST(HasAnyParameter, DoesNotMatchThisPointer) {1299 EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",1300 cxxMethodDecl(hasAnyParameter(1301 hasType(pointsTo(recordDecl(hasName("X"))))))));1302}1303 1304TEST(HasName, MatchesParameterVariableDeclarations) {1305 EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",1306 cxxMethodDecl(hasAnyParameter(hasName("x")))));1307 EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",1308 cxxMethodDecl(hasAnyParameter(hasName("x")))));1309}1310 1311TEST(Matcher, MatchesTypeTemplateArgument) {1312 EXPECT_TRUE(matches(1313 "template<typename T> struct B {};"1314 "B<int> b;",1315 classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(1316 asString("int"))))));1317}1318 1319TEST(Matcher, MatchesTemplateTemplateArgument) {1320 EXPECT_TRUE(matches("template<template <typename> class S> class X {};"1321 "template<typename T> class Y {};"1322 "X<Y> xi;",1323 classTemplateSpecializationDecl(hasAnyTemplateArgument(1324 refersToTemplate(templateName())))));1325}1326 1327TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {1328 EXPECT_TRUE(matches(1329 "struct B { int next; };"1330 "template<int(B::*next_ptr)> struct A {};"1331 "A<&B::next> a;",1332 classTemplateSpecializationDecl(hasAnyTemplateArgument(1333 refersToDeclaration(fieldDecl(hasName("next")))))));1334 1335 EXPECT_TRUE(notMatches(1336 "template <typename T> struct A {};"1337 "A<int> a;",1338 classTemplateSpecializationDecl(hasAnyTemplateArgument(1339 refersToDeclaration(decl())))));1340 1341 EXPECT_TRUE(matches(1342 "struct B { int next; };"1343 "template<int(B::*next_ptr)> struct A {};"1344 "A<&B::next> a;",1345 templateSpecializationType(hasAnyTemplateArgument(isExpr(1346 hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));1347 1348 EXPECT_TRUE(notMatches(1349 "template <typename T> struct A {};"1350 "A<int> a;",1351 templateSpecializationType(hasAnyTemplateArgument(1352 refersToDeclaration(decl())))));1353}1354 1355 1356TEST(Matcher, MatchesSpecificArgument) {1357 EXPECT_TRUE(matches(1358 "template<typename T, typename U> class A {};"1359 "A<bool, int> a;",1360 classTemplateSpecializationDecl(hasTemplateArgument(1361 1, refersToType(asString("int"))))));1362 EXPECT_TRUE(notMatches(1363 "template<typename T, typename U> class A {};"1364 "A<int, bool> a;",1365 classTemplateSpecializationDecl(hasTemplateArgument(1366 1, refersToType(asString("int"))))));1367 1368 EXPECT_TRUE(matches(1369 "template<typename T, typename U> class A {};"1370 "A<bool, int> a;",1371 templateSpecializationType(hasTemplateArgument(1372 1, refersToType(asString("int"))))));1373 EXPECT_TRUE(notMatches(1374 "template<typename T, typename U> class A {};"1375 "A<int, bool> a;",1376 templateSpecializationType(hasTemplateArgument(1377 1, refersToType(asString("int"))))));1378 1379 EXPECT_TRUE(matches(1380 "template<typename T> void f() {};"1381 "void func() { f<int>(); }",1382 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));1383 EXPECT_TRUE(notMatches(1384 "template<typename T> void f() {};",1385 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));1386}1387 1388TEST(TemplateArgument, Matches) {1389 EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",1390 classTemplateSpecializationDecl(1391 hasAnyTemplateArgument(templateArgument()))));1392 EXPECT_TRUE(matches(1393 "template<typename T> struct C {}; C<int> c;",1394 templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));1395 1396 EXPECT_TRUE(matches(1397 "template<typename T> void f() {};"1398 "void func() { f<int>(); }",1399 functionDecl(hasAnyTemplateArgument(templateArgument()))));1400}1401 1402TEST(TemplateTypeParmDecl, CXXMethodDecl) {1403 const char input[] =1404 "template<typename T>\n"1405 "class Class {\n"1406 " void method();\n"1407 "};\n"1408 "template<typename U>\n"1409 "void Class<U>::method() {}\n";1410 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1411 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1412}1413 1414TEST(TemplateTypeParmDecl, VarDecl) {1415 const char input[] =1416 "template<typename T>\n"1417 "class Class {\n"1418 " static T pi;\n"1419 "};\n"1420 "template<typename U>\n"1421 "U Class<U>::pi = U(3.1415926535897932385);\n";1422 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1423 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1424}1425 1426TEST(TemplateTypeParmDecl, VarTemplatePartialSpecializationDecl) {1427 const char input[] =1428 "template<typename T>\n"1429 "struct Struct {\n"1430 " template<typename T2> static int field;\n"1431 "};\n"1432 "template<typename U>\n"1433 "template<typename U2>\n"1434 "int Struct<U>::field<U2*> = 123;\n";1435 EXPECT_TRUE(1436 matches(input, templateTypeParmDecl(hasName("T")), langCxx14OrLater()));1437 EXPECT_TRUE(1438 matches(input, templateTypeParmDecl(hasName("T2")), langCxx14OrLater()));1439 EXPECT_TRUE(1440 matches(input, templateTypeParmDecl(hasName("U")), langCxx14OrLater()));1441 EXPECT_TRUE(1442 matches(input, templateTypeParmDecl(hasName("U2")), langCxx14OrLater()));1443}1444 1445TEST(TemplateTypeParmDecl, ClassTemplatePartialSpecializationDecl) {1446 const char input[] =1447 "template<typename T>\n"1448 "class Class {\n"1449 " template<typename T2> struct Struct;\n"1450 "};\n"1451 "template<typename U>\n"1452 "template<typename U2>\n"1453 "struct Class<U>::Struct<U2*> {};\n";1454 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1455 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));1456 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1457 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));1458}1459 1460TEST(TemplateTypeParmDecl, EnumDecl) {1461 const char input[] =1462 "template<typename T>\n"1463 "struct Struct {\n"1464 " enum class Enum : T;\n"1465 "};\n"1466 "template<typename U>\n"1467 "enum class Struct<U>::Enum : U {\n"1468 " e1,\n"1469 " e2\n"1470 "};\n";1471 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1472 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1473}1474 1475TEST(TemplateTypeParmDecl, RecordDecl) {1476 const char input[] =1477 "template<typename T>\n"1478 "class Class {\n"1479 " struct Struct;\n"1480 "};\n"1481 "template<typename U>\n"1482 "struct Class<U>::Struct {\n"1483 " U field;\n"1484 "};\n";1485 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));1486 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));1487}1488 1489TEST(RefersToIntegralType, Matches) {1490 EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",1491 classTemplateSpecializationDecl(1492 hasAnyTemplateArgument(refersToIntegralType(1493 asString("int"))))));1494 EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",1495 classTemplateSpecializationDecl(hasAnyTemplateArgument(1496 refersToIntegralType(asString("int"))))));1497}1498 1499TEST(ConstructorDeclaration, SimpleCase) {1500 EXPECT_TRUE(matches("class Foo { Foo(int i); };",1501 cxxConstructorDecl(ofClass(hasName("Foo")))));1502 EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",1503 cxxConstructorDecl(ofClass(hasName("Bar")))));1504}1505 1506TEST(DestructorDeclaration, MatchesVirtualDestructor) {1507 EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",1508 cxxDestructorDecl(ofClass(hasName("Foo")))));1509}1510 1511TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {1512 EXPECT_TRUE(notMatches("class Foo {};",1513 cxxDestructorDecl(ofClass(hasName("Foo")))));1514}1515 1516TEST(HasAnyConstructorInitializer, SimpleCase) {1517 EXPECT_TRUE(1518 notMatches("class Foo { Foo() { } };",1519 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));1520 EXPECT_TRUE(1521 matches("class Foo {"1522 " Foo() : foo_() { }"1523 " int foo_;"1524 "};",1525 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));1526}1527 1528TEST(HasAnyConstructorInitializer, ForField) {1529 static const char Code[] =1530 "class Baz { };"1531 "class Foo {"1532 " Foo() : foo_(), bar_() { }"1533 " Baz foo_;"1534 " struct {"1535 " Baz bar_;"1536 " };"1537 "};";1538 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1539 forField(hasType(recordDecl(hasName("Baz"))))))));1540 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1541 forField(hasName("foo_"))))));1542 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1543 forField(hasName("bar_"))))));1544 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1545 forField(hasType(recordDecl(hasName("Bar"))))))));1546}1547 1548TEST(HasAnyConstructorInitializer, WithInitializer) {1549 static const char Code[] =1550 "class Foo {"1551 " Foo() : foo_(0) { }"1552 " int foo_;"1553 "};";1554 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1555 withInitializer(integerLiteral(equals(0)))))));1556 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1557 withInitializer(integerLiteral(equals(1)))))));1558}1559 1560TEST(HasAnyConstructorInitializer, IsWritten) {1561 static const char Code[] =1562 "struct Bar { Bar(){} };"1563 "class Foo {"1564 " Foo() : foo_() { }"1565 " Bar foo_;"1566 " Bar bar_;"1567 "};";1568 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1569 allOf(forField(hasName("foo_")), isWritten())))));1570 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1571 allOf(forField(hasName("bar_")), isWritten())))));1572 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(1573 allOf(forField(hasName("bar_")), unless(isWritten()))))));1574}1575 1576TEST(HasAnyConstructorInitializer, IsBaseInitializer) {1577 static const char Code[] =1578 "struct B {};"1579 "struct D : B {"1580 " int I;"1581 " D(int i) : I(i) {}"1582 "};"1583 "struct E : B {"1584 " E() : B() {}"1585 "};";1586 EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(1587 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),1588 hasName("E")))));1589 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(1590 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),1591 hasName("D")))));1592 EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(1593 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),1594 hasName("D")))));1595 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(1596 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),1597 hasName("E")))));1598}1599 1600TEST(IfStmt, ChildTraversalMatchers) {1601 EXPECT_TRUE(matches("void f() { if (false) true; else false; }",1602 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));1603 EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",1604 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));1605 EXPECT_TRUE(matches("void f() { if (false) false; else true; }",1606 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));1607 EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",1608 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));1609}1610 1611TEST(MatchBinaryOperator, HasOperatorName) {1612 StatementMatcher OperatorOr = binaryOperator(hasOperatorName("||"));1613 1614 EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr));1615 EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr));1616}1617 1618TEST(MatchBinaryOperator, HasAnyOperatorName) {1619 StatementMatcher Matcher =1620 binaryOperator(hasAnyOperatorName("+", "-", "*", "/"));1621 1622 EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher));1623 EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher));1624 EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher));1625 EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher));1626 EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher));1627 // Ensure '+= isn't mistaken.1628 EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher));1629}1630 1631TEST(MatchBinaryOperator, HasLHSAndHasRHS) {1632 StatementMatcher OperatorTrueFalse =1633 binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),1634 hasRHS(cxxBoolLiteral(equals(false))));1635 1636 EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));1637 EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));1638 EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse));1639 1640 StatementMatcher OperatorIntPointer = arraySubscriptExpr(1641 hasLHS(hasType(isInteger())),1642 traverse(TK_AsIs, hasRHS(hasType(pointsTo(qualType())))));1643 EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer));1644 EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer));1645 1646 StringRef Code = R"cpp(1647struct HasOpEqMem1648{1649 bool operator==(const HasOpEqMem& other) const1650 {1651 return true;1652 }1653};1654 1655struct HasOpFree1656{1657};1658bool operator==(const HasOpFree& lhs, const HasOpFree& rhs)1659{1660 return true;1661}1662 1663void opMem()1664{1665 HasOpEqMem s1;1666 HasOpEqMem s2;1667 if (s1 == s2)1668 return;1669}1670 1671void opFree()1672{1673 HasOpFree s1;1674 HasOpFree s2;1675 if (s1 == s2)1676 return;1677}1678)cpp";1679 auto s1Expr = declRefExpr(to(varDecl(hasName("s1"))));1680 auto s2Expr = declRefExpr(to(varDecl(hasName("s2"))));1681 EXPECT_TRUE(matches(1682 Code,1683 traverse(TK_IgnoreUnlessSpelledInSource,1684 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),1685 hasOperatorName("=="), hasLHS(s1Expr),1686 hasRHS(s2Expr)))));1687 EXPECT_TRUE(matches(1688 Code, traverse(TK_IgnoreUnlessSpelledInSource,1689 cxxOperatorCallExpr(1690 forFunction(functionDecl(hasName("opMem"))),1691 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr)))));1692 EXPECT_TRUE(matches(1693 Code, traverse(TK_IgnoreUnlessSpelledInSource,1694 cxxOperatorCallExpr(1695 forFunction(functionDecl(hasName("opMem"))),1696 hasOperatorName("=="), hasOperands(s1Expr, s2Expr)))));1697 EXPECT_TRUE(matches(1698 Code, traverse(TK_IgnoreUnlessSpelledInSource,1699 cxxOperatorCallExpr(1700 forFunction(functionDecl(hasName("opMem"))),1701 hasOperatorName("=="), hasEitherOperand(s2Expr)))));1702 1703 EXPECT_TRUE(matches(1704 Code,1705 traverse(TK_IgnoreUnlessSpelledInSource,1706 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),1707 hasOperatorName("=="), hasLHS(s1Expr),1708 hasRHS(s2Expr)))));1709 EXPECT_TRUE(matches(1710 Code, traverse(TK_IgnoreUnlessSpelledInSource,1711 cxxOperatorCallExpr(1712 forFunction(functionDecl(hasName("opFree"))),1713 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr)))));1714 EXPECT_TRUE(matches(1715 Code, traverse(TK_IgnoreUnlessSpelledInSource,1716 cxxOperatorCallExpr(1717 forFunction(functionDecl(hasName("opFree"))),1718 hasOperatorName("=="), hasOperands(s1Expr, s2Expr)))));1719 EXPECT_TRUE(matches(1720 Code, traverse(TK_IgnoreUnlessSpelledInSource,1721 cxxOperatorCallExpr(1722 forFunction(functionDecl(hasName("opFree"))),1723 hasOperatorName("=="), hasEitherOperand(s2Expr)))));1724}1725 1726TEST(MatchBinaryOperator, HasEitherOperand) {1727 StatementMatcher HasOperand =1728 binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));1729 1730 EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));1731 EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));1732 EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand));1733}1734 1735TEST(MatchBinaryOperator, HasOperands) {1736 StatementMatcher HasOperands = binaryOperator(1737 hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2))));1738 EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands));1739 EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands));1740 EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands));1741 EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands));1742 EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands));1743 EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands));1744}1745 1746TEST(MatchBinaryOperator, HasOperandsEnsureOrdering) {1747 StatementMatcher HasOperandsWithBindings = binaryOperator(hasOperands(1748 cStyleCastExpr(has(declRefExpr(hasDeclaration(valueDecl().bind("d"))))),1749 declRefExpr(hasDeclaration(valueDecl(equalsBoundNode("d"))))));1750 EXPECT_TRUE(matches(1751 "int a; int b = ((int) a) + a;",1752 traverse(TK_IgnoreUnlessSpelledInSource, HasOperandsWithBindings)));1753 EXPECT_TRUE(matches(1754 "int a; int b = a + ((int) a);",1755 traverse(TK_IgnoreUnlessSpelledInSource, HasOperandsWithBindings)));1756}1757 1758TEST(Matcher, BinaryOperatorTypes) {1759 // Integration test that verifies the AST provides all binary operators in1760 // a way we expect.1761 // FIXME: Operator ','1762 EXPECT_TRUE(1763 matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));1764 EXPECT_TRUE(1765 matches("bool b; bool c = (b = true);",1766 binaryOperator(hasOperatorName("="))));1767 EXPECT_TRUE(1768 matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));1769 EXPECT_TRUE(1770 matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));1771 EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));1772 EXPECT_TRUE(1773 matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));1774 EXPECT_TRUE(1775 matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));1776 EXPECT_TRUE(1777 matches("int i = 1; int j = (i <<= 2);",1778 binaryOperator(hasOperatorName("<<="))));1779 EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));1780 EXPECT_TRUE(1781 matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));1782 EXPECT_TRUE(1783 matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));1784 EXPECT_TRUE(1785 matches("int i = 1; int j = (i >>= 2);",1786 binaryOperator(hasOperatorName(">>="))));1787 EXPECT_TRUE(1788 matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));1789 EXPECT_TRUE(1790 matches("int i = 42; int j = (i ^= 42);",1791 binaryOperator(hasOperatorName("^="))));1792 EXPECT_TRUE(1793 matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));1794 EXPECT_TRUE(1795 matches("int i = 42; int j = (i %= 42);",1796 binaryOperator(hasOperatorName("%="))));1797 EXPECT_TRUE(1798 matches("bool b = 42 &23;", binaryOperator(hasOperatorName("&"))));1799 EXPECT_TRUE(1800 matches("bool b = true && false;",1801 binaryOperator(hasOperatorName("&&"))));1802 EXPECT_TRUE(1803 matches("bool b = true; bool c = (b &= false);",1804 binaryOperator(hasOperatorName("&="))));1805 EXPECT_TRUE(1806 matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));1807 EXPECT_TRUE(1808 matches("bool b = true || false;",1809 binaryOperator(hasOperatorName("||"))));1810 EXPECT_TRUE(1811 matches("bool b = true; bool c = (b |= false);",1812 binaryOperator(hasOperatorName("|="))));1813 EXPECT_TRUE(1814 matches("int i = 42 *23;", binaryOperator(hasOperatorName("*"))));1815 EXPECT_TRUE(1816 matches("int i = 42; int j = (i *= 23);",1817 binaryOperator(hasOperatorName("*="))));1818 EXPECT_TRUE(1819 matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));1820 EXPECT_TRUE(1821 matches("int i = 42; int j = (i /= 23);",1822 binaryOperator(hasOperatorName("/="))));1823 EXPECT_TRUE(1824 matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));1825 EXPECT_TRUE(1826 matches("int i = 42; int j = (i += 23);",1827 binaryOperator(hasOperatorName("+="))));1828 EXPECT_TRUE(1829 matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));1830 EXPECT_TRUE(1831 matches("int i = 42; int j = (i -= 23);",1832 binaryOperator(hasOperatorName("-="))));1833 EXPECT_TRUE(1834 matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",1835 binaryOperator(hasOperatorName("->*"))));1836 EXPECT_TRUE(1837 matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",1838 binaryOperator(hasOperatorName(".*"))));1839 1840 // Member expressions as operators are not supported in matches.1841 EXPECT_TRUE(1842 notMatches("struct A { void x(A *a) { a->x(this); } };",1843 binaryOperator(hasOperatorName("->"))));1844 1845 // Initializer assignments are not represented as operator equals.1846 EXPECT_TRUE(1847 notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));1848 1849 // Array indexing is not represented as operator.1850 EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));1851 1852 // Overloaded operators do not match at all.1853 EXPECT_TRUE(notMatches(1854 "struct A { bool operator&&(const A &a) const { return false; } };"1855 "void x() { A a, b; a && b; }",1856 binaryOperator()));1857}1858 1859TEST(MatchUnaryOperator, HasOperatorName) {1860 StatementMatcher OperatorNot = unaryOperator(hasOperatorName("!"));1861 1862 EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot));1863 EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot));1864}1865 1866TEST(MatchUnaryOperator, HasAnyOperatorName) {1867 StatementMatcher Matcher = unaryOperator(hasAnyOperatorName("-", "*", "++"));1868 1869 EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher));1870 EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher));1871 EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher));1872 EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher));1873 EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher));1874 EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher));1875 EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher));1876}1877 1878TEST(MatchUnaryOperator, HasUnaryOperand) {1879 StatementMatcher OperatorOnFalse =1880 unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));1881 1882 EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));1883 EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));1884 1885 StringRef Code = R"cpp(1886struct HasOpBangMem1887{1888 bool operator!() const1889 {1890 return false;1891 }1892};1893struct HasOpBangFree1894{1895};1896bool operator!(HasOpBangFree const&)1897{1898 return false;1899}1900 1901void opMem()1902{1903 HasOpBangMem s1;1904 if (!s1)1905 return;1906}1907void opFree()1908{1909 HasOpBangFree s1;1910 if (!s1)1911 return;1912}1913)cpp";1914 auto s1Expr = declRefExpr(to(varDecl(hasName("s1"))));1915 EXPECT_TRUE(matches(1916 Code, traverse(TK_IgnoreUnlessSpelledInSource,1917 cxxOperatorCallExpr(1918 forFunction(functionDecl(hasName("opMem"))),1919 hasOperatorName("!"), hasUnaryOperand(s1Expr)))));1920 EXPECT_TRUE(matches(1921 Code,1922 traverse(TK_IgnoreUnlessSpelledInSource,1923 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),1924 hasAnyOperatorName("+", "!"),1925 hasUnaryOperand(s1Expr)))));1926 1927 EXPECT_TRUE(matches(1928 Code, traverse(TK_IgnoreUnlessSpelledInSource,1929 cxxOperatorCallExpr(1930 forFunction(functionDecl(hasName("opFree"))),1931 hasOperatorName("!"), hasUnaryOperand(s1Expr)))));1932 EXPECT_TRUE(matches(1933 Code,1934 traverse(TK_IgnoreUnlessSpelledInSource,1935 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),1936 hasAnyOperatorName("+", "!"),1937 hasUnaryOperand(s1Expr)))));1938 1939 Code = R"cpp(1940struct HasIncOperatorsMem1941{1942 HasIncOperatorsMem& operator++();1943 HasIncOperatorsMem operator++(int);1944};1945struct HasIncOperatorsFree1946{1947};1948HasIncOperatorsFree& operator++(HasIncOperatorsFree&);1949HasIncOperatorsFree operator++(HasIncOperatorsFree&, int);1950 1951void prefixIncOperatorMem()1952{1953 HasIncOperatorsMem s1;1954 ++s1;1955}1956void prefixIncOperatorFree()1957{1958 HasIncOperatorsFree s1;1959 ++s1;1960}1961void postfixIncOperatorMem()1962{1963 HasIncOperatorsMem s1;1964 s1++;1965}1966void postfixIncOperatorFree()1967{1968 HasIncOperatorsFree s1;1969 s1++;1970}1971 1972struct HasOpPlusInt1973{1974 HasOpPlusInt& operator+(int);1975};1976void plusIntOperator()1977{1978 HasOpPlusInt s1;1979 s1+1;1980}1981)cpp";1982 1983 EXPECT_TRUE(matches(1984 Code,1985 traverse(TK_IgnoreUnlessSpelledInSource,1986 cxxOperatorCallExpr(1987 forFunction(functionDecl(hasName("prefixIncOperatorMem"))),1988 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));1989 1990 EXPECT_TRUE(matches(1991 Code,1992 traverse(TK_IgnoreUnlessSpelledInSource,1993 cxxOperatorCallExpr(1994 forFunction(functionDecl(hasName("prefixIncOperatorFree"))),1995 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));1996 1997 EXPECT_TRUE(matches(1998 Code,1999 traverse(TK_IgnoreUnlessSpelledInSource,2000 cxxOperatorCallExpr(2001 forFunction(functionDecl(hasName("postfixIncOperatorMem"))),2002 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));2003 2004 EXPECT_TRUE(matches(2005 Code,2006 traverse(TK_IgnoreUnlessSpelledInSource,2007 cxxOperatorCallExpr(2008 forFunction(functionDecl(hasName("postfixIncOperatorFree"))),2009 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));2010 2011 EXPECT_FALSE(matches(2012 Code, traverse(TK_IgnoreUnlessSpelledInSource,2013 cxxOperatorCallExpr(2014 forFunction(functionDecl(hasName("plusIntOperator"))),2015 hasOperatorName("+"), hasUnaryOperand(expr())))));2016 2017 Code = R"cpp(2018struct S {2019 void foo(int);2020};2021struct HasOpStar2022{2023 int& operator*();2024};2025struct HasOpArrow2026{2027 S* operator->();2028};2029void hasOpStarMem(HasOpStar s)2030{2031 *s;2032}2033void hasOpArrowMem(HasOpArrow a)2034{2035 a->foo(42);2036}2037)cpp";2038 2039 EXPECT_TRUE(2040 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2041 cxxOperatorCallExpr(hasOperatorName("*"),2042 hasUnaryOperand(expr())))));2043 EXPECT_TRUE(matches(2044 Code, traverse(TK_IgnoreUnlessSpelledInSource,2045 cxxOperatorCallExpr(hasOperatorName("->"),2046 hasUnaryOperand(declRefExpr(2047 to(varDecl(hasName("a")))))))));2048}2049 2050TEST(Matcher, UnaryOperatorTypes) {2051 // Integration test that verifies the AST provides all unary operators in2052 // a way we expect.2053 EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));2054 EXPECT_TRUE(2055 matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));2056 EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));2057 EXPECT_TRUE(2058 matches("bool *p; bool b = *p;", unaryOperator(hasOperatorName("*"))));2059 EXPECT_TRUE(2060 matches("int i; int j = +i;", unaryOperator(hasOperatorName("+"))));2061 EXPECT_TRUE(2062 matches("int i; int j = -i;", unaryOperator(hasOperatorName("-"))));2063 EXPECT_TRUE(2064 matches("int i; int j = ++i;", unaryOperator(hasOperatorName("++"))));2065 EXPECT_TRUE(2066 matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));2067 EXPECT_TRUE(2068 matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));2069 EXPECT_TRUE(2070 matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));2071 2072 // We don't match conversion operators.2073 EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));2074 2075 // Function calls are not represented as operator.2076 EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));2077 2078 // Overloaded operators do not match at all.2079 // FIXME: We probably want to add that.2080 EXPECT_TRUE(notMatches(2081 "struct A { bool operator!() const { return false; } };"2082 "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));2083}2084 2085TEST_P(ASTMatchersTest, HasInit) {2086 if (!GetParam().isCXX11OrLater()) {2087 // FIXME: Add a test for `hasInit()` that does not depend on C++.2088 return;2089 }2090 2091 EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));2092 EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));2093 EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));2094}2095 2096TEST_P(ASTMatchersTest, HasFoldInit) {2097 if (!GetParam().isCXX17OrLater()) {2098 return;2099 }2100 2101 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2102 "return (0 + ... + args); }",2103 cxxFoldExpr(hasFoldInit(expr()))));2104 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2105 "return (args + ... + 0); }",2106 cxxFoldExpr(hasFoldInit(expr()))));2107 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2108 "return (... + args); };",2109 cxxFoldExpr(hasFoldInit(expr()))));2110}2111 2112TEST_P(ASTMatchersTest, HasPattern) {2113 if (!GetParam().isCXX17OrLater()) {2114 return;2115 }2116 2117 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2118 "return (0 + ... + args); }",2119 cxxFoldExpr(hasPattern(expr()))));2120 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2121 "return (args + ... + 0); }",2122 cxxFoldExpr(hasPattern(expr()))));2123 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2124 "return (... + args); };",2125 cxxFoldExpr(hasPattern(expr()))));2126}2127 2128TEST_P(ASTMatchersTest, HasLHSAndHasRHS) {2129 if (!GetParam().isCXX17OrLater()) {2130 return;2131 }2132 2133 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2134 "return (0 + ... + args); }",2135 cxxFoldExpr(hasLHS(expr()))));2136 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2137 "return (args + ... + 0); }",2138 cxxFoldExpr(hasLHS(expr()))));2139 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2140 "return (... + args); };",2141 cxxFoldExpr(hasLHS(expr()))));2142 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2143 "return (args + ...); };",2144 cxxFoldExpr(hasLHS(expr()))));2145 2146 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2147 "return (0 + ... + args); }",2148 cxxFoldExpr(hasRHS(expr()))));2149 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2150 "return (args + ... + 0); }",2151 cxxFoldExpr(hasRHS(expr()))));2152 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2153 "return (... + args); };",2154 cxxFoldExpr(hasRHS(expr()))));2155 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2156 "return (args + ...); };",2157 cxxFoldExpr(hasRHS(expr()))));2158}2159 2160TEST_P(ASTMatchersTest, HasEitherOperandAndHasOperands) {2161 if (!GetParam().isCXX17OrLater()) {2162 return;2163 }2164 2165 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2166 "return (0 + ... + args); }",2167 cxxFoldExpr(hasEitherOperand(integerLiteral()))));2168 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2169 "return (args + ... + 0); }",2170 cxxFoldExpr(hasEitherOperand(integerLiteral()))));2171 2172 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2173 "return (0 + ... + args); }",2174 cxxFoldExpr(hasEitherOperand(2175 declRefExpr(to(namedDecl(hasName("args"))))))));2176 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2177 "return (args + ... + 0); }",2178 cxxFoldExpr(hasEitherOperand(2179 declRefExpr(to(namedDecl(hasName("args"))))))));2180 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2181 "return (... + args); };",2182 cxxFoldExpr(hasEitherOperand(2183 declRefExpr(to(namedDecl(hasName("args"))))))));2184 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "2185 "return (args + ...); };",2186 cxxFoldExpr(hasEitherOperand(2187 declRefExpr(to(namedDecl(hasName("args"))))))));2188 2189 EXPECT_TRUE(matches(2190 "template <typename... Args> auto sum(Args... args) { "2191 "return (0 + ... + args); }",2192 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2193 integerLiteral()))));2194 EXPECT_TRUE(matches(2195 "template <typename... Args> auto sum(Args... args) { "2196 "return (args + ... + 0); }",2197 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2198 integerLiteral()))));2199 EXPECT_FALSE(matches(2200 "template <typename... Args> auto sum(Args... args) { "2201 "return (... + args); };",2202 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2203 integerLiteral()))));2204 EXPECT_FALSE(matches(2205 "template <typename... Args> auto sum(Args... args) { "2206 "return (args + ...); };",2207 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),2208 integerLiteral()))));2209}2210 2211TEST_P(ASTMatchersTest, Callee) {2212 if (!GetParam().isCXX17OrLater()) {2213 return;2214 }2215 2216 EXPECT_TRUE(matches(2217 "struct Dummy {}; Dummy operator+(Dummy, Dummy); template "2218 "<typename... Args> auto sum(Args... args) { return (0 + ... + args); }",2219 cxxFoldExpr(callee(expr()))));2220 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "2221 "return (0 + ... + args); }",2222 cxxFoldExpr(callee(expr()))));2223}2224 2225TEST(ArraySubscriptMatchers, ArrayIndex) {2226 EXPECT_TRUE(matches(2227 "int i[2]; void f() { i[1] = 1; }",2228 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));2229 EXPECT_TRUE(matches(2230 "int i[2]; void f() { 1[i] = 1; }",2231 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));2232 EXPECT_TRUE(notMatches(2233 "int i[2]; void f() { i[1] = 1; }",2234 arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));2235}2236 2237TEST(ArraySubscriptMatchers, MatchesArrayBase) {2238 EXPECT_TRUE(2239 matches("int i[2]; void f() { i[1] = 2; }",2240 traverse(TK_AsIs, arraySubscriptExpr(hasBase(implicitCastExpr(2241 hasSourceExpression(declRefExpr())))))));2242}2243 2244TEST(Matcher, OfClass) {2245 StatementMatcher Constructor = cxxConstructExpr(hasDeclaration(cxxMethodDecl(2246 ofClass(hasName("X")))));2247 2248 EXPECT_TRUE(2249 matches("class X { public: X(); }; void x(int) { X x; }", Constructor));2250 EXPECT_TRUE(2251 matches("class X { public: X(); }; void x(int) { X x = X(); }",2252 Constructor));2253 EXPECT_TRUE(2254 notMatches("class Y { public: Y(); }; void x(int) { Y y; }",2255 Constructor));2256}2257 2258TEST(Matcher, VisitsTemplateInstantiations) {2259 EXPECT_TRUE(matches(2260 "class A { public: void x(); };"2261 "template <typename T> class B { public: void y() { T t; t.x(); } };"2262 "void f() { B<A> b; b.y(); }",2263 callExpr(callee(cxxMethodDecl(hasName("x"))))));2264 2265 EXPECT_TRUE(matches(2266 "class A { public: void x(); };"2267 "class C {"2268 " public:"2269 " template <typename T> class B { public: void y() { T t; t.x(); } };"2270 "};"2271 "void f() {"2272 " C::B<A> b; b.y();"2273 "}",2274 recordDecl(hasName("C"), hasDescendant(callExpr(2275 callee(cxxMethodDecl(hasName("x"))))))));2276}2277 2278TEST(Matcher, HasCondition) {2279 StatementMatcher IfStmt =2280 ifStmt(hasCondition(cxxBoolLiteral(equals(true))));2281 EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt));2282 EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt));2283 2284 StatementMatcher ForStmt =2285 forStmt(hasCondition(cxxBoolLiteral(equals(true))));2286 EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt));2287 EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt));2288 2289 StatementMatcher WhileStmt =2290 whileStmt(hasCondition(cxxBoolLiteral(equals(true))));2291 EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt));2292 EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt));2293 2294 StatementMatcher SwitchStmt =2295 switchStmt(hasCondition(integerLiteral(equals(42))));2296 EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt));2297 EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt));2298}2299 2300TEST(For, ForLoopInternals) {2301 EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",2302 forStmt(hasCondition(anything()))));2303 EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",2304 forStmt(hasLoopInit(anything()))));2305}2306 2307TEST(For, ForRangeLoopInternals) {2308 EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",2309 cxxForRangeStmt(hasLoopVariable(anything()))));2310 EXPECT_TRUE(matches(2311 "void f(){ int a[] {1, 2}; for (int i : a); }",2312 cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));2313}2314 2315TEST(For, NegativeForLoopInternals) {2316 EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",2317 forStmt(hasCondition(expr()))));2318 EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",2319 forStmt(hasLoopInit(anything()))));2320}2321 2322TEST(HasBody, FindsBodyOfForWhileDoLoops) {2323 EXPECT_TRUE(matches("void f() { for(;;) {} }",2324 forStmt(hasBody(compoundStmt()))));2325 EXPECT_TRUE(notMatches("void f() { for(;;); }",2326 forStmt(hasBody(compoundStmt()))));2327 EXPECT_TRUE(matches("void f() { while(true) {} }",2328 whileStmt(hasBody(compoundStmt()))));2329 EXPECT_TRUE(matches("void f() { do {} while(true); }",2330 doStmt(hasBody(compoundStmt()))));2331 EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",2332 cxxForRangeStmt(hasBody(compoundStmt()))));2333}2334 2335TEST(HasBody, FindsBodyOfFunctions) {2336 EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));2337 EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));2338 EXPECT_TRUE(matchAndVerifyResultTrue(2339 "void f(); void f() {}",2340 functionDecl(hasBody(compoundStmt())).bind("func"),2341 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 1)));2342 EXPECT_TRUE(matchAndVerifyResultTrue(2343 "class C { void f(); }; void C::f() {}",2344 cxxMethodDecl(hasBody(compoundStmt())).bind("met"),2345 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 1)));2346 EXPECT_TRUE(matchAndVerifyResultTrue(2347 "class C { C(); }; C::C() {}",2348 cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),2349 std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 1)));2350 EXPECT_TRUE(matchAndVerifyResultTrue(2351 "class C { ~C(); }; C::~C() {}",2352 cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),2353 std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 1)));2354}2355 2356TEST(HasAnyBody, FindsAnyBodyOfFunctions) {2357 EXPECT_TRUE(matches("void f() {}", functionDecl(hasAnyBody(compoundStmt()))));2358 EXPECT_TRUE(notMatches("void f();",2359 functionDecl(hasAnyBody(compoundStmt()))));2360 EXPECT_TRUE(matchAndVerifyResultTrue(2361 "void f(); void f() {}",2362 functionDecl(hasAnyBody(compoundStmt())).bind("func"),2363 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 2)));2364 EXPECT_TRUE(matchAndVerifyResultTrue(2365 "class C { void f(); }; void C::f() {}",2366 cxxMethodDecl(hasAnyBody(compoundStmt())).bind("met"),2367 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 2)));2368 EXPECT_TRUE(matchAndVerifyResultTrue(2369 "class C { C(); }; C::C() {}",2370 cxxConstructorDecl(hasAnyBody(compoundStmt())).bind("ctr"),2371 std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 2)));2372 EXPECT_TRUE(matchAndVerifyResultTrue(2373 "class C { ~C(); }; C::~C() {}",2374 cxxDestructorDecl(hasAnyBody(compoundStmt())).bind("dtr"),2375 std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 2)));2376}2377 2378TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {2379 // The simplest case: every compound statement is in a function2380 // definition, and the function body itself must be a compound2381 // statement.2382 EXPECT_TRUE(matches("void f() { for (;;); }",2383 compoundStmt(hasAnySubstatement(forStmt()))));2384}2385 2386TEST(HasAnySubstatement, IsNotRecursive) {2387 // It's really "has any immediate substatement".2388 EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",2389 compoundStmt(hasAnySubstatement(forStmt()))));2390}2391 2392TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {2393 EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",2394 compoundStmt(hasAnySubstatement(forStmt()))));2395}2396 2397TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {2398 EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",2399 compoundStmt(hasAnySubstatement(forStmt()))));2400}2401 2402TEST(Member, MatchesMemberAllocationFunction) {2403 // Fails in C++11 mode2404 EXPECT_TRUE(matchesConditionally(2405 "namespace std { typedef typeof(sizeof(int)) size_t; }"2406 "class X { void *operator new(std::size_t); };",2407 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));2408 2409 EXPECT_TRUE(matches("class X { void operator delete(void*); };",2410 cxxMethodDecl(ofClass(hasName("X")))));2411 2412 // Fails in C++11 mode2413 EXPECT_TRUE(matchesConditionally(2414 "namespace std { typedef typeof(sizeof(int)) size_t; }"2415 "class X { void operator delete[](void*, std::size_t); };",2416 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));2417}2418 2419TEST(HasDestinationType, MatchesSimpleCase) {2420 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",2421 cxxStaticCastExpr(hasDestinationType(2422 pointsTo(TypeMatcher(anything()))))));2423}2424 2425TEST(HasImplicitDestinationType, MatchesSimpleCase) {2426 // This test creates an implicit const cast.2427 EXPECT_TRUE(matches(2428 "int x; const int i = x;",2429 traverse(TK_AsIs,2430 implicitCastExpr(hasImplicitDestinationType(isInteger())))));2431 // This test creates an implicit array-to-pointer cast.2432 EXPECT_TRUE(2433 matches("int arr[3]; int *p = arr;",2434 traverse(TK_AsIs, implicitCastExpr(hasImplicitDestinationType(2435 pointsTo(TypeMatcher(anything())))))));2436}2437 2438TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {2439 // This test creates an implicit cast from int to char.2440 EXPECT_TRUE(notMatches("char c = 0;",2441 implicitCastExpr(hasImplicitDestinationType(2442 unless(anything())))));2443 // This test creates an implicit array-to-pointer cast.2444 EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",2445 implicitCastExpr(hasImplicitDestinationType(2446 unless(anything())))));2447}2448 2449TEST(Matcher, IgnoresElidableConstructors) {2450 EXPECT_TRUE(2451 matches("struct H {};"2452 "template<typename T> H B(T A);"2453 "void f() {"2454 " H D1;"2455 " D1 = B(B(1));"2456 "}",2457 cxxOperatorCallExpr(hasArgument(2458 1, callExpr(hasArgument(2459 0, ignoringElidableConstructorCall(callExpr()))))),2460 langCxx11OrLater()));2461 EXPECT_TRUE(2462 matches("struct H {};"2463 "template<typename T> H B(T A);"2464 "void f() {"2465 " H D1;"2466 " D1 = B(1);"2467 "}",2468 cxxOperatorCallExpr(hasArgument(2469 1, callExpr(hasArgument(0, ignoringElidableConstructorCall(2470 integerLiteral()))))),2471 langCxx11OrLater()));2472 EXPECT_TRUE(matches(2473 "struct H {};"2474 "H G();"2475 "void f() {"2476 " H D = G();"2477 "}",2478 varDecl(hasInitializer(anyOf(2479 ignoringElidableConstructorCall(callExpr()),2480 exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())))))),2481 langCxx11OrLater()));2482}2483 2484TEST(Matcher, IgnoresElidableInReturn) {2485 auto matcher = expr(ignoringElidableConstructorCall(declRefExpr()));2486 EXPECT_TRUE(matches("struct H {};"2487 "H f() {"2488 " H g;"2489 " return g;"2490 "}",2491 matcher, langCxx11OrLater()));2492 EXPECT_TRUE(notMatches("struct H {};"2493 "H f() {"2494 " return H();"2495 "}",2496 matcher, langCxx11OrLater()));2497}2498 2499TEST(Matcher, IgnoreElidableConstructorDoesNotMatchConstructors) {2500 EXPECT_TRUE(matches("struct H {};"2501 "void f() {"2502 " H D;"2503 "}",2504 varDecl(hasInitializer(2505 ignoringElidableConstructorCall(cxxConstructExpr()))),2506 langCxx11OrLater()));2507}2508 2509TEST(Matcher, IgnoresElidableDoesNotPreventMatches) {2510 EXPECT_TRUE(matches("void f() {"2511 " int D = 10;"2512 "}",2513 expr(ignoringElidableConstructorCall(integerLiteral())),2514 langCxx11OrLater()));2515}2516 2517TEST(Matcher, IgnoresElidableInVarInit) {2518 auto matcher =2519 varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())));2520 EXPECT_TRUE(matches("struct H {};"2521 "H G();"2522 "void f(H D = G()) {"2523 " return;"2524 "}",2525 matcher, langCxx11OrLater()));2526 EXPECT_TRUE(matches("struct H {};"2527 "H G();"2528 "void f() {"2529 " H D = G();"2530 "}",2531 matcher, langCxx11OrLater()));2532}2533 2534TEST(IgnoringImplicit, MatchesImplicit) {2535 EXPECT_TRUE(matches("class C {}; C a = C();",2536 varDecl(has(ignoringImplicit(cxxConstructExpr())))));2537}2538 2539TEST(IgnoringImplicit, MatchesNestedImplicit) {2540 StringRef Code = R"(2541 2542struct OtherType;2543 2544struct SomeType2545{2546 SomeType() {}2547 SomeType(const OtherType&) {}2548 SomeType& operator=(OtherType const&) { return *this; }2549};2550 2551struct OtherType2552{2553 OtherType() {}2554 ~OtherType() {}2555};2556 2557OtherType something()2558{2559 return {};2560}2561 2562int main()2563{2564 SomeType i = something();2565}2566)";2567 EXPECT_TRUE(matches(2568 Code,2569 traverse(TK_AsIs,2570 varDecl(hasName("i"),2571 hasInitializer(exprWithCleanups(has(cxxConstructExpr(2572 has(expr(ignoringImplicit(cxxConstructExpr(has(2573 expr(ignoringImplicit(callExpr())))))))))))))));2574}2575 2576TEST(IgnoringImplicit, DoesNotMatchIncorrectly) {2577 EXPECT_TRUE(notMatches("class C {}; C a = C();",2578 traverse(TK_AsIs, varDecl(has(cxxConstructExpr())))));2579}2580 2581TEST(Traversal, traverseMatcher) {2582 2583 StringRef VarDeclCode = R"cpp(2584void foo()2585{2586 int i = 3.0;2587}2588)cpp";2589 2590 auto Matcher = varDecl(hasInitializer(floatLiteral()));2591 2592 EXPECT_TRUE(notMatches(VarDeclCode, traverse(TK_AsIs, Matcher)));2593 EXPECT_TRUE(2594 matches(VarDeclCode, traverse(TK_IgnoreUnlessSpelledInSource, Matcher)));2595 2596 auto ParentMatcher = floatLiteral(hasParent(varDecl(hasName("i"))));2597 2598 EXPECT_TRUE(notMatches(VarDeclCode, traverse(TK_AsIs, ParentMatcher)));2599 EXPECT_TRUE(matches(VarDeclCode,2600 traverse(TK_IgnoreUnlessSpelledInSource, ParentMatcher)));2601 2602 EXPECT_TRUE(matches(2603 VarDeclCode, decl(traverse(TK_AsIs, anyOf(cxxRecordDecl(), varDecl())))));2604 2605 EXPECT_TRUE(2606 matches(VarDeclCode,2607 floatLiteral(traverse(TK_AsIs, hasParent(implicitCastExpr())))));2608 2609 EXPECT_TRUE(2610 matches(VarDeclCode, floatLiteral(traverse(TK_IgnoreUnlessSpelledInSource,2611 hasParent(varDecl())))));2612 2613 EXPECT_TRUE(2614 matches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,2615 unless(parmVarDecl())))));2616 2617 EXPECT_TRUE(2618 notMatches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,2619 has(implicitCastExpr())))));2620 2621 EXPECT_TRUE(matches(VarDeclCode,2622 varDecl(traverse(TK_AsIs, has(implicitCastExpr())))));2623 2624 EXPECT_TRUE(matches(2625 VarDeclCode, traverse(TK_IgnoreUnlessSpelledInSource,2626 // The has() below strips away the ImplicitCastExpr2627 // before the traverse(AsIs) gets to process it.2628 varDecl(has(traverse(TK_AsIs, floatLiteral()))))));2629 2630 EXPECT_TRUE(2631 matches(VarDeclCode, functionDecl(traverse(TK_AsIs, hasName("foo")))));2632 2633 EXPECT_TRUE(matches(2634 VarDeclCode,2635 functionDecl(traverse(TK_IgnoreUnlessSpelledInSource, hasName("foo")))));2636 2637 EXPECT_TRUE(matches(2638 VarDeclCode, functionDecl(traverse(TK_AsIs, hasAnyName("foo", "bar")))));2639 2640 EXPECT_TRUE(2641 matches(VarDeclCode, functionDecl(traverse(TK_IgnoreUnlessSpelledInSource,2642 hasAnyName("foo", "bar")))));2643 2644 StringRef Code = R"cpp(2645void foo(int a)2646{2647 int i = 3.0 + a;2648}2649void bar()2650{2651 foo(7.0);2652}2653)cpp";2654 EXPECT_TRUE(2655 matches(Code, callExpr(traverse(TK_IgnoreUnlessSpelledInSource,2656 hasArgument(0, floatLiteral())))));2657 2658 EXPECT_TRUE(2659 matches(Code, callExpr(traverse(TK_IgnoreUnlessSpelledInSource,2660 hasAnyArgument(floatLiteral())))));2661 2662 EXPECT_TRUE(matches(2663 R"cpp(2664void takesBool(bool){}2665 2666template <typename T>2667void neverInstantiatedTemplate() {2668 takesBool(T{});2669}2670)cpp",2671 traverse(TK_IgnoreUnlessSpelledInSource,2672 callExpr(unless(callExpr(hasDeclaration(functionDecl())))))));2673 2674 EXPECT_TRUE(2675 matches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,2676 hasType(builtinType())))));2677 2678 EXPECT_TRUE(2679 matches(VarDeclCode,2680 functionDecl(hasName("foo"),2681 traverse(TK_AsIs, hasDescendant(floatLiteral())))));2682 2683 EXPECT_TRUE(notMatches(2684 Code, traverse(TK_AsIs, floatLiteral(hasParent(callExpr(2685 callee(functionDecl(hasName("foo")))))))));2686 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2687 floatLiteral(hasParent(callExpr(callee(2688 functionDecl(hasName("foo")))))))));2689 2690 Code = R"cpp(2691void foo()2692{2693 int i = (3);2694}2695)cpp";2696 EXPECT_TRUE(matches(2697 Code, traverse(TK_IgnoreUnlessSpelledInSource,2698 varDecl(hasInitializer(integerLiteral(equals(3)))))));2699 EXPECT_TRUE(matches(2700 Code,2701 traverse(TK_IgnoreUnlessSpelledInSource,2702 integerLiteral(equals(3), hasParent(varDecl(hasName("i")))))));2703 2704 Code = R"cpp(2705const char *SomeString{"str"};2706)cpp";2707 EXPECT_TRUE(2708 matches(Code, traverse(TK_AsIs, stringLiteral(hasParent(implicitCastExpr(2709 hasParent(initListExpr())))))));2710 EXPECT_TRUE(2711 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2712 stringLiteral(hasParent(initListExpr())))));2713 2714 Code = R"cpp(2715struct String2716{2717 String(const char*, int = -1) {}2718};2719 2720void stringConstruct()2721{2722 String s = "foo";2723 s = "bar";2724}2725)cpp";2726 EXPECT_TRUE(matches(2727 Code,2728 traverse(2729 TK_AsIs,2730 functionDecl(2731 hasName("stringConstruct"),2732 hasDescendant(varDecl(2733 hasName("s"),2734 hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(2735 0, ignoringImplicit(cxxConstructExpr(hasArgument(2736 0, ignoringImplicit(stringLiteral()))))))))))))));2737 2738 EXPECT_TRUE(matches(2739 Code,2740 traverse(2741 TK_AsIs,2742 functionDecl(hasName("stringConstruct"),2743 hasDescendant(cxxOperatorCallExpr(2744 isAssignmentOperator(),2745 hasArgument(1, ignoringImplicit(2746 cxxConstructExpr(hasArgument(2747 0, ignoringImplicit(stringLiteral())))))2748 ))))));2749 2750 EXPECT_TRUE(matches(2751 Code, traverse(TK_IgnoreUnlessSpelledInSource,2752 functionDecl(hasName("stringConstruct"),2753 hasDescendant(varDecl(2754 hasName("s"),2755 hasInitializer(stringLiteral())))))));2756 2757 EXPECT_TRUE(2758 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,2759 functionDecl(hasName("stringConstruct"),2760 hasDescendant(cxxOperatorCallExpr(2761 isAssignmentOperator(),2762 hasArgument(1, stringLiteral())))))));2763 2764 Code = R"cpp(2765 2766struct C1 {};2767struct C2 { operator C1(); };2768 2769void conversionOperator()2770{2771 C2* c2;2772 C1 c1 = (*c2);2773}2774 2775)cpp";2776 EXPECT_TRUE(matches(2777 Code,2778 traverse(2779 TK_AsIs,2780 functionDecl(2781 hasName("conversionOperator"),2782 hasDescendant(2783 varDecl(2784 hasName("c1"),2785 hasInitializer(2786 ignoringImplicit(cxxConstructExpr(hasArgument(2787 0, ignoringImplicit(2788 cxxMemberCallExpr(onImplicitObjectArgument(2789 ignoringParenImpCasts(unaryOperator(2790 hasOperatorName("*")))))))))))2791 .bind("c1"))))));2792 2793 EXPECT_TRUE(matches(2794 Code,2795 traverse(TK_IgnoreUnlessSpelledInSource,2796 functionDecl(hasName("conversionOperator"),2797 hasDescendant(varDecl(2798 hasName("c1"), hasInitializer(unaryOperator(2799 hasOperatorName("*")))))))));2800 2801 Code = R"cpp(2802 2803template <unsigned alignment>2804void template_test() {2805 static_assert(alignment, "");2806}2807void actual_template_test() {2808 template_test<4>();2809}2810 2811)cpp";2812 EXPECT_TRUE(matches(2813 Code,2814 traverse(TK_AsIs,2815 staticAssertDecl(has(implicitCastExpr(has(2816 substNonTypeTemplateParmExpr(has(integerLiteral())))))))));2817 EXPECT_TRUE(matches(2818 Code, traverse(TK_IgnoreUnlessSpelledInSource,2819 staticAssertDecl(has(declRefExpr(2820 to(nonTypeTemplateParmDecl(hasName("alignment"))),2821 hasType(asString("unsigned int"))))))));2822 2823 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, staticAssertDecl(hasDescendant(2824 integerLiteral())))));2825 EXPECT_FALSE(matches(2826 Code, traverse(TK_IgnoreUnlessSpelledInSource,2827 staticAssertDecl(hasDescendant(integerLiteral())))));2828 2829 Code = R"cpp(2830 2831struct OneParamCtor {2832 explicit OneParamCtor(int);2833};2834struct TwoParamCtor {2835 explicit TwoParamCtor(int, int);2836};2837 2838void varDeclCtors() {2839 {2840 auto var1 = OneParamCtor(5);2841 auto var2 = TwoParamCtor(6, 7);2842 }2843 {2844 OneParamCtor var3(5);2845 TwoParamCtor var4(6, 7);2846 }2847 int i = 0;2848 {2849 auto var5 = OneParamCtor(i);2850 auto var6 = TwoParamCtor(i, 7);2851 }2852 {2853 OneParamCtor var7(i);2854 TwoParamCtor var8(i, 7);2855 }2856}2857 2858)cpp";2859 EXPECT_TRUE(matches(2860 Code,2861 traverse(TK_AsIs, varDecl(hasName("var1"), hasInitializer(hasDescendant(2862 cxxConstructExpr()))))));2863 EXPECT_TRUE(matches(2864 Code,2865 traverse(TK_AsIs, varDecl(hasName("var2"), hasInitializer(hasDescendant(2866 cxxConstructExpr()))))));2867 EXPECT_TRUE(matches(2868 Code, traverse(TK_AsIs, varDecl(hasName("var3"),2869 hasInitializer(cxxConstructExpr())))));2870 EXPECT_TRUE(matches(2871 Code, traverse(TK_AsIs, varDecl(hasName("var4"),2872 hasInitializer(cxxConstructExpr())))));2873 EXPECT_TRUE(matches(2874 Code,2875 traverse(TK_AsIs, varDecl(hasName("var5"), hasInitializer(hasDescendant(2876 cxxConstructExpr()))))));2877 EXPECT_TRUE(matches(2878 Code,2879 traverse(TK_AsIs, varDecl(hasName("var6"), hasInitializer(hasDescendant(2880 cxxConstructExpr()))))));2881 EXPECT_TRUE(matches(2882 Code, traverse(TK_AsIs, varDecl(hasName("var7"),2883 hasInitializer(cxxConstructExpr())))));2884 EXPECT_TRUE(matches(2885 Code, traverse(TK_AsIs, varDecl(hasName("var8"),2886 hasInitializer(cxxConstructExpr())))));2887 2888 EXPECT_TRUE(matches(2889 Code,2890 traverse(TK_IgnoreUnlessSpelledInSource,2891 varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));2892 EXPECT_TRUE(matches(2893 Code,2894 traverse(TK_IgnoreUnlessSpelledInSource,2895 varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));2896 EXPECT_TRUE(matches(2897 Code,2898 traverse(TK_IgnoreUnlessSpelledInSource,2899 varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));2900 EXPECT_TRUE(matches(2901 Code,2902 traverse(TK_IgnoreUnlessSpelledInSource,2903 varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));2904 EXPECT_TRUE(matches(2905 Code,2906 traverse(TK_IgnoreUnlessSpelledInSource,2907 varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));2908 EXPECT_TRUE(matches(2909 Code,2910 traverse(TK_IgnoreUnlessSpelledInSource,2911 varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));2912 EXPECT_TRUE(matches(2913 Code,2914 traverse(TK_IgnoreUnlessSpelledInSource,2915 varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));2916 EXPECT_TRUE(matches(2917 Code,2918 traverse(TK_IgnoreUnlessSpelledInSource,2919 varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));2920 2921 Code = R"cpp(2922 2923template<typename T>2924struct TemplStruct {2925 TemplStruct() {}2926 ~TemplStruct() {}2927 2928 void outOfLine(T);2929 2930private:2931 T m_t;2932};2933 2934template<typename T>2935void TemplStruct<T>::outOfLine(T)2936{2937 2938}2939 2940template<typename T>2941T timesTwo(T input)2942{2943 return input * 2;2944}2945 2946void instantiate()2947{2948 TemplStruct<int> ti;2949 TemplStruct<double> td;2950 (void)timesTwo<int>(2);2951 (void)timesTwo<double>(2);2952}2953 2954template class TemplStruct<float>;2955 2956extern template class TemplStruct<long>;2957 2958template<> class TemplStruct<bool> {2959 TemplStruct() {}2960 ~TemplStruct() {}2961 2962 void boolSpecializationMethodOnly() {}2963private:2964 bool m_t;2965};2966 2967template float timesTwo(float);2968template<> bool timesTwo<bool>(bool){2969 return true;2970}2971)cpp";2972 {2973 auto M = cxxRecordDecl(hasName("TemplStruct"),2974 has(fieldDecl(hasType(asString("int")))));2975 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2976 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2977 }2978 {2979 auto M = cxxRecordDecl(hasName("TemplStruct"),2980 has(fieldDecl(hasType(asString("double")))));2981 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2982 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2983 }2984 {2985 auto M =2986 functionDecl(hasName("timesTwo"),2987 hasParameter(0, parmVarDecl(hasType(asString("int")))));2988 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2989 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2990 }2991 {2992 auto M =2993 functionDecl(hasName("timesTwo"),2994 hasParameter(0, parmVarDecl(hasType(asString("double")))));2995 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));2996 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));2997 }2998 {2999 // Match on the integer literal in the explicit instantiation:3000 auto MDef =3001 functionDecl(hasName("timesTwo"),3002 hasParameter(0, parmVarDecl(hasType(asString("float")))),3003 hasDescendant(integerLiteral(equals(2))));3004 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));3005 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));3006 3007 auto MTempl =3008 functionDecl(hasName("timesTwo"),3009 hasTemplateArgument(0, refersToType(asString("float"))));3010 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MTempl)));3011 // TODO: If we could match on explicit instantiations of function templates,3012 // this would be EXPECT_TRUE. See Sema::ActOnExplicitInstantiation.3013 EXPECT_FALSE(3014 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MTempl)));3015 }3016 {3017 auto M = functionDecl(hasName("timesTwo"),3018 hasParameter(0, parmVarDecl(hasType(booleanType()))));3019 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3020 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3021 }3022 {3023 // Match on the field within the explicit instantiation:3024 auto MRecord = cxxRecordDecl(hasName("TemplStruct"),3025 has(fieldDecl(hasType(asString("float")))));3026 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MRecord)));3027 EXPECT_FALSE(3028 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MRecord)));3029 3030 // Match on the explicit template instantiation itself:3031 auto MTempl = classTemplateSpecializationDecl(3032 hasName("TemplStruct"),3033 hasTemplateArgument(0,3034 templateArgument(refersToType(asString("float")))));3035 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MTempl)));3036 EXPECT_TRUE(3037 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MTempl)));3038 }3039 {3040 // The template argument is matchable, but the instantiation is not:3041 auto M = classTemplateSpecializationDecl(3042 hasName("TemplStruct"),3043 hasTemplateArgument(0,3044 templateArgument(refersToType(asString("float")))),3045 has(cxxConstructorDecl(hasName("TemplStruct"))));3046 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3047 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3048 }3049 {3050 // The template argument is matchable, but the instantiation is not:3051 auto M = classTemplateSpecializationDecl(3052 hasName("TemplStruct"),3053 hasTemplateArgument(0,3054 templateArgument(refersToType(asString("long")))),3055 has(cxxConstructorDecl(hasName("TemplStruct"))));3056 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3057 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3058 }3059 {3060 // Instantiated, out-of-line methods are not matchable.3061 auto M =3062 cxxMethodDecl(hasName("outOfLine"), isDefinition(),3063 hasParameter(0, parmVarDecl(hasType(asString("float")))));3064 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3065 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3066 }3067 {3068 // Explicit specialization is written in source and it matches:3069 auto M = classTemplateSpecializationDecl(3070 hasName("TemplStruct"),3071 hasTemplateArgument(0, templateArgument(refersToType(booleanType()))),3072 has(cxxConstructorDecl(hasName("TemplStruct"))),3073 has(cxxMethodDecl(hasName("boolSpecializationMethodOnly"))));3074 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3075 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3076 }3077 3078 Code = R"cpp(3079struct B {3080 B(int);3081};3082 3083B func1() { return 42; }3084 )cpp";3085 {3086 auto M = expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit")));3087 EXPECT_TRUE(matchAndVerifyResultTrue(3088 Code, traverse(TK_AsIs, M),3089 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3090 EXPECT_TRUE(matchAndVerifyResultTrue(3091 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3092 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3093 }3094 {3095 auto M = expr(unless(integerLiteral(equals(24)))).bind("intLit");3096 EXPECT_TRUE(matchAndVerifyResultTrue(3097 Code, traverse(TK_AsIs, M),3098 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 6),3099 {"-std=c++11"}));3100 3101 EXPECT_TRUE(matchAndVerifyResultTrue(3102 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3103 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1),3104 {"-std=c++11"}));3105 }3106 {3107 auto M =3108 expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr())));3109 EXPECT_TRUE(matchAndVerifyResultTrue(3110 Code, traverse(TK_AsIs, M),3111 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3112 EXPECT_TRUE(matchAndVerifyResultTrue(3113 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3114 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3115 }3116 {3117 auto M = expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr()));3118 EXPECT_TRUE(matchAndVerifyResultTrue(3119 Code, traverse(TK_AsIs, M),3120 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3121 EXPECT_TRUE(matchAndVerifyResultTrue(3122 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3123 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3124 }3125 {3126 auto M = expr(integerLiteral(equals(42)).bind("intLit"), expr());3127 EXPECT_TRUE(matchAndVerifyResultTrue(3128 Code, traverse(TK_AsIs, M),3129 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3130 EXPECT_TRUE(matchAndVerifyResultTrue(3131 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3132 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3133 }3134 {3135 auto M = expr(optionally(integerLiteral(equals(42)).bind("intLit")));3136 EXPECT_TRUE(matchAndVerifyResultTrue(3137 Code, traverse(TK_AsIs, M),3138 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3139 EXPECT_TRUE(matchAndVerifyResultTrue(3140 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3141 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));3142 }3143 {3144 auto M = expr().bind("allExprs");3145 EXPECT_TRUE(matchAndVerifyResultTrue(3146 Code, traverse(TK_AsIs, M),3147 std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 6),3148 {"-std=c++11"}));3149 EXPECT_TRUE(matchAndVerifyResultTrue(3150 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3151 std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 1)));3152 }3153 3154 Code = R"cpp(3155void foo()3156{3157 int arr[3];3158 auto &[f, s, t] = arr;3159 3160 f = 42;3161}3162 )cpp";3163 {3164 auto M = bindingDecl(hasName("f"));3165 EXPECT_TRUE(3166 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3167 EXPECT_TRUE(3168 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3169 true, {"-std=c++17"}));3170 }3171 {3172 auto M = bindingDecl(hasName("f"), has(expr()));3173 EXPECT_TRUE(3174 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3175 EXPECT_FALSE(3176 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3177 true, {"-std=c++17"}));3178 }3179 {3180 auto M = integerLiteral(hasAncestor(bindingDecl(hasName("f"))));3181 EXPECT_TRUE(3182 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3183 EXPECT_FALSE(3184 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3185 true, {"-std=c++17"}));3186 }3187 {3188 auto M = declRefExpr(hasAncestor(bindingDecl(hasName("f"))));3189 EXPECT_TRUE(3190 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));3191 EXPECT_FALSE(3192 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3193 true, {"-std=c++17"}));3194 }3195}3196 3197TEST(Traversal, traverseNoImplicit) {3198 StringRef Code = R"cpp(3199struct NonTrivial {3200 NonTrivial() {}3201 NonTrivial(const NonTrivial&) {}3202 NonTrivial& operator=(const NonTrivial&) { return *this; }3203 3204 ~NonTrivial() {}3205};3206 3207struct NoSpecialMethods {3208 NonTrivial nt;3209};3210 3211struct ContainsArray {3212 NonTrivial arr[2];3213 ContainsArray& operator=(const ContainsArray &other) = default;3214};3215 3216void copyIt()3217{3218 NoSpecialMethods nc1;3219 NoSpecialMethods nc2(nc1);3220 nc2 = nc1;3221 3222 ContainsArray ca;3223 ContainsArray ca2;3224 ca2 = ca;3225}3226 3227struct HasCtorInits : NoSpecialMethods, NonTrivial3228{3229 int m_i;3230 NonTrivial m_nt;3231 HasCtorInits() : NoSpecialMethods(), m_i(42) {}3232};3233 3234struct CtorInitsNonTrivial : NonTrivial3235{3236 int m_i;3237 NonTrivial m_nt;3238 CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}3239};3240 3241)cpp";3242 {3243 auto M = cxxRecordDecl(hasName("NoSpecialMethods"),3244 has(cxxRecordDecl(hasName("NoSpecialMethods"))));3245 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3246 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3247 3248 M = cxxRecordDecl(hasName("NoSpecialMethods"),3249 has(cxxConstructorDecl(isCopyConstructor())));3250 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3251 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3252 3253 M = cxxRecordDecl(hasName("NoSpecialMethods"),3254 has(cxxMethodDecl(isCopyAssignmentOperator())));3255 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3256 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3257 3258 M = cxxRecordDecl(hasName("NoSpecialMethods"),3259 has(cxxConstructorDecl(isDefaultConstructor())));3260 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3261 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3262 3263 M = cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));3264 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3265 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3266 3267 M = cxxRecordDecl(hasName("NoSpecialMethods"),3268 hasMethod(cxxConstructorDecl(isCopyConstructor())));3269 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3270 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3271 3272 M = cxxRecordDecl(hasName("NoSpecialMethods"),3273 hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));3274 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3275 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3276 3277 M = cxxRecordDecl(hasName("NoSpecialMethods"),3278 hasMethod(cxxConstructorDecl(isDefaultConstructor())));3279 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3280 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3281 3282 M = cxxRecordDecl(hasName("NoSpecialMethods"),3283 hasMethod(cxxDestructorDecl()));3284 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3285 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3286 }3287 {3288 // Because the copy-assignment operator is not spelled in the3289 // source (ie, isImplicit()), we don't match it3290 auto M =3291 cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),3292 callee(cxxMethodDecl(isCopyAssignmentOperator())));3293 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3294 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3295 }3296 {3297 // Compiler generates a forStmt to copy the array3298 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, forStmt())));3299 EXPECT_FALSE(3300 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, forStmt())));3301 }3302 {3303 // The defaulted method declaration can be matched, but not its3304 // definition, in IgnoreUnlessSpelledInSource mode3305 auto MDecl = cxxMethodDecl(ofClass(cxxRecordDecl(hasName("ContainsArray"))),3306 isCopyAssignmentOperator(), isDefaulted());3307 3308 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDecl)));3309 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDecl)));3310 3311 auto MDef = cxxMethodDecl(MDecl, has(compoundStmt()));3312 3313 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));3314 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));3315 3316 auto MBody = cxxMethodDecl(MDecl, hasBody(compoundStmt()));3317 3318 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MBody)));3319 EXPECT_FALSE(3320 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MBody)));3321 3322 auto MIsDefn = cxxMethodDecl(MDecl, isDefinition());3323 3324 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MIsDefn)));3325 EXPECT_TRUE(3326 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsDefn)));3327 3328 auto MIsInline = cxxMethodDecl(MDecl, isInline());3329 3330 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, MIsInline)));3331 EXPECT_FALSE(3332 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsInline)));3333 3334 // The parameter of the defaulted method can still be matched.3335 auto MParm =3336 cxxMethodDecl(MDecl, hasParameter(0, parmVarDecl(hasName("other"))));3337 3338 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MParm)));3339 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MParm)));3340 }3341 {3342 auto M =3343 cxxConstructorDecl(hasName("HasCtorInits"),3344 has(cxxCtorInitializer(forField(hasName("m_i")))));3345 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3346 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3347 }3348 {3349 auto M =3350 cxxConstructorDecl(hasName("HasCtorInits"),3351 has(cxxCtorInitializer(forField(hasName("m_nt")))));3352 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3353 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3354 }3355 {3356 auto M = cxxConstructorDecl(hasName("HasCtorInits"),3357 hasAnyConstructorInitializer(cxxCtorInitializer(3358 forField(hasName("m_nt")))));3359 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3360 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3361 }3362 {3363 auto M =3364 cxxConstructorDecl(hasName("HasCtorInits"),3365 forEachConstructorInitializer(3366 cxxCtorInitializer(forField(hasName("m_nt")))));3367 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3368 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3369 }3370 {3371 auto M = cxxConstructorDecl(3372 hasName("CtorInitsNonTrivial"),3373 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(3374 hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));3375 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3376 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3377 }3378 {3379 auto M = cxxConstructorDecl(3380 hasName("HasCtorInits"),3381 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(3382 cxxConstructorDecl(hasName("NoSpecialMethods"))))))));3383 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3384 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3385 }3386 {3387 auto M = cxxCtorInitializer(forField(hasName("m_nt")));3388 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3389 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3390 }3391 3392 Code = R"cpp(3393 void rangeFor()3394 {3395 int arr[2];3396 for (auto i : arr)3397 {3398 if (true)3399 {3400 }3401 }3402 }3403 )cpp";3404 {3405 auto M = cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));3406 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3407 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3408 }3409 {3410 auto M =3411 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));3412 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3413 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3414 }3415 {3416 auto M =3417 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));3418 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3419 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3420 }3421 {3422 auto M = cxxForRangeStmt(has(declStmt()));3423 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3424 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3425 }3426 {3427 auto M =3428 cxxForRangeStmt(hasLoopVariable(varDecl(hasName("i"))),3429 hasRangeInit(declRefExpr(to(varDecl(hasName("arr"))))));3430 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3431 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3432 }3433 {3434 auto M = cxxForRangeStmt(unless(hasInitStatement(stmt())));3435 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3436 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3437 }3438 {3439 auto M = cxxForRangeStmt(hasBody(stmt()));3440 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3441 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3442 }3443 {3444 auto M = cxxForRangeStmt(hasDescendant(ifStmt()));3445 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3446 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3447 }3448 {3449 EXPECT_TRUE(matches(3450 Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(3451 hasSingleDecl(varDecl(hasName("i")))))))));3452 EXPECT_TRUE(3453 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,3454 cxxForRangeStmt(has(varDecl(hasName("i")))))));3455 }3456 {3457 EXPECT_TRUE(matches(3458 Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(hasSingleDecl(3459 varDecl(hasInitializer(declRefExpr(3460 to(varDecl(hasName("arr")))))))))))));3461 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,3462 cxxForRangeStmt(has(declRefExpr(3463 to(varDecl(hasName("arr")))))))));3464 }3465 {3466 auto M = cxxForRangeStmt(has(compoundStmt()));3467 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3468 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3469 }3470 {3471 auto M = binaryOperator(hasOperatorName("!="));3472 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3473 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3474 }3475 {3476 auto M = unaryOperator(hasOperatorName("++"));3477 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3478 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3479 }3480 {3481 auto M = declStmt(hasSingleDecl(varDecl(matchesName("__range"))));3482 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3483 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3484 }3485 {3486 auto M = declStmt(hasSingleDecl(varDecl(matchesName("__begin"))));3487 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3488 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3489 }3490 {3491 auto M = declStmt(hasSingleDecl(varDecl(matchesName("__end"))));3492 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3493 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3494 }3495 {3496 auto M = ifStmt(hasParent(compoundStmt(hasParent(cxxForRangeStmt()))));3497 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3498 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3499 }3500 {3501 auto M = cxxForRangeStmt(3502 has(varDecl(hasName("i"), hasParent(cxxForRangeStmt()))));3503 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));3504 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3505 }3506 {3507 auto M = cxxForRangeStmt(hasDescendant(varDecl(3508 hasName("i"), hasParent(declStmt(hasParent(cxxForRangeStmt()))))));3509 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3510 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3511 }3512 {3513 auto M = cxxForRangeStmt(hasRangeInit(declRefExpr(3514 to(varDecl(hasName("arr"))), hasParent(cxxForRangeStmt()))));3515 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));3516 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3517 }3518 3519 {3520 auto M = cxxForRangeStmt(hasRangeInit(declRefExpr(3521 to(varDecl(hasName("arr"))), hasParent(varDecl(hasParent(declStmt(3522 hasParent(cxxForRangeStmt()))))))));3523 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3524 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3525 }3526 3527 Code = R"cpp(3528 struct Range {3529 int* begin() const;3530 int* end() const;3531 };3532 Range getRange(int);3533 3534 void rangeFor()3535 {3536 for (auto i : getRange(42))3537 {3538 }3539 }3540 )cpp";3541 {3542 auto M = integerLiteral(equals(42));3543 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3544 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3545 }3546 {3547 auto M = callExpr(hasDescendant(integerLiteral(equals(42))));3548 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3549 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3550 }3551 {3552 auto M = compoundStmt(hasDescendant(integerLiteral(equals(42))));3553 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3554 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3555 }3556 3557 Code = R"cpp(3558 void rangeFor()3559 {3560 int arr[2];3561 for (auto& a = arr; auto i : a)3562 {3563 3564 }3565 }3566 )cpp";3567 {3568 auto M = cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));3569 EXPECT_TRUE(3570 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3571 EXPECT_FALSE(3572 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3573 true, {"-std=c++20"}));3574 }3575 {3576 auto M =3577 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));3578 EXPECT_TRUE(3579 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3580 EXPECT_FALSE(3581 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3582 true, {"-std=c++20"}));3583 }3584 {3585 auto M =3586 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));3587 EXPECT_TRUE(3588 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3589 EXPECT_FALSE(3590 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3591 true, {"-std=c++20"}));3592 }3593 {3594 auto M =3595 cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i"))))));3596 EXPECT_TRUE(3597 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3598 EXPECT_FALSE(3599 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3600 true, {"-std=c++20"}));3601 }3602 {3603 auto M = cxxForRangeStmt(3604 hasInitStatement(declStmt(hasSingleDecl(varDecl(3605 hasName("a"),3606 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),3607 hasLoopVariable(varDecl(hasName("i"))),3608 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));3609 EXPECT_TRUE(3610 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3611 EXPECT_TRUE(3612 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3613 true, {"-std=c++20"}));3614 }3615 {3616 auto M = cxxForRangeStmt(3617 has(declStmt(hasSingleDecl(varDecl(3618 hasName("a"),3619 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),3620 hasLoopVariable(varDecl(hasName("i"))),3621 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));3622 EXPECT_TRUE(3623 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3624 EXPECT_TRUE(3625 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3626 true, {"-std=c++20"}));3627 }3628 {3629 auto M = cxxForRangeStmt(hasInitStatement(declStmt(3630 hasSingleDecl(varDecl(hasName("a"))), hasParent(cxxForRangeStmt()))));3631 EXPECT_TRUE(3632 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3633 EXPECT_TRUE(3634 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3635 true, {"-std=c++20"}));3636 }3637 3638 Code = R"cpp(3639 struct Range {3640 int* begin() const;3641 int* end() const;3642 };3643 Range getRange(int);3644 3645 int getNum(int);3646 3647 void rangeFor()3648 {3649 for (auto j = getNum(42); auto i : getRange(j))3650 {3651 }3652 }3653 )cpp";3654 {3655 auto M = integerLiteral(equals(42));3656 EXPECT_TRUE(3657 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3658 EXPECT_TRUE(3659 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3660 true, {"-std=c++20"}));3661 }3662 {3663 auto M = compoundStmt(hasDescendant(integerLiteral(equals(42))));3664 EXPECT_TRUE(3665 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));3666 EXPECT_TRUE(3667 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),3668 true, {"-std=c++20"}));3669 }3670 3671 Code = R"cpp(3672void hasDefaultArg(int i, int j = 0)3673{3674}3675void callDefaultArg()3676{3677 hasDefaultArg(42);3678}3679)cpp";3680 auto hasDefaultArgCall = [](auto InnerMatcher) {3681 return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),3682 InnerMatcher);3683 };3684 {3685 auto M = hasDefaultArgCall(has(integerLiteral(equals(42))));3686 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3687 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3688 }3689 {3690 auto M = hasDefaultArgCall(has(cxxDefaultArgExpr()));3691 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3692 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3693 }3694 {3695 auto M = hasDefaultArgCall(argumentCountIs(2));3696 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3697 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3698 }3699 {3700 auto M = hasDefaultArgCall(argumentCountIs(1));3701 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));3702 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3703 }3704 {3705 auto M = hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));3706 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3707 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3708 }3709 {3710 auto M = hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));3711 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3712 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3713 }3714 Code = R"cpp(3715struct A3716{3717 ~A();3718private:3719 int i;3720};3721 3722A::~A() = default;3723)cpp";3724 {3725 auto M = cxxDestructorDecl(isDefaulted(),3726 ofClass(cxxRecordDecl(has(fieldDecl()))));3727 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));3728 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));3729 }3730 Code = R"cpp(3731struct S3732{3733 static constexpr bool getTrue() { return true; }3734};3735 3736struct A3737{3738 explicit(S::getTrue()) A();3739};3740 3741A::A() = default;3742)cpp";3743 {3744 EXPECT_TRUE(matchesConditionally(3745 Code,3746 traverse(TK_AsIs,3747 cxxConstructorDecl(3748 isDefaulted(),3749 hasExplicitSpecifier(expr(ignoringImplicit(3750 callExpr(has(ignoringImplicit(declRefExpr())))))))),3751 true, {"-std=c++20"}));3752 EXPECT_TRUE(matchesConditionally(3753 Code,3754 traverse(TK_IgnoreUnlessSpelledInSource,3755 cxxConstructorDecl(3756 isDefaulted(),3757 hasExplicitSpecifier(callExpr(has(declRefExpr()))))),3758 true, {"-std=c++20"}));3759 }3760}3761 3762template <typename MatcherT>3763bool matcherTemplateWithBinding(StringRef Code, const MatcherT &M) {3764 return matchAndVerifyResultTrue(3765 Code, M.bind("matchedStmt"),3766 std::make_unique<VerifyIdIsBoundTo<ReturnStmt>>("matchedStmt", 1));3767}3768 3769TEST(Traversal, traverseWithBinding) {3770 // Some existing matcher code expects to take a matcher as a3771 // template arg and bind to it. Verify that that works.3772 3773 llvm::StringRef Code = R"cpp(3774int foo()3775{3776 return 42.0;3777}3778)cpp";3779 EXPECT_TRUE(matcherTemplateWithBinding(3780 Code, traverse(TK_AsIs,3781 returnStmt(has(implicitCastExpr(has(floatLiteral())))))));3782}3783 3784TEST(Traversal, traverseMatcherNesting) {3785 3786 StringRef Code = R"cpp(3787float bar(int i)3788{3789 return i;3790}3791 3792void foo()3793{3794 bar(bar(3.0));3795}3796)cpp";3797 3798 EXPECT_TRUE(3799 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,3800 callExpr(has(callExpr(traverse(3801 TK_AsIs, callExpr(has(implicitCastExpr(3802 has(floatLiteral())))))))))));3803 3804 EXPECT_TRUE(matches(3805 Code,3806 traverse(TK_IgnoreUnlessSpelledInSource,3807 traverse(TK_AsIs, implicitCastExpr(has(floatLiteral()))))));3808}3809 3810TEST(Traversal, traverseMatcherThroughImplicit) {3811 StringRef Code = R"cpp(3812struct S {3813 S(int x);3814};3815 3816void constructImplicit() {3817 int a = 8;3818 S s(a);3819}3820 )cpp";3821 3822 auto Matcher = traverse(TK_IgnoreUnlessSpelledInSource, implicitCastExpr());3823 3824 // Verfiy that it does not segfault3825 EXPECT_FALSE(matches(Code, Matcher));3826}3827 3828TEST(Traversal, traverseMatcherThroughMemoization) {3829 3830 StringRef Code = R"cpp(3831void foo()3832{3833 int i = 3.0;3834}3835 )cpp";3836 3837 auto Matcher = varDecl(hasInitializer(floatLiteral()));3838 3839 // Matchers such as hasDescendant memoize their result regarding AST3840 // nodes. In the matcher below, the first use of hasDescendant(Matcher)3841 // fails, and the use of it inside the traverse() matcher should pass3842 // causing the overall matcher to be a true match.3843 // This test verifies that the first false result is not re-used, which3844 // would cause the overall matcher to be incorrectly false.3845 3846 EXPECT_TRUE(matches(3847 Code,3848 functionDecl(anyOf(hasDescendant(Matcher),3849 traverse(TK_IgnoreUnlessSpelledInSource,3850 functionDecl(hasDescendant(Matcher)))))));3851}3852 3853TEST(Traversal, traverseUnlessSpelledInSource) {3854 3855 StringRef Code = R"cpp(3856 3857struct A3858{3859};3860 3861struct B3862{3863 B(int);3864 B(A const& a);3865 B();3866};3867 3868struct C3869{3870 operator B();3871};3872 3873B func1() {3874 return 42;3875}3876 3877B func2() {3878 return B{42};3879}3880 3881B func3() {3882 return B(42);3883}3884 3885B func4() {3886 return B();3887}3888 3889B func5() {3890 return B{};3891}3892 3893B func6() {3894 return C();3895}3896 3897B func7() {3898 return A();3899}3900 3901B func8() {3902 return C{};3903}3904 3905B func9() {3906 return A{};3907}3908 3909B func10() {3910 A a;3911 return a;3912}3913 3914B func11() {3915 B b;3916 return b;3917}3918 3919B func12() {3920 C c;3921 return c;3922}3923 3924void func13() {3925 int a = 0;3926 int c = 0;3927 3928 [a, b = c](int d) { int e = d; };3929}3930 3931void func14() {3932 [] <typename TemplateType> (TemplateType t, TemplateType u) { int e = t + u; };3933 float i = 42.0;3934}3935 3936void func15() {3937 int count = 0;3938 auto l = [&] { ++count; };3939 (void)l;3940}3941 3942)cpp";3943 3944 EXPECT_TRUE(3945 matches(Code,3946 traverse(TK_IgnoreUnlessSpelledInSource,3947 returnStmt(forFunction(functionDecl(hasName("func1"))),3948 hasReturnValue(integerLiteral(equals(42))))),3949 langCxx20OrLater()));3950 3951 EXPECT_TRUE(3952 matches(Code,3953 traverse(TK_IgnoreUnlessSpelledInSource,3954 integerLiteral(equals(42),3955 hasParent(returnStmt(forFunction(3956 functionDecl(hasName("func1"))))))),3957 langCxx20OrLater()));3958 3959 EXPECT_TRUE(matches(3960 Code,3961 traverse(TK_IgnoreUnlessSpelledInSource,3962 returnStmt(forFunction(functionDecl(hasName("func2"))),3963 hasReturnValue(cxxTemporaryObjectExpr(3964 hasArgument(0, integerLiteral(equals(42))))))),3965 langCxx20OrLater()));3966 EXPECT_TRUE(matches(3967 Code,3968 traverse(3969 TK_IgnoreUnlessSpelledInSource,3970 integerLiteral(equals(42),3971 hasParent(cxxTemporaryObjectExpr(hasParent(returnStmt(3972 forFunction(functionDecl(hasName("func2"))))))))),3973 langCxx20OrLater()));3974 3975 EXPECT_TRUE(3976 matches(Code,3977 traverse(TK_IgnoreUnlessSpelledInSource,3978 returnStmt(forFunction(functionDecl(hasName("func3"))),3979 hasReturnValue(cxxConstructExpr(hasArgument(3980 0, integerLiteral(equals(42))))))),3981 langCxx20OrLater()));3982 3983 EXPECT_TRUE(matches(3984 Code,3985 traverse(3986 TK_IgnoreUnlessSpelledInSource,3987 integerLiteral(equals(42),3988 hasParent(cxxConstructExpr(hasParent(returnStmt(3989 forFunction(functionDecl(hasName("func3"))))))))),3990 langCxx20OrLater()));3991 3992 EXPECT_TRUE(3993 matches(Code,3994 traverse(TK_IgnoreUnlessSpelledInSource,3995 returnStmt(forFunction(functionDecl(hasName("func4"))),3996 hasReturnValue(cxxTemporaryObjectExpr()))),3997 langCxx20OrLater()));3998 3999 EXPECT_TRUE(4000 matches(Code,4001 traverse(TK_IgnoreUnlessSpelledInSource,4002 returnStmt(forFunction(functionDecl(hasName("func5"))),4003 hasReturnValue(cxxTemporaryObjectExpr()))),4004 langCxx20OrLater()));4005 4006 EXPECT_TRUE(4007 matches(Code,4008 traverse(TK_IgnoreUnlessSpelledInSource,4009 returnStmt(forFunction(functionDecl(hasName("func6"))),4010 hasReturnValue(cxxTemporaryObjectExpr()))),4011 langCxx20OrLater()));4012 4013 EXPECT_TRUE(4014 matches(Code,4015 traverse(TK_IgnoreUnlessSpelledInSource,4016 returnStmt(forFunction(functionDecl(hasName("func7"))),4017 hasReturnValue(cxxTemporaryObjectExpr()))),4018 langCxx20OrLater()));4019 4020 EXPECT_TRUE(4021 matches(Code,4022 traverse(TK_IgnoreUnlessSpelledInSource,4023 returnStmt(forFunction(functionDecl(hasName("func8"))),4024 hasReturnValue(cxxFunctionalCastExpr(4025 hasSourceExpression(initListExpr()))))),4026 langCxx20OrLater()));4027 4028 EXPECT_TRUE(4029 matches(Code,4030 traverse(TK_IgnoreUnlessSpelledInSource,4031 returnStmt(forFunction(functionDecl(hasName("func9"))),4032 hasReturnValue(cxxFunctionalCastExpr(4033 hasSourceExpression(initListExpr()))))),4034 langCxx20OrLater()));4035 4036 EXPECT_TRUE(matches(4037 Code,4038 traverse(4039 TK_IgnoreUnlessSpelledInSource,4040 returnStmt(forFunction(functionDecl(hasName("func10"))),4041 hasReturnValue(declRefExpr(to(varDecl(hasName("a"))))))),4042 langCxx20OrLater()));4043 4044 EXPECT_TRUE(4045 matches(Code,4046 traverse(TK_IgnoreUnlessSpelledInSource,4047 declRefExpr(to(varDecl(hasName("a"))),4048 hasParent(returnStmt(forFunction(4049 functionDecl(hasName("func10"))))))),4050 langCxx20OrLater()));4051 4052 EXPECT_TRUE(matches(4053 Code,4054 traverse(4055 TK_IgnoreUnlessSpelledInSource,4056 returnStmt(forFunction(functionDecl(hasName("func11"))),4057 hasReturnValue(declRefExpr(to(varDecl(hasName("b"))))))),4058 langCxx20OrLater()));4059 4060 EXPECT_TRUE(4061 matches(Code,4062 traverse(TK_IgnoreUnlessSpelledInSource,4063 declRefExpr(to(varDecl(hasName("b"))),4064 hasParent(returnStmt(forFunction(4065 functionDecl(hasName("func11"))))))),4066 langCxx20OrLater()));4067 4068 EXPECT_TRUE(matches(4069 Code,4070 traverse(4071 TK_IgnoreUnlessSpelledInSource,4072 returnStmt(forFunction(functionDecl(hasName("func12"))),4073 hasReturnValue(declRefExpr(to(varDecl(hasName("c"))))))),4074 langCxx20OrLater()));4075 4076 EXPECT_TRUE(4077 matches(Code,4078 traverse(TK_IgnoreUnlessSpelledInSource,4079 declRefExpr(to(varDecl(hasName("c"))),4080 hasParent(returnStmt(forFunction(4081 functionDecl(hasName("func12"))))))),4082 langCxx20OrLater()));4083 4084 EXPECT_TRUE(matches(4085 Code,4086 traverse(4087 TK_IgnoreUnlessSpelledInSource,4088 lambdaExpr(forFunction(functionDecl(hasName("func13"))),4089 has(compoundStmt(hasDescendant(varDecl(hasName("e"))))),4090 has(declRefExpr(to(varDecl(hasName("a"))))),4091 has(varDecl(hasName("b"), hasInitializer(declRefExpr(to(4092 varDecl(hasName("c"))))))),4093 has(parmVarDecl(hasName("d"))))),4094 langCxx20OrLater()));4095 4096 EXPECT_TRUE(4097 matches(Code,4098 traverse(TK_IgnoreUnlessSpelledInSource,4099 declRefExpr(to(varDecl(hasName("a"))),4100 hasParent(lambdaExpr(forFunction(4101 functionDecl(hasName("func13"))))))),4102 langCxx20OrLater()));4103 4104 EXPECT_TRUE(matches(4105 Code,4106 traverse(TK_IgnoreUnlessSpelledInSource,4107 varDecl(hasName("b"),4108 hasInitializer(declRefExpr(to(varDecl(hasName("c"))))),4109 hasParent(lambdaExpr(4110 forFunction(functionDecl(hasName("func13"))))))),4111 langCxx20OrLater()));4112 4113 EXPECT_TRUE(matches(Code,4114 traverse(TK_IgnoreUnlessSpelledInSource,4115 compoundStmt(hasParent(lambdaExpr(forFunction(4116 functionDecl(hasName("func13"))))))),4117 langCxx20OrLater()));4118 4119 EXPECT_TRUE(matches(4120 Code,4121 traverse(TK_IgnoreUnlessSpelledInSource,4122 templateTypeParmDecl(hasName("TemplateType"),4123 hasParent(lambdaExpr(forFunction(4124 functionDecl(hasName("func14"))))))),4125 langCxx20OrLater()));4126 4127 EXPECT_TRUE(matches(4128 Code,4129 traverse(TK_IgnoreUnlessSpelledInSource,4130 lambdaExpr(forFunction(functionDecl(hasName("func14"))),4131 has(templateTypeParmDecl(hasName("TemplateType"))))),4132 langCxx20OrLater()));4133 4134 EXPECT_TRUE(matches(4135 Code,4136 traverse(TK_IgnoreUnlessSpelledInSource,4137 functionDecl(hasName("func14"), hasDescendant(floatLiteral()))),4138 langCxx20OrLater()));4139 4140 EXPECT_TRUE(matches(4141 Code,4142 traverse(TK_IgnoreUnlessSpelledInSource,4143 compoundStmt(4144 hasDescendant(varDecl(hasName("count")).bind("countVar")),4145 hasDescendant(4146 declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))),4147 langCxx20OrLater()));4148 4149 Code = R"cpp(4150void foo() {4151 int explicit_captured = 0;4152 int implicit_captured = 0;4153 auto l = [&, explicit_captured](int i) {4154 if (i || explicit_captured || implicit_captured) return;4155 };4156}4157)cpp";4158 4159 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, ifStmt())));4160 EXPECT_TRUE(4161 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, ifStmt())));4162 4163 auto lambdaExplicitCapture = declRefExpr(4164 to(varDecl(hasName("explicit_captured"))), unless(hasAncestor(ifStmt())));4165 auto lambdaImplicitCapture = declRefExpr(4166 to(varDecl(hasName("implicit_captured"))), unless(hasAncestor(ifStmt())));4167 4168 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaExplicitCapture)));4169 EXPECT_TRUE(matches(4170 Code, traverse(TK_IgnoreUnlessSpelledInSource, lambdaExplicitCapture)));4171 4172 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaImplicitCapture)));4173 EXPECT_FALSE(matches(4174 Code, traverse(TK_IgnoreUnlessSpelledInSource, lambdaImplicitCapture)));4175 4176 Code = R"cpp(4177struct S {};4178 4179struct HasOpEq4180{4181 bool operator==(const S& other)4182 {4183 return true;4184 }4185};4186 4187void binop()4188{4189 HasOpEq s1;4190 S s2;4191 if (s1 != s2)4192 return;4193}4194)cpp";4195 {4196 auto M = unaryOperator(4197 hasOperatorName("!"),4198 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="))));4199 EXPECT_TRUE(4200 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4201 EXPECT_FALSE(4202 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4203 true, {"-std=c++20"}));4204 }4205 {4206 auto M = declRefExpr(to(varDecl(hasName("s1"))));4207 EXPECT_TRUE(4208 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4209 EXPECT_TRUE(4210 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4211 true, {"-std=c++20"}));4212 }4213 {4214 auto M = cxxOperatorCallExpr(hasOverloadedOperatorName("=="));4215 EXPECT_TRUE(4216 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4217 EXPECT_FALSE(4218 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4219 true, {"-std=c++20"}));4220 }4221 {4222 auto M = cxxOperatorCallExpr(hasOverloadedOperatorName("!="));4223 EXPECT_FALSE(4224 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4225 EXPECT_FALSE(4226 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4227 true, {"-std=c++20"}));4228 }4229 auto withDescendants = [](StringRef lName, StringRef rName) {4230 return stmt(hasDescendant(declRefExpr(to(varDecl(hasName(lName))))),4231 hasDescendant(declRefExpr(to(varDecl(hasName(rName))))));4232 };4233 {4234 auto M = cxxRewrittenBinaryOperator(withDescendants("s1", "s2"));4235 EXPECT_TRUE(4236 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4237 EXPECT_TRUE(4238 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4239 true, {"-std=c++20"}));4240 }4241 {4242 auto M = cxxRewrittenBinaryOperator(4243 has(declRefExpr(to(varDecl(hasName("s1"))))),4244 has(declRefExpr(to(varDecl(hasName("s2"))))));4245 EXPECT_FALSE(4246 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4247 EXPECT_TRUE(4248 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4249 true, {"-std=c++20"}));4250 }4251 {4252 auto M = cxxRewrittenBinaryOperator(4253 hasLHS(expr(hasParent(cxxRewrittenBinaryOperator()))),4254 hasRHS(expr(hasParent(cxxRewrittenBinaryOperator()))));4255 EXPECT_FALSE(4256 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4257 EXPECT_TRUE(4258 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4259 true, {"-std=c++20"}));4260 }4261 {4262 EXPECT_TRUE(matchesConditionally(4263 Code,4264 traverse(TK_AsIs,4265 cxxRewrittenBinaryOperator(4266 hasOperatorName("!="), hasAnyOperatorName("<", "!="),4267 isComparisonOperator(),4268 hasLHS(ignoringImplicit(4269 declRefExpr(to(varDecl(hasName("s1")))))),4270 hasRHS(ignoringImplicit(4271 declRefExpr(to(varDecl(hasName("s2")))))),4272 hasEitherOperand(ignoringImplicit(4273 declRefExpr(to(varDecl(hasName("s2")))))),4274 hasOperands(ignoringImplicit(4275 declRefExpr(to(varDecl(hasName("s1"))))),4276 ignoringImplicit(declRefExpr(4277 to(varDecl(hasName("s2")))))))),4278 true, {"-std=c++20"}));4279 EXPECT_TRUE(matchesConditionally(4280 Code,4281 traverse(TK_IgnoreUnlessSpelledInSource,4282 cxxRewrittenBinaryOperator(4283 hasOperatorName("!="), hasAnyOperatorName("<", "!="),4284 isComparisonOperator(),4285 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),4286 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),4287 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),4288 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),4289 declRefExpr(to(varDecl(hasName("s2"))))))),4290 true, {"-std=c++20"}));4291 }4292 4293 Code = R"cpp(4294namespace std {4295struct strong_ordering {4296 int n;4297 constexpr operator int() const { return n; }4298 static const strong_ordering equal, greater, less;4299};4300constexpr strong_ordering strong_ordering::equal = {0};4301constexpr strong_ordering strong_ordering::greater = {1};4302constexpr strong_ordering strong_ordering::less = {-1};4303}4304 4305struct HasSpaceshipMem {4306 int a;4307 constexpr auto operator<=>(const HasSpaceshipMem&) const = default;4308};4309 4310void binop()4311{4312 HasSpaceshipMem hs1, hs2;4313 if (hs1 == hs2)4314 return;4315 4316 HasSpaceshipMem hs3, hs4;4317 if (hs3 != hs4)4318 return;4319 4320 HasSpaceshipMem hs5, hs6;4321 if (hs5 < hs6)4322 return;4323 4324 HasSpaceshipMem hs7, hs8;4325 if (hs7 > hs8)4326 return;4327 4328 HasSpaceshipMem hs9, hs10;4329 if (hs9 <= hs10)4330 return;4331 4332 HasSpaceshipMem hs11, hs12;4333 if (hs11 >= hs12)4334 return;4335}4336)cpp";4337 auto withArgs = [](StringRef lName, StringRef rName) {4338 return cxxOperatorCallExpr(4339 hasArgument(0, declRefExpr(to(varDecl(hasName(lName))))),4340 hasArgument(1, declRefExpr(to(varDecl(hasName(rName))))));4341 };4342 {4343 auto M = ifStmt(hasCondition(cxxOperatorCallExpr(4344 hasOverloadedOperatorName("=="), withArgs("hs1", "hs2"))));4345 EXPECT_TRUE(4346 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4347 EXPECT_TRUE(4348 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4349 true, {"-std=c++20"}));4350 }4351 {4352 auto M =4353 unaryOperator(hasOperatorName("!"),4354 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),4355 withArgs("hs3", "hs4"))));4356 EXPECT_TRUE(4357 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4358 EXPECT_FALSE(4359 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4360 true, {"-std=c++20"}));4361 }4362 {4363 auto M =4364 unaryOperator(hasOperatorName("!"),4365 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),4366 withArgs("hs3", "hs4"))));4367 EXPECT_TRUE(4368 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4369 EXPECT_FALSE(4370 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4371 true, {"-std=c++20"}));4372 }4373 {4374 auto M = binaryOperator(4375 hasOperatorName("<"),4376 hasLHS(hasDescendant(cxxOperatorCallExpr(4377 hasOverloadedOperatorName("<=>"), withArgs("hs5", "hs6")))),4378 hasRHS(integerLiteral(equals(0))));4379 EXPECT_TRUE(4380 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4381 EXPECT_FALSE(4382 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4383 true, {"-std=c++20"}));4384 }4385 {4386 auto M = cxxRewrittenBinaryOperator(withDescendants("hs3", "hs4"));4387 EXPECT_TRUE(4388 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4389 EXPECT_TRUE(4390 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4391 true, {"-std=c++20"}));4392 }4393 {4394 auto M = declRefExpr(to(varDecl(hasName("hs3"))));4395 EXPECT_TRUE(4396 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4397 EXPECT_TRUE(4398 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4399 true, {"-std=c++20"}));4400 }4401 {4402 auto M = cxxRewrittenBinaryOperator(has(4403 unaryOperator(hasOperatorName("!"), withDescendants("hs3", "hs4"))));4404 EXPECT_TRUE(4405 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4406 EXPECT_FALSE(4407 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4408 true, {"-std=c++20"}));4409 }4410 {4411 auto M = cxxRewrittenBinaryOperator(4412 has(declRefExpr(to(varDecl(hasName("hs3"))))),4413 has(declRefExpr(to(varDecl(hasName("hs4"))))));4414 EXPECT_FALSE(4415 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));4416 EXPECT_TRUE(4417 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),4418 true, {"-std=c++20"}));4419 }4420 {4421 EXPECT_TRUE(matchesConditionally(4422 Code,4423 traverse(TK_AsIs,4424 cxxRewrittenBinaryOperator(4425 hasOperatorName("!="), hasAnyOperatorName("<", "!="),4426 isComparisonOperator(),4427 hasLHS(ignoringImplicit(4428 declRefExpr(to(varDecl(hasName("hs3")))))),4429 hasRHS(ignoringImplicit(4430 declRefExpr(to(varDecl(hasName("hs4")))))),4431 hasEitherOperand(ignoringImplicit(4432 declRefExpr(to(varDecl(hasName("hs3")))))),4433 hasOperands(ignoringImplicit(4434 declRefExpr(to(varDecl(hasName("hs3"))))),4435 ignoringImplicit(declRefExpr(4436 to(varDecl(hasName("hs4")))))))),4437 true, {"-std=c++20"}));4438 EXPECT_TRUE(matchesConditionally(4439 Code,4440 traverse(TK_IgnoreUnlessSpelledInSource,4441 cxxRewrittenBinaryOperator(4442 hasOperatorName("!="), hasAnyOperatorName("<", "!="),4443 isComparisonOperator(),4444 hasLHS(declRefExpr(to(varDecl(hasName("hs3"))))),4445 hasRHS(declRefExpr(to(varDecl(hasName("hs4"))))),4446 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs3"))))),4447 hasOperands(declRefExpr(to(varDecl(hasName("hs3")))),4448 declRefExpr(to(varDecl(hasName("hs4"))))))),4449 true, {"-std=c++20"}));4450 }4451 {4452 EXPECT_TRUE(matchesConditionally(4453 Code,4454 traverse(TK_AsIs,4455 cxxRewrittenBinaryOperator(4456 hasOperatorName("<"), hasAnyOperatorName("<", "!="),4457 isComparisonOperator(),4458 hasLHS(ignoringImplicit(4459 declRefExpr(to(varDecl(hasName("hs5")))))),4460 hasRHS(ignoringImplicit(4461 declRefExpr(to(varDecl(hasName("hs6")))))),4462 hasEitherOperand(ignoringImplicit(4463 declRefExpr(to(varDecl(hasName("hs5")))))),4464 hasOperands(ignoringImplicit(4465 declRefExpr(to(varDecl(hasName("hs5"))))),4466 ignoringImplicit(declRefExpr(4467 to(varDecl(hasName("hs6")))))))),4468 true, {"-std=c++20"}));4469 EXPECT_TRUE(matchesConditionally(4470 Code,4471 traverse(TK_IgnoreUnlessSpelledInSource,4472 cxxRewrittenBinaryOperator(4473 hasOperatorName("<"), hasAnyOperatorName("<", "!="),4474 isComparisonOperator(),4475 hasLHS(declRefExpr(to(varDecl(hasName("hs5"))))),4476 hasRHS(declRefExpr(to(varDecl(hasName("hs6"))))),4477 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs5"))))),4478 hasOperands(declRefExpr(to(varDecl(hasName("hs5")))),4479 declRefExpr(to(varDecl(hasName("hs6"))))))),4480 true, {"-std=c++20"}));4481 }4482 {4483 EXPECT_TRUE(matchesConditionally(4484 Code,4485 traverse(TK_AsIs,4486 cxxRewrittenBinaryOperator(4487 hasOperatorName(">"), hasAnyOperatorName("<", ">"),4488 isComparisonOperator(),4489 hasLHS(ignoringImplicit(4490 declRefExpr(to(varDecl(hasName("hs7")))))),4491 hasRHS(ignoringImplicit(4492 declRefExpr(to(varDecl(hasName("hs8")))))),4493 hasEitherOperand(ignoringImplicit(4494 declRefExpr(to(varDecl(hasName("hs7")))))),4495 hasOperands(ignoringImplicit(4496 declRefExpr(to(varDecl(hasName("hs7"))))),4497 ignoringImplicit(declRefExpr(4498 to(varDecl(hasName("hs8")))))))),4499 true, {"-std=c++20"}));4500 EXPECT_TRUE(matchesConditionally(4501 Code,4502 traverse(TK_IgnoreUnlessSpelledInSource,4503 cxxRewrittenBinaryOperator(4504 hasOperatorName(">"), hasAnyOperatorName("<", ">"),4505 isComparisonOperator(),4506 hasLHS(declRefExpr(to(varDecl(hasName("hs7"))))),4507 hasRHS(declRefExpr(to(varDecl(hasName("hs8"))))),4508 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs7"))))),4509 hasOperands(declRefExpr(to(varDecl(hasName("hs7")))),4510 declRefExpr(to(varDecl(hasName("hs8"))))))),4511 true, {"-std=c++20"}));4512 }4513 {4514 EXPECT_TRUE(matchesConditionally(4515 Code,4516 traverse(TK_AsIs,4517 cxxRewrittenBinaryOperator(4518 hasOperatorName("<="), hasAnyOperatorName("<", "<="),4519 isComparisonOperator(),4520 hasLHS(ignoringImplicit(4521 declRefExpr(to(varDecl(hasName("hs9")))))),4522 hasRHS(ignoringImplicit(4523 declRefExpr(to(varDecl(hasName("hs10")))))),4524 hasEitherOperand(ignoringImplicit(4525 declRefExpr(to(varDecl(hasName("hs9")))))),4526 hasOperands(ignoringImplicit(4527 declRefExpr(to(varDecl(hasName("hs9"))))),4528 ignoringImplicit(declRefExpr(4529 to(varDecl(hasName("hs10")))))))),4530 true, {"-std=c++20"}));4531 EXPECT_TRUE(matchesConditionally(4532 Code,4533 traverse(TK_IgnoreUnlessSpelledInSource,4534 cxxRewrittenBinaryOperator(4535 hasOperatorName("<="), hasAnyOperatorName("<", "<="),4536 isComparisonOperator(),4537 hasLHS(declRefExpr(to(varDecl(hasName("hs9"))))),4538 hasRHS(declRefExpr(to(varDecl(hasName("hs10"))))),4539 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs9"))))),4540 hasOperands(declRefExpr(to(varDecl(hasName("hs9")))),4541 declRefExpr(to(varDecl(hasName("hs10"))))))),4542 true, {"-std=c++20"}));4543 }4544 {4545 EXPECT_TRUE(matchesConditionally(4546 Code,4547 traverse(TK_AsIs,4548 cxxRewrittenBinaryOperator(4549 hasOperatorName(">="), hasAnyOperatorName("<", ">="),4550 isComparisonOperator(),4551 hasLHS(ignoringImplicit(4552 declRefExpr(to(varDecl(hasName("hs11")))))),4553 hasRHS(ignoringImplicit(4554 declRefExpr(to(varDecl(hasName("hs12")))))),4555 hasEitherOperand(ignoringImplicit(4556 declRefExpr(to(varDecl(hasName("hs11")))))),4557 hasOperands(ignoringImplicit(4558 declRefExpr(to(varDecl(hasName("hs11"))))),4559 ignoringImplicit(declRefExpr(4560 to(varDecl(hasName("hs12")))))))),4561 true, {"-std=c++20"}));4562 EXPECT_TRUE(matchesConditionally(4563 Code,4564 traverse(4565 TK_IgnoreUnlessSpelledInSource,4566 cxxRewrittenBinaryOperator(4567 hasOperatorName(">="), hasAnyOperatorName("<", ">="),4568 isComparisonOperator(),4569 hasLHS(declRefExpr(to(varDecl(hasName("hs11"))))),4570 hasRHS(declRefExpr(to(varDecl(hasName("hs12"))))),4571 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs11"))))),4572 hasOperands(declRefExpr(to(varDecl(hasName("hs11")))),4573 declRefExpr(to(varDecl(hasName("hs12"))))))),4574 true, {"-std=c++20"}));4575 }4576 4577 Code = R"cpp(4578struct S {};4579 4580struct HasOpEq4581{4582 bool operator==(const S& other) const4583 {4584 return true;4585 }4586};4587 4588struct HasOpEqMem {4589 bool operator==(const HasOpEqMem&) const { return true; }4590};4591 4592struct HasOpEqFree {4593};4594bool operator==(const HasOpEqFree&, const HasOpEqFree&) { return true; }4595 4596void binop()4597{4598 {4599 HasOpEq s1;4600 S s2;4601 if (s1 != s2)4602 return;4603 }4604 4605 {4606 int i1;4607 int i2;4608 if (i1 != i2)4609 return;4610 }4611 4612 {4613 HasOpEqMem M1;4614 HasOpEqMem M2;4615 if (M1 == M2)4616 return;4617 }4618 4619 {4620 HasOpEqFree F1;4621 HasOpEqFree F2;4622 if (F1 == F2)4623 return;4624 }4625}4626)cpp";4627 {4628 EXPECT_TRUE(matchesConditionally(4629 Code,4630 traverse(TK_AsIs,4631 binaryOperation(4632 hasOperatorName("!="), hasAnyOperatorName("<", "!="),4633 isComparisonOperator(),4634 hasLHS(ignoringImplicit(4635 declRefExpr(to(varDecl(hasName("s1")))))),4636 hasRHS(ignoringImplicit(4637 declRefExpr(to(varDecl(hasName("s2")))))),4638 hasEitherOperand(ignoringImplicit(4639 declRefExpr(to(varDecl(hasName("s2")))))),4640 hasOperands(ignoringImplicit(4641 declRefExpr(to(varDecl(hasName("s1"))))),4642 ignoringImplicit(declRefExpr(4643 to(varDecl(hasName("s2")))))))),4644 true, {"-std=c++20"}));4645 EXPECT_TRUE(matchesConditionally(4646 Code,4647 traverse(TK_AsIs, binaryOperation(hasOperatorName("!="),4648 hasLHS(ignoringImplicit(declRefExpr(4649 to(varDecl(hasName("i1")))))),4650 hasRHS(ignoringImplicit(declRefExpr(4651 to(varDecl(hasName("i2")))))))),4652 true, {"-std=c++20"}));4653 EXPECT_TRUE(matchesConditionally(4654 Code,4655 traverse(TK_AsIs, binaryOperation(hasOperatorName("=="),4656 hasLHS(ignoringImplicit(declRefExpr(4657 to(varDecl(hasName("M1")))))),4658 hasRHS(ignoringImplicit(declRefExpr(4659 to(varDecl(hasName("M2")))))))),4660 true, {"-std=c++20"}));4661 EXPECT_TRUE(matchesConditionally(4662 Code,4663 traverse(TK_AsIs, binaryOperation(hasOperatorName("=="),4664 hasLHS(ignoringImplicit(declRefExpr(4665 to(varDecl(hasName("F1")))))),4666 hasRHS(ignoringImplicit(declRefExpr(4667 to(varDecl(hasName("F2")))))))),4668 true, {"-std=c++20"}));4669 EXPECT_TRUE(matchesConditionally(4670 Code,4671 traverse(TK_IgnoreUnlessSpelledInSource,4672 binaryOperation(4673 hasOperatorName("!="), hasAnyOperatorName("<", "!="),4674 isComparisonOperator(),4675 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),4676 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),4677 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),4678 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),4679 declRefExpr(to(varDecl(hasName("s2"))))))),4680 true, {"-std=c++20"}));4681 EXPECT_TRUE(matchesConditionally(4682 Code,4683 traverse(4684 TK_IgnoreUnlessSpelledInSource,4685 binaryOperation(hasOperatorName("!="),4686 hasLHS(declRefExpr(to(varDecl(hasName("i1"))))),4687 hasRHS(declRefExpr(to(varDecl(hasName("i2"))))))),4688 true, {"-std=c++20"}));4689 EXPECT_TRUE(matchesConditionally(4690 Code,4691 traverse(4692 TK_IgnoreUnlessSpelledInSource,4693 binaryOperation(hasOperatorName("=="),4694 hasLHS(declRefExpr(to(varDecl(hasName("M1"))))),4695 hasRHS(declRefExpr(to(varDecl(hasName("M2"))))))),4696 true, {"-std=c++20"}));4697 EXPECT_TRUE(matchesConditionally(4698 Code,4699 traverse(4700 TK_IgnoreUnlessSpelledInSource,4701 binaryOperation(hasOperatorName("=="),4702 hasLHS(declRefExpr(to(varDecl(hasName("F1"))))),4703 hasRHS(declRefExpr(to(varDecl(hasName("F2"))))))),4704 true, {"-std=c++20"}));4705 }4706}4707 4708TEST(IgnoringImpCasts, PathologicalLambda) {4709 4710 // Test that deeply nested lambdas are not a performance penalty4711 StringRef Code = R"cpp(4712void f() {4713 [] {4714 [] {4715 [] {4716 [] {4717 [] {4718 [] {4719 [] {4720 [] {4721 [] {4722 [] {4723 [] {4724 [] {4725 [] {4726 [] {4727 [] {4728 [] {4729 [] {4730 [] {4731 [] {4732 [] {4733 [] {4734 [] {4735 [] {4736 [] {4737 [] {4738 [] {4739 [] {4740 [] {4741 [] {4742 int i = 42;4743 (void)i;4744 }();4745 }();4746 }();4747 }();4748 }();4749 }();4750 }();4751 }();4752 }();4753 }();4754 }();4755 }();4756 }();4757 }();4758 }();4759 }();4760 }();4761 }();4762 }();4763 }();4764 }();4765 }();4766 }();4767 }();4768 }();4769 }();4770 }();4771 }();4772 }();4773}4774 )cpp";4775 4776 EXPECT_TRUE(matches(Code, integerLiteral(equals(42))));4777 EXPECT_TRUE(matches(Code, functionDecl(hasDescendant(integerLiteral(equals(42))))));4778}4779 4780TEST(IgnoringImpCasts, MatchesImpCasts) {4781 // This test checks that ignoringImpCasts matches when implicit casts are4782 // present and its inner matcher alone does not match.4783 // Note that this test creates an implicit const cast.4784 EXPECT_TRUE(matches("int x = 0; const int y = x;",4785 varDecl(hasInitializer(ignoringImpCasts(4786 declRefExpr(to(varDecl(hasName("x")))))))));4787 // This test creates an implict cast from int to char.4788 EXPECT_TRUE(matches("char x = 0;",4789 varDecl(hasInitializer(ignoringImpCasts(4790 integerLiteral(equals(0)))))));4791}4792 4793TEST(IgnoringImpCasts, DoesNotMatchIncorrectly) {4794 // These tests verify that ignoringImpCasts does not match if the inner4795 // matcher does not match.4796 // Note that the first test creates an implicit const cast.4797 EXPECT_TRUE(notMatches("int x; const int y = x;",4798 varDecl(hasInitializer(ignoringImpCasts(4799 unless(anything()))))));4800 EXPECT_TRUE(notMatches("int x; int y = x;",4801 varDecl(hasInitializer(ignoringImpCasts(4802 unless(anything()))))));4803 4804 // These tests verify that ignoringImplictCasts does not look through explicit4805 // casts or parentheses.4806 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",4807 varDecl(hasInitializer(ignoringImpCasts(4808 integerLiteral())))));4809 EXPECT_TRUE(notMatches(4810 "int i = (0);",4811 traverse(TK_AsIs,4812 varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))))));4813 EXPECT_TRUE(notMatches("float i = (float)0;",4814 varDecl(hasInitializer(ignoringImpCasts(4815 integerLiteral())))));4816 EXPECT_TRUE(notMatches("float i = float(0);",4817 varDecl(hasInitializer(ignoringImpCasts(4818 integerLiteral())))));4819}4820 4821TEST(IgnoringImpCasts, MatchesWithoutImpCasts) {4822 // This test verifies that expressions that do not have implicit casts4823 // still match the inner matcher.4824 EXPECT_TRUE(matches("int x = 0; int &y = x;",4825 varDecl(hasInitializer(ignoringImpCasts(4826 declRefExpr(to(varDecl(hasName("x")))))))));4827}4828 4829TEST(IgnoringParenCasts, MatchesParenCasts) {4830 // This test checks that ignoringParenCasts matches when parentheses and/or4831 // casts are present and its inner matcher alone does not match.4832 EXPECT_TRUE(matches("int x = (0);",4833 varDecl(hasInitializer(ignoringParenCasts(4834 integerLiteral(equals(0)))))));4835 EXPECT_TRUE(matches("int x = (((((0)))));",4836 varDecl(hasInitializer(ignoringParenCasts(4837 integerLiteral(equals(0)))))));4838 4839 // This test creates an implict cast from int to char in addition to the4840 // parentheses.4841 EXPECT_TRUE(matches("char x = (0);",4842 varDecl(hasInitializer(ignoringParenCasts(4843 integerLiteral(equals(0)))))));4844 4845 EXPECT_TRUE(matches("char x = (char)0;",4846 varDecl(hasInitializer(ignoringParenCasts(4847 integerLiteral(equals(0)))))));4848 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",4849 varDecl(hasInitializer(ignoringParenCasts(4850 integerLiteral(equals(0)))))));4851}4852 4853TEST(IgnoringParenCasts, MatchesWithoutParenCasts) {4854 // This test verifies that expressions that do not have any casts still match.4855 EXPECT_TRUE(matches("int x = 0;",4856 varDecl(hasInitializer(ignoringParenCasts(4857 integerLiteral(equals(0)))))));4858}4859 4860TEST(IgnoringParenCasts, DoesNotMatchIncorrectly) {4861 // These tests verify that ignoringImpCasts does not match if the inner4862 // matcher does not match.4863 EXPECT_TRUE(notMatches("int x = ((0));",4864 varDecl(hasInitializer(ignoringParenCasts(4865 unless(anything()))))));4866 4867 // This test creates an implicit cast from int to char in addition to the4868 // parentheses.4869 EXPECT_TRUE(notMatches("char x = ((0));",4870 varDecl(hasInitializer(ignoringParenCasts(4871 unless(anything()))))));4872 4873 EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",4874 varDecl(hasInitializer(ignoringParenCasts(4875 unless(anything()))))));4876}4877 4878TEST(IgnoringParenAndImpCasts, MatchesParenImpCasts) {4879 // This test checks that ignoringParenAndImpCasts matches when4880 // parentheses and/or implicit casts are present and its inner matcher alone4881 // does not match.4882 // Note that this test creates an implicit const cast.4883 EXPECT_TRUE(matches("int x = 0; const int y = x;",4884 varDecl(hasInitializer(ignoringParenImpCasts(4885 declRefExpr(to(varDecl(hasName("x")))))))));4886 // This test creates an implicit cast from int to char.4887 EXPECT_TRUE(matches("const char x = (0);",4888 varDecl(hasInitializer(ignoringParenImpCasts(4889 integerLiteral(equals(0)))))));4890}4891 4892TEST(IgnoringParenAndImpCasts, MatchesWithoutParenImpCasts) {4893 // This test verifies that expressions that do not have parentheses or4894 // implicit casts still match.4895 EXPECT_TRUE(matches("int x = 0; int &y = x;",4896 varDecl(hasInitializer(ignoringParenImpCasts(4897 declRefExpr(to(varDecl(hasName("x")))))))));4898 EXPECT_TRUE(matches("int x = 0;",4899 varDecl(hasInitializer(ignoringParenImpCasts(4900 integerLiteral(equals(0)))))));4901}4902 4903TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {4904 // These tests verify that ignoringParenImpCasts does not match if4905 // the inner matcher does not match.4906 // This test creates an implicit cast.4907 EXPECT_TRUE(notMatches("char c = ((3));",4908 varDecl(hasInitializer(ignoringParenImpCasts(4909 unless(anything()))))));4910 // These tests verify that ignoringParenAndImplictCasts does not look4911 // through explicit casts.4912 EXPECT_TRUE(notMatches("float y = (float(0));",4913 varDecl(hasInitializer(ignoringParenImpCasts(4914 integerLiteral())))));4915 EXPECT_TRUE(notMatches("float y = (float)0;",4916 varDecl(hasInitializer(ignoringParenImpCasts(4917 integerLiteral())))));4918 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",4919 varDecl(hasInitializer(ignoringParenImpCasts(4920 integerLiteral())))));4921}4922 4923TEST(HasSourceExpression, MatchesImplicitCasts) {4924 EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"4925 "void r() {string a_string; URL url = a_string; }",4926 traverse(TK_AsIs, implicitCastExpr(hasSourceExpression(4927 cxxConstructExpr())))));4928}4929 4930TEST(HasSourceExpression, MatchesExplicitCasts) {4931 EXPECT_TRUE(4932 matches("float x = static_cast<float>(42);",4933 traverse(TK_AsIs, explicitCastExpr(hasSourceExpression(4934 hasDescendant(expr(integerLiteral())))))));4935}4936 4937TEST(UsingDeclaration, MatchesSpecificTarget) {4938 EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",4939 usingDecl(hasAnyUsingShadowDecl(4940 hasTargetDecl(functionDecl())))));4941 EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",4942 usingDecl(hasAnyUsingShadowDecl(4943 hasTargetDecl(functionDecl())))));4944}4945 4946TEST(UsingDeclaration, ThroughUsingDeclaration) {4947 EXPECT_TRUE(matches(4948 "namespace a { void f(); } using a::f; void g() { f(); }",4949 declRefExpr(throughUsingDecl(anything()))));4950 EXPECT_TRUE(notMatches(4951 "namespace a { void f(); } using a::f; void g() { a::f(); }",4952 declRefExpr(throughUsingDecl(anything()))));4953}4954 4955TEST(SingleDecl, IsSingleDecl) {4956 StatementMatcher SingleDeclStmt =4957 declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));4958 EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt));4959 EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt));4960 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",4961 SingleDeclStmt));4962}4963 4964TEST(DeclStmt, ContainsDeclaration) {4965 DeclarationMatcher MatchesInit = varDecl(hasInitializer(anything()));4966 4967 EXPECT_TRUE(matches("void f() {int a = 4;}",4968 declStmt(containsDeclaration(0, MatchesInit))));4969 EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",4970 declStmt(containsDeclaration(0, MatchesInit),4971 containsDeclaration(1, MatchesInit))));4972 unsigned WrongIndex = 42;4973 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",4974 declStmt(containsDeclaration(WrongIndex,4975 MatchesInit))));4976}4977 4978TEST(SwitchCase, MatchesEachCase) {4979 EXPECT_TRUE(notMatches("void x() { switch(42); }",4980 switchStmt(forEachSwitchCase(caseStmt()))));4981 EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",4982 switchStmt(forEachSwitchCase(caseStmt()))));4983 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",4984 switchStmt(forEachSwitchCase(caseStmt()))));4985 EXPECT_TRUE(notMatches(4986 "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",4987 ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));4988 EXPECT_TRUE(matches(4989 "void x() { switch(42) { case 1+1: case 4:; } }",4990 traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(4991 constantExpr(has(integerLiteral())))))))));4992 EXPECT_TRUE(notMatches(4993 "void x() { switch(42) { case 1+1: case 2+2:; } }",4994 traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(4995 constantExpr(has(integerLiteral())))))))));4996 EXPECT_TRUE(notMatches(4997 "void x() { switch(42) { case 1 ... 2:; } }",4998 traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(4999 constantExpr(has(integerLiteral())))))))));5000 EXPECT_TRUE(matchAndVerifyResultTrue(5001 "void x() { switch (42) { case 1: case 2: case 3: default:; } }",5002 switchStmt(forEachSwitchCase(caseStmt().bind("x"))),5003 std::make_unique<VerifyIdIsBoundTo<CaseStmt>>("x", 3)));5004}5005 5006TEST(Declaration, HasExplicitSpecifier) {5007 5008 EXPECT_TRUE(notMatches("void f();",5009 functionDecl(hasExplicitSpecifier(constantExpr())),5010 langCxx20OrLater()));5011 EXPECT_TRUE(5012 notMatches("template<bool b> struct S { explicit operator int(); };",5013 cxxConversionDecl(5014 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),5015 langCxx20OrLater()));5016 EXPECT_TRUE(5017 notMatches("template<bool b> struct S { explicit(b) operator int(); };",5018 cxxConversionDecl(5019 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),5020 langCxx20OrLater()));5021 EXPECT_TRUE(5022 matches("struct S { explicit(true) operator int(); };",5023 traverse(TK_AsIs, cxxConversionDecl(hasExplicitSpecifier(5024 constantExpr(has(cxxBoolLiteral()))))),5025 langCxx20OrLater()));5026 EXPECT_TRUE(5027 matches("struct S { explicit(false) operator int(); };",5028 traverse(TK_AsIs, cxxConversionDecl(hasExplicitSpecifier(5029 constantExpr(has(cxxBoolLiteral()))))),5030 langCxx20OrLater()));5031 EXPECT_TRUE(5032 notMatches("template<bool b> struct S { explicit(b) S(int); };",5033 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(5034 constantExpr(has(cxxBoolLiteral()))))),5035 langCxx20OrLater()));5036 EXPECT_TRUE(5037 matches("struct S { explicit(true) S(int); };",5038 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(5039 constantExpr(has(cxxBoolLiteral()))))),5040 langCxx20OrLater()));5041 EXPECT_TRUE(5042 matches("struct S { explicit(false) S(int); };",5043 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(5044 constantExpr(has(cxxBoolLiteral()))))),5045 langCxx20OrLater()));5046 EXPECT_TRUE(5047 notMatches("template<typename T> struct S { S(int); };"5048 "template<bool b = true> explicit(b) S(int) -> S<int>;",5049 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(5050 constantExpr(has(cxxBoolLiteral()))))),5051 langCxx20OrLater()));5052 EXPECT_TRUE(5053 matches("template<typename T> struct S { S(int); };"5054 "explicit(true) S(int) -> S<int>;",5055 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(5056 constantExpr(has(cxxBoolLiteral()))))),5057 langCxx20OrLater()));5058 EXPECT_TRUE(5059 matches("template<typename T> struct S { S(int); };"5060 "explicit(false) S(int) -> S<int>;",5061 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(5062 constantExpr(has(cxxBoolLiteral()))))),5063 langCxx20OrLater()));5064}5065 5066TEST(ForEachConstructorInitializer, MatchesInitializers) {5067 EXPECT_TRUE(matches(5068 "struct X { X() : i(42), j(42) {} int i, j; };",5069 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));5070}5071 5072TEST(LambdaCapture, InvalidLambdaCapture) {5073 // not crash5074 EXPECT_FALSE(matches(5075 R"(int main() {5076 struct A { A()=default; A(A const&)=delete; };5077 A a; [a]() -> void {}();5078 return 0;5079 })",5080 traverse(TK_IgnoreUnlessSpelledInSource,5081 lambdaExpr(has(lambdaCapture()))),5082 langCxx11OrLater()));5083}5084 5085TEST(ForEachLambdaCapture, MatchesCaptures) {5086 EXPECT_TRUE(matches(5087 "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",5088 lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));5089 auto matcher = lambdaExpr(forEachLambdaCapture(5090 lambdaCapture(capturesVar(varDecl(hasType(isInteger())))).bind("LC")));5091 EXPECT_TRUE(matchAndVerifyResultTrue(5092 "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",5093 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5094 EXPECT_TRUE(matchAndVerifyResultTrue(5095 "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "5096 "z; }; }",5097 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5098}5099 5100TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) {5101 auto matcher =5102 traverse(TK_IgnoreUnlessSpelledInSource,5103 lambdaExpr(forEachLambdaCapture(5104 lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))5105 .bind("LC"))));5106 EXPECT_TRUE(5107 notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",5108 matcher, langCxx11OrLater()));5109 EXPECT_TRUE(5110 notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",5111 matcher, langCxx11OrLater()));5112 EXPECT_TRUE(matchAndVerifyResultTrue(5113 R"cc(5114 int main() {5115 int x, y;5116 float z;5117 auto f = [=, &y]() { return x + y + z; };5118 }5119 )cc",5120 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));5121}5122 5123TEST(ForEachLambdaCapture, MatchImplicitCapturesOnly) {5124 auto matcher =5125 lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));5126 EXPECT_TRUE(matchAndVerifyResultTrue(5127 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",5128 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5129 EXPECT_TRUE(matchAndVerifyResultTrue(5130 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",5131 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));5132}5133 5134TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) {5135 auto matcher = lambdaExpr(5136 forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));5137 EXPECT_TRUE(matchAndVerifyResultTrue(5138 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",5139 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));5140 EXPECT_TRUE(matchAndVerifyResultTrue(5141 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",5142 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));5143}5144 5145TEST(ForEach, BindsOneNode) {5146 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",5147 recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),5148 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("x", 1)));5149}5150 5151TEST(ForEach, BindsMultipleNodes) {5152 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",5153 recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),5154 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 3)));5155}5156 5157TEST(ForEach, BindsRecursiveCombinations) {5158 EXPECT_TRUE(matchAndVerifyResultTrue(5159 "class C { class D { int x; int y; }; class E { int y; int z; }; };",5160 recordDecl(hasName("C"),5161 forEach(recordDecl(forEach(fieldDecl().bind("f"))))),5162 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 4)));5163}5164 5165TEST(ForEach, DoesNotIgnoreImplicit) {5166 StringRef Code = R"cpp(5167void foo()5168{5169 int i = 0;5170 int b = 4;5171 i < b;5172}5173)cpp";5174 EXPECT_TRUE(matchAndVerifyResultFalse(5175 Code, binaryOperator(forEach(declRefExpr().bind("dre"))),5176 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 0)));5177 5178 EXPECT_TRUE(matchAndVerifyResultTrue(5179 Code,5180 binaryOperator(forEach(5181 implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))),5182 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));5183 5184 EXPECT_TRUE(matchAndVerifyResultTrue(5185 Code,5186 binaryOperator(5187 forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))),5188 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));5189 5190 EXPECT_TRUE(matchAndVerifyResultTrue(5191 Code,5192 traverse(TK_IgnoreUnlessSpelledInSource,5193 binaryOperator(forEach(declRefExpr().bind("dre")))),5194 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));5195}5196 5197TEST(ForEachDescendant, BindsOneNode) {5198 EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",5199 recordDecl(hasName("C"),5200 forEachDescendant(fieldDecl(hasName("x")).bind("x"))),5201 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("x", 1)));5202}5203 5204TEST(ForEachDescendant, NestedForEachDescendant) {5205 DeclarationMatcher m = recordDecl(5206 isDefinition(), decl().bind("x"), hasName("C"));5207 EXPECT_TRUE(matchAndVerifyResultTrue(5208 "class A { class B { class C {}; }; };",5209 recordDecl(hasName("A"), anyOf(m, forEachDescendant(m))),5210 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", "C")));5211 5212 // Check that a partial match of 'm' that binds 'x' in the5213 // first part of anyOf(m, anything()) will not overwrite the5214 // binding created by the earlier binding in the hasDescendant.5215 EXPECT_TRUE(matchAndVerifyResultTrue(5216 "class A { class B { class C {}; }; };",5217 recordDecl(hasName("A"), allOf(hasDescendant(m), anyOf(m, anything()))),5218 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", "C")));5219}5220 5221TEST(ForEachDescendant, BindsMultipleNodes) {5222 EXPECT_TRUE(matchAndVerifyResultTrue(5223 "class C { class D { int x; int y; }; "5224 " class E { class F { int y; int z; }; }; };",5225 recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),5226 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 4)));5227}5228 5229TEST(ForEachDescendant, BindsRecursiveCombinations) {5230 EXPECT_TRUE(matchAndVerifyResultTrue(5231 "class C { class D { "5232 " class E { class F { class G { int y; int z; }; }; }; }; };",5233 recordDecl(hasName("C"), forEachDescendant(recordDecl(5234 forEachDescendant(fieldDecl().bind("f"))))),5235 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 8)));5236}5237 5238TEST(ForEachDescendant, BindsCombinations) {5239 EXPECT_TRUE(matchAndVerifyResultTrue(5240 "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "5241 "(true) {} }",5242 compoundStmt(forEachDescendant(ifStmt().bind("if")),5243 forEachDescendant(whileStmt().bind("while"))),5244 std::make_unique<VerifyIdIsBoundTo<IfStmt>>("if", 6)));5245}5246 5247TEST(ForEachTemplateArgument, OnFunctionDecl) {5248 const std::string Code = R"(5249template <typename T, typename U> void f(T, U) {}5250void test() {5251 int I = 1;5252 bool B = false;5253 f(I, B);5254})";5255 EXPECT_TRUE(matches(5256 Code, functionDecl(forEachTemplateArgument(refersToType(builtinType()))),5257 langCxx11OrLater()));5258 auto matcher =5259 functionDecl(forEachTemplateArgument(5260 templateArgument(refersToType(builtinType().bind("BT")))5261 .bind("TA")))5262 .bind("FN");5263 5264 EXPECT_TRUE(matchAndVerifyResultTrue(5265 Code, matcher,5266 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("FN", 2)));5267 EXPECT_TRUE(matchAndVerifyResultTrue(5268 Code, matcher,5269 std::make_unique<VerifyIdIsBoundTo<TemplateArgument>>("TA", 2)));5270 EXPECT_TRUE(matchAndVerifyResultTrue(5271 Code, matcher,5272 std::make_unique<VerifyIdIsBoundTo<BuiltinType>>("BT", 2)));5273}5274 5275TEST(ForEachTemplateArgument, OnClassTemplateSpecialization) {5276 const std::string Code = R"(5277template <typename T, unsigned N, unsigned M>5278struct Matrix {};5279 5280static constexpr unsigned R = 2;5281 5282Matrix<int, R * 2, R * 4> M;5283)";5284 EXPECT_TRUE(matches(5285 Code, templateSpecializationType(forEachTemplateArgument(isExpr(expr()))),5286 langCxx11OrLater()));5287 auto matcher = templateSpecializationType(5288 forEachTemplateArgument(5289 templateArgument(isExpr(expr().bind("E"))).bind("TA")))5290 .bind("TST");5291 5292 EXPECT_TRUE(matchAndVerifyResultTrue(5293 Code, matcher,5294 std::make_unique<VerifyIdIsBoundTo<TemplateSpecializationType>>("TST",5295 2)));5296 EXPECT_TRUE(matchAndVerifyResultTrue(5297 Code, matcher,5298 std::make_unique<VerifyIdIsBoundTo<TemplateArgument>>("TA", 2)));5299 EXPECT_TRUE(matchAndVerifyResultTrue(5300 Code, matcher, std::make_unique<VerifyIdIsBoundTo<Expr>>("E", 2)));5301}5302 5303TEST(Has, DoesNotDeleteBindings) {5304 EXPECT_TRUE(matchAndVerifyResultTrue(5305 "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),5306 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5307}5308 5309TEST(TemplateArgumentLoc, Matches) {5310 EXPECT_TRUE(matchAndVerifyResultTrue(5311 R"cpp(5312 template <typename A, int B, template <typename> class C> class X {};5313 class A {};5314 const int B = 42;5315 template <typename> class C {};5316 X<A, B, C> x;5317 )cpp",5318 templateArgumentLoc().bind("x"),5319 std::make_unique<VerifyIdIsBoundTo<TemplateArgumentLoc>>("x", 3)));5320}5321 5322TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {5323 // Those matchers cover all the cases where an inner matcher is called5324 // and there is not a 1:1 relationship between the match of the outer5325 // matcher and the match of the inner matcher.5326 // The pattern to look for is:5327 // ... return InnerMatcher.matches(...); ...5328 // In which case no special handling is needed.5329 //5330 // On the other hand, if there are multiple alternative matches5331 // (for example forEach*) or matches might be discarded (for example has*)5332 // the implementation must make sure that the discarded matches do not5333 // affect the bindings.5334 // When new such matchers are added, add a test here that:5335 // - matches a simple node, and binds it as the first thing in the matcher:5336 // recordDecl(decl().bind("x"), hasName("X")))5337 // - uses the matcher under test afterwards in a way that not the first5338 // alternative is matched; for anyOf, that means the first branch5339 // would need to return false; for hasAncestor, it means that not5340 // the direct parent matches the inner matcher.5341 5342 EXPECT_TRUE(matchAndVerifyResultTrue(5343 "class X { int y; };",5344 recordDecl(5345 recordDecl().bind("x"), hasName("::X"),5346 anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),5347 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));5348 EXPECT_TRUE(matchAndVerifyResultTrue(5349 "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),5350 anyOf(unless(anything()), anything())),5351 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));5352 EXPECT_TRUE(matchAndVerifyResultTrue(5353 "template<typename T1, typename T2> class X {}; X<float, int> x;",5354 classTemplateSpecializationDecl(5355 decl().bind("x"),5356 hasAnyTemplateArgument(refersToType(asString("int")))),5357 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5358 EXPECT_TRUE(matchAndVerifyResultTrue(5359 "class X { void f(); void g(); };",5360 cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),5361 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5362 EXPECT_TRUE(matchAndVerifyResultTrue(5363 "class X { X() : a(1), b(2) {} double a; int b; };",5364 recordDecl(decl().bind("x"),5365 has(cxxConstructorDecl(5366 hasAnyConstructorInitializer(forField(hasName("b")))))),5367 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5368 EXPECT_TRUE(matchAndVerifyResultTrue(5369 "void x(int, int) { x(0, 42); }",5370 callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),5371 std::make_unique<VerifyIdIsBoundTo<Expr>>("x", 1)));5372 EXPECT_TRUE(matchAndVerifyResultTrue(5373 "void x(int, int y) {}",5374 functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),5375 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5376 EXPECT_TRUE(matchAndVerifyResultTrue(5377 "void x() { return; if (true) {} }",5378 functionDecl(decl().bind("x"),5379 has(compoundStmt(hasAnySubstatement(ifStmt())))),5380 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5381 EXPECT_TRUE(matchAndVerifyResultTrue(5382 "namespace X { void b(int); void b(); }"5383 "using X::b;",5384 usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(5385 functionDecl(parameterCountIs(1))))),5386 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5387 EXPECT_TRUE(matchAndVerifyResultTrue(5388 "class A{}; class B{}; class C : B, A {};",5389 cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A"),5390 unless(isImplicit())),5391 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5392 EXPECT_TRUE(matchAndVerifyResultTrue(5393 "class A{}; typedef A B; typedef A C; typedef A D;"5394 "class E : A {};",5395 cxxRecordDecl(decl().bind("x"), isDerivedFrom("C"), unless(isImplicit())),5396 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5397 EXPECT_TRUE(matchAndVerifyResultTrue(5398 "class A { class B { void f() {} }; };",5399 functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),5400 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5401 EXPECT_TRUE(matchAndVerifyResultTrue(5402 "template <typename T> struct A { struct B {"5403 " void f() { if(true) {} }"5404 "}; };"5405 "void t() { A<int>::B b; b.f(); }",5406 ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),5407 std::make_unique<VerifyIdIsBoundTo<Stmt>>("x", 2)));5408 EXPECT_TRUE(matchAndVerifyResultTrue(5409 "class A {};",5410 recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),5411 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5412 EXPECT_TRUE(matchAndVerifyResultTrue(5413 "class A { A() : s(), i(42) {} const char *s; int i; };",5414 cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),5415 forEachConstructorInitializer(forField(hasName("i")))),5416 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));5417}5418 5419TEST(ForEachDescendant, BindsCorrectNodes) {5420 EXPECT_TRUE(matchAndVerifyResultTrue(5421 "class C { void f(); int i; };",5422 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),5423 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("decl", 1)));5424 EXPECT_TRUE(matchAndVerifyResultTrue(5425 "class C { void f() {} int i; };",5426 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),5427 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("decl", 1)));5428}5429 5430TEST(FindAll, BindsNodeOnMatch) {5431 EXPECT_TRUE(matchAndVerifyResultTrue(5432 "class A {};",5433 recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),5434 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("v", 1)));5435}5436 5437TEST(FindAll, BindsDescendantNodeOnMatch) {5438 EXPECT_TRUE(matchAndVerifyResultTrue(5439 "class A { int a; int b; };",5440 recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),5441 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 2)));5442}5443 5444TEST(FindAll, BindsNodeAndDescendantNodesOnOneMatch) {5445 EXPECT_TRUE(matchAndVerifyResultTrue(5446 "class A { int a; int b; };",5447 recordDecl(hasName("::A"),5448 findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),5449 fieldDecl().bind("v"))))),5450 std::make_unique<VerifyIdIsBoundTo<Decl>>("v", 3)));5451 5452 EXPECT_TRUE(matchAndVerifyResultTrue(5453 "class A { class B {}; class C {}; };",5454 recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),5455 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("v", 3)));5456}5457 5458TEST(HasAncenstor, MatchesDeclarationAncestors) {5459 EXPECT_TRUE(matches(5460 "class A { class B { class C {}; }; };",5461 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));5462}5463 5464TEST(HasAncenstor, FailsIfNoAncestorMatches) {5465 EXPECT_TRUE(notMatches(5466 "class A { class B { class C {}; }; };",5467 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));5468}5469 5470TEST(HasAncestor, MatchesDeclarationsThatGetVisitedLater) {5471 EXPECT_TRUE(matches(5472 "class A { class B { void f() { C c; } class C {}; }; };",5473 varDecl(hasName("c"), hasType(recordDecl(hasName("C"),5474 hasAncestor(recordDecl(hasName("A"))))))));5475}5476 5477TEST(HasAncenstor, MatchesStatementAncestors) {5478 EXPECT_TRUE(matches(5479 "void f() { if (true) { while (false) { 42; } } }",5480 integerLiteral(equals(42), hasAncestor(ifStmt()))));5481}5482 5483TEST(HasAncestor, DrillsThroughDifferentHierarchies) {5484 EXPECT_TRUE(matches(5485 "void f() { if (true) { int x = 42; } }",5486 integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));5487}5488 5489TEST(HasAncestor, BindsRecursiveCombinations) {5490 EXPECT_TRUE(matchAndVerifyResultTrue(5491 "class C { class D { class E { class F { int y; }; }; }; };",5492 fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),5493 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("r", 1)));5494}5495 5496TEST(HasAncestor, BindsCombinationsWithHasDescendant) {5497 EXPECT_TRUE(matchAndVerifyResultTrue(5498 "class C { class D { class E { class F { int y; }; }; }; };",5499 fieldDecl(hasAncestor(5500 decl(5501 hasDescendant(recordDecl(isDefinition(),5502 hasAncestor(recordDecl())))5503 ).bind("d")5504 )),5505 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("d", "E")));5506}5507 5508TEST(HasAncestor, MatchesClosestAncestor) {5509 EXPECT_TRUE(matchAndVerifyResultTrue(5510 "template <typename T> struct C {"5511 " void f(int) {"5512 " struct I { void g(T) { int x; } } i; i.g(42);"5513 " }"5514 "};"5515 "template struct C<int>;",5516 varDecl(hasName("x"),5517 hasAncestor(functionDecl(hasParameter(5518 0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),5519 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("f", "g", 2)));5520}5521 5522TEST(HasAncestor, MatchesInTemplateInstantiations) {5523 EXPECT_TRUE(matches(5524 "template <typename T> struct A { struct B { struct C { T t; }; }; }; "5525 "A<int>::B::C a;",5526 fieldDecl(hasType(asString("int")),5527 hasAncestor(recordDecl(hasName("A"))))));5528}5529 5530TEST(HasAncestor, MatchesInImplicitCode) {5531 EXPECT_TRUE(matches(5532 "struct X {}; struct A { A() {} X x; };",5533 cxxConstructorDecl(5534 hasAnyConstructorInitializer(withInitializer(expr(5535 hasAncestor(recordDecl(hasName("A")))))))));5536}5537 5538TEST(HasParent, MatchesOnlyParent) {5539 EXPECT_TRUE(matches(5540 "void f() { if (true) { int x = 42; } }",5541 compoundStmt(hasParent(ifStmt()))));5542 EXPECT_TRUE(notMatches(5543 "void f() { for (;;) { int x = 42; } }",5544 compoundStmt(hasParent(ifStmt()))));5545 EXPECT_TRUE(notMatches(5546 "void f() { if (true) for (;;) { int x = 42; } }",5547 compoundStmt(hasParent(ifStmt()))));5548}5549 5550TEST(MatcherMemoize, HasParentDiffersFromHas) {5551 // Test introduced after detecting a bug in memoization5552 constexpr auto code = "void f() { throw 1; }";5553 EXPECT_TRUE(notMatches(5554 code,5555 cxxThrowExpr(hasParent(expr()))));5556 EXPECT_TRUE(matches(5557 code,5558 cxxThrowExpr(has(expr()))));5559 EXPECT_TRUE(matches(5560 code,5561 cxxThrowExpr(anyOf(hasParent(expr()), has(expr())))));5562}5563 5564TEST(MatcherMemoize, HasDiffersFromHasDescendant) {5565 // Test introduced after detecting a bug in memoization5566 constexpr auto code = "void f() { throw 1+1; }";5567 EXPECT_TRUE(notMatches(5568 code,5569 cxxThrowExpr(has(integerLiteral()))));5570 EXPECT_TRUE(matches(5571 code,5572 cxxThrowExpr(hasDescendant(integerLiteral()))));5573 EXPECT_TRUE(5574 notMatches(code, cxxThrowExpr(allOf(hasDescendant(integerLiteral()),5575 has(integerLiteral())))));5576}5577TEST(HasAncestor, MatchesAllAncestors) {5578 EXPECT_TRUE(matches(5579 "template <typename T> struct C { static void f() { 42; } };"5580 "void t() { C<int>::f(); }",5581 integerLiteral(5582 equals(42),5583 allOf(5584 hasAncestor(cxxRecordDecl(isTemplateInstantiation())),5585 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));5586}5587 5588TEST(HasAncestor, ImplicitArrayCopyCtorDeclRefExpr) {5589 EXPECT_TRUE(matches("struct MyClass {\n"5590 " int c[1];\n"5591 " static MyClass Create() { return MyClass(); }\n"5592 "};",5593 declRefExpr(to(decl(hasAncestor(decl()))))));5594}5595 5596TEST(HasAncestor, AnonymousUnionMemberExpr) {5597 EXPECT_TRUE(matches("int F() {\n"5598 " union { int i; };\n"5599 " return i;\n"5600 "}\n",5601 memberExpr(member(hasAncestor(decl())))));5602 EXPECT_TRUE(matches("void f() {\n"5603 " struct {\n"5604 " struct { int a; int b; };\n"5605 " } s;\n"5606 " s.a = 4;\n"5607 "}\n",5608 memberExpr(member(hasAncestor(decl())))));5609 EXPECT_TRUE(matches("void f() {\n"5610 " struct {\n"5611 " struct { int a; int b; };\n"5612 " } s;\n"5613 " s.a = 4;\n"5614 "}\n",5615 declRefExpr(to(decl(hasAncestor(decl()))))));5616}5617TEST(HasAncestor, NonParmDependentTemplateParmVarDeclRefExpr) {5618 EXPECT_TRUE(matches("struct PartitionAllocator {\n"5619 " template<typename T>\n"5620 " static int quantizedSize(int count) {\n"5621 " return count;\n"5622 " }\n"5623 " void f() { quantizedSize<int>(10); }\n"5624 "};",5625 declRefExpr(to(decl(hasAncestor(decl()))))));5626}5627 5628TEST(HasAncestor, AddressOfExplicitSpecializationFunction) {5629 EXPECT_TRUE(matches("template <class T> void f();\n"5630 "template <> void f<int>();\n"5631 "void (*get_f())() { return f<int>; }\n",5632 declRefExpr(to(decl(hasAncestor(decl()))))));5633}5634 5635TEST(HasParent, MatchesAllParents) {5636 EXPECT_TRUE(matches(5637 "template <typename T> struct C { static void f() { 42; } };"5638 "void t() { C<int>::f(); }",5639 integerLiteral(5640 equals(42),5641 hasParent(compoundStmt(hasParent(functionDecl(5642 hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));5643 EXPECT_TRUE(5644 matches("template <typename T> struct C { static void f() { 42; } };"5645 "void t() { C<int>::f(); }",5646 integerLiteral(5647 equals(42),5648 hasParent(compoundStmt(hasParent(functionDecl(hasParent(5649 cxxRecordDecl(unless(isTemplateInstantiation()))))))))));5650 EXPECT_TRUE(matches(5651 "template <typename T> struct C { static void f() { 42; } };"5652 "void t() { C<int>::f(); }",5653 integerLiteral(equals(42),5654 hasParent(compoundStmt(5655 allOf(hasParent(functionDecl(hasParent(5656 cxxRecordDecl(isTemplateInstantiation())))),5657 hasParent(functionDecl(hasParent(cxxRecordDecl(5658 unless(isTemplateInstantiation())))))))))));5659 EXPECT_TRUE(5660 notMatches("template <typename T> struct C { static void f() {} };"5661 "void t() { C<int>::f(); }",5662 compoundStmt(hasParent(recordDecl()))));5663}5664 5665TEST(HasParent, NoDuplicateParents) {5666 class HasDuplicateParents : public BoundNodesCallback {5667 public:5668 bool run(const BoundNodes *Nodes, ASTContext *Context) override {5669 const Stmt *Node = Nodes->getNodeAs<Stmt>("node");5670 std::set<const void *> Parents;5671 for (const auto &Parent : Context->getParents(*Node)) {5672 if (!Parents.insert(Parent.getMemoizationData()).second) {5673 return true;5674 }5675 }5676 return false;5677 }5678 };5679 EXPECT_FALSE(matchAndVerifyResultTrue(5680 "template <typename T> int Foo() { return 1 + 2; }\n"5681 "int x = Foo<int>() + Foo<unsigned>();",5682 stmt().bind("node"), std::make_unique<HasDuplicateParents>()));5683}5684 5685TEST(HasAnyBase, BindsInnerBoundNodes) {5686 EXPECT_TRUE(matchAndVerifyResultTrue(5687 "struct Inner {}; struct Proxy : Inner {}; struct Main : public "5688 "Proxy {};",5689 cxxRecordDecl(hasName("Main"), unless(isImplicit()),5690 hasAnyBase(cxxBaseSpecifier(hasType(5691 cxxRecordDecl(hasName("Inner")).bind("base-class")))))5692 .bind("class"),5693 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("base-class",5694 "Inner")));5695}5696 5697TEST(TypeMatching, PointeeTypes) {5698 EXPECT_TRUE(matches("int b; int &a = b;",5699 referenceType(pointee(builtinType()))));5700 EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));5701 5702 EXPECT_TRUE(matches("int *a;",5703 loc(pointerType(pointee(builtinType())))));5704 5705 EXPECT_TRUE(matches(5706 "int const *A;",5707 pointerType(pointee(isConstQualified(), builtinType()))));5708 EXPECT_TRUE(notMatches(5709 "int *A;",5710 pointerType(pointee(isConstQualified(), builtinType()))));5711}5712 5713TEST(ElaboratedTypeNarrowing, hasQualifier) {5714 EXPECT_TRUE(matches(5715 "namespace N {"5716 " namespace M {"5717 " class D {};"5718 " }"5719 "}"5720 "N::M::D d;",5721 recordType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));5722 EXPECT_TRUE(notMatches(5723 "namespace M {"5724 " class D {};"5725 "}"5726 "M::D d;",5727 recordType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));5728 EXPECT_TRUE(notMatches("struct D {"5729 "} d;",5730 recordType(hasQualifier(nestedNameSpecifier()))));5731}5732 5733TEST(NNS, BindsNestedNameSpecifiers) {5734 EXPECT_TRUE(matchAndVerifyResultTrue(5735 "namespace ns { struct E { struct B {}; }; } ns::E::B b;",5736 nestedNameSpecifier(specifiesType(asString("ns::E"))).bind("nns"),5737 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("nns",5738 "ns::E::")));5739}5740 5741TEST(NNS, BindsNestedNameSpecifierLocs) {5742 EXPECT_TRUE(matchAndVerifyResultTrue(5743 "namespace ns { struct B {}; } ns::B b;",5744 loc(nestedNameSpecifier()).bind("loc"),5745 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("loc", 1)));5746}5747 5748TEST(NNS, DescendantsOfNestedNameSpecifiers) {5749 StringRef Fragment =5750 "namespace a { struct A { struct B { struct C {}; }; }; };"5751 "void f() { a::A::B::C c; }";5752 EXPECT_TRUE(matches(5753 Fragment, nestedNameSpecifier(specifiesType(asString("a::A::B")),5754 hasDescendant(nestedNameSpecifier(5755 specifiesNamespace(hasName("a")))))));5756 EXPECT_TRUE(notMatches(5757 Fragment, nestedNameSpecifier(specifiesType(asString("a::A::B")),5758 has(nestedNameSpecifier(5759 specifiesNamespace(hasName("a")))))));5760 EXPECT_TRUE(matches(5761 Fragment, nestedNameSpecifier(specifiesType(asString("a::A")),5762 has(nestedNameSpecifier(5763 specifiesNamespace(hasName("a")))))));5764 5765 // Not really useful because a NestedNameSpecifier can af at most one child,5766 // but to complete the interface.5767 EXPECT_TRUE(matchAndVerifyResultTrue(5768 Fragment,5769 nestedNameSpecifier(specifiesType(asString("a::A::B")),5770 forEach(nestedNameSpecifier().bind("x"))),5771 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 1)));5772}5773 5774TEST(NNS, NestedNameSpecifiersAsDescendants) {5775 StringRef Fragment =5776 "namespace a { struct A { struct B { struct C {}; }; }; };"5777 "void f() { a::A::B::C c; }";5778 EXPECT_TRUE(matches(Fragment, decl(hasDescendant(nestedNameSpecifier(5779 specifiesType(asString("a::A")))))));5780 EXPECT_TRUE(matchAndVerifyResultTrue(5781 Fragment,5782 functionDecl(hasName("f"),5783 forEachDescendant(nestedNameSpecifier().bind("x"))),5784 // Nested names: a, a::A and a::A::B.5785 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 3)));5786}5787 5788TEST(NNSLoc, DescendantsOfNestedNameSpecifierLocs) {5789 StringRef Fragment =5790 "namespace a { struct A { struct B { struct C {}; }; }; };"5791 "void f() { a::A::B::C c; }";5792 EXPECT_TRUE(matches(Fragment, nestedNameSpecifierLoc(5793 loc(specifiesType(asString("a::A::B"))),5794 hasDescendant(loc(nestedNameSpecifier(5795 specifiesNamespace(hasName("a"))))))));5796 EXPECT_TRUE(notMatches(5797 Fragment,5798 nestedNameSpecifierLoc(5799 loc(specifiesType(asString("a::A::B"))),5800 has(loc(nestedNameSpecifier(specifiesNamespace(hasName("a"))))))));5801 EXPECT_TRUE(matches(5802 Fragment,5803 nestedNameSpecifierLoc(5804 loc(specifiesType(asString("a::A"))),5805 has(loc(nestedNameSpecifier(specifiesNamespace(hasName("a"))))))));5806 5807 EXPECT_TRUE(matchAndVerifyResultTrue(5808 Fragment,5809 nestedNameSpecifierLoc(loc(specifiesType(asString("a::A::B"))),5810 forEach(nestedNameSpecifierLoc().bind("x"))),5811 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 1)));5812}5813 5814TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) {5815 StringRef Fragment =5816 "namespace a { struct A { struct B { struct C {}; }; }; };"5817 "void f() { a::A::B::C c; }";5818 EXPECT_TRUE(matches(Fragment, decl(hasDescendant(loc(nestedNameSpecifier(5819 specifiesType(asString("a::A"))))))));5820 EXPECT_TRUE(matchAndVerifyResultTrue(5821 Fragment,5822 functionDecl(hasName("f"),5823 forEachDescendant(nestedNameSpecifierLoc().bind("x"))),5824 // Nested names: a, a::A and a::A::B.5825 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 3)));5826}5827 5828TEST(Attr, AttrsAsDescendants) {5829 StringRef Fragment = "namespace a { struct [[clang::warn_unused_result]] "5830 "F{}; [[noreturn]] void foo(); }";5831 EXPECT_TRUE(matches(Fragment, namespaceDecl(hasDescendant(attr()))));5832 EXPECT_TRUE(matchAndVerifyResultTrue(5833 Fragment,5834 namespaceDecl(hasName("a"),5835 forEachDescendant(decl(5836 hasDescendant(attr(unless(isImplicit())).bind("x")),5837 unless(isImplicit())))),5838 std::make_unique<VerifyIdIsBoundTo<Attr>>("x", 2)));5839}5840 5841TEST(Attr, ParentsOfAttrs) {5842 StringRef Fragment =5843 "namespace a { struct [[clang::warn_unused_result]] F{}; }";5844 EXPECT_TRUE(matches(Fragment, attr(hasAncestor(namespaceDecl()))));5845}5846 5847template <typename T> class VerifyMatchOnNode : public BoundNodesCallback {5848public:5849 VerifyMatchOnNode(StringRef Id, const internal::Matcher<T> &InnerMatcher,5850 StringRef InnerId)5851 : Id(Id), InnerMatcher(InnerMatcher), InnerId(InnerId) {}5852 5853 bool run(const BoundNodes *Nodes, ASTContext *Context) override {5854 const T *Node = Nodes->getNodeAs<T>(Id);5855 return selectFirst<T>(InnerId, match(InnerMatcher, *Node, *Context)) !=5856 nullptr;5857 }5858 5859private:5860 std::string Id;5861 internal::Matcher<T> InnerMatcher;5862 std::string InnerId;5863};5864 5865TEST(MatchFinder, CanMatchDeclarationsRecursively) {5866 EXPECT_TRUE(matchAndVerifyResultTrue(5867 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5868 std::make_unique<VerifyMatchOnNode<Decl>>(5869 "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),5870 "Y")));5871 EXPECT_TRUE(matchAndVerifyResultFalse(5872 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5873 std::make_unique<VerifyMatchOnNode<Decl>>(5874 "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),5875 "Z")));5876}5877 5878TEST(MatchFinder, CanMatchStatementsRecursively) {5879 EXPECT_TRUE(matchAndVerifyResultTrue(5880 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),5881 std::make_unique<VerifyMatchOnNode<Stmt>>(5882 "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));5883 EXPECT_TRUE(matchAndVerifyResultFalse(5884 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),5885 std::make_unique<VerifyMatchOnNode<Stmt>>(5886 "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));5887}5888 5889TEST(MatchFinder, CanMatchSingleNodesRecursively) {5890 EXPECT_TRUE(matchAndVerifyResultTrue(5891 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5892 std::make_unique<VerifyMatchOnNode<Decl>>(5893 "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));5894 EXPECT_TRUE(matchAndVerifyResultFalse(5895 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),5896 std::make_unique<VerifyMatchOnNode<Decl>>(5897 "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));5898}5899 5900TEST(StatementMatcher, HasReturnValue) {5901 StatementMatcher RetVal = returnStmt(hasReturnValue(binaryOperator()));5902 EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal));5903 EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal));5904 EXPECT_FALSE(matches("void F() { return; }", RetVal));5905}5906 5907TEST(StatementMatcher, ForFunction) {5908 StringRef CppString1 = "struct PosVec {"5909 " PosVec& operator=(const PosVec&) {"5910 " auto x = [] { return 1; };"5911 " return *this;"5912 " }"5913 "};";5914 StringRef CppString2 = "void F() {"5915 " struct S {"5916 " void F2() {"5917 " return;"5918 " }"5919 " };"5920 "}";5921 EXPECT_TRUE(5922 matches(5923 CppString1,5924 returnStmt(forFunction(hasName("operator=")),5925 has(unaryOperator(hasOperatorName("*"))))));5926 EXPECT_TRUE(5927 notMatches(5928 CppString1,5929 returnStmt(forFunction(hasName("operator=")),5930 has(integerLiteral()))));5931 EXPECT_TRUE(5932 matches(5933 CppString1,5934 returnStmt(forFunction(hasName("operator()")),5935 has(integerLiteral()))));5936 EXPECT_TRUE(matches(CppString2, returnStmt(forFunction(hasName("F2")))));5937 EXPECT_TRUE(notMatches(CppString2, returnStmt(forFunction(hasName("F")))));5938}5939 5940TEST(StatementMatcher, ForCallable) {5941 // These tests are copied over from the forFunction() test above.5942 StringRef CppString1 = "struct PosVec {"5943 " PosVec& operator=(const PosVec&) {"5944 " auto x = [] { return 1; };"5945 " return *this;"5946 " }"5947 "};";5948 StringRef CppString2 = "void F() {"5949 " struct S {"5950 " void F2() {"5951 " return;"5952 " }"5953 " };"5954 "}";5955 5956 EXPECT_TRUE(5957 matches(5958 CppString1,5959 returnStmt(forCallable(functionDecl(hasName("operator="))),5960 has(unaryOperator(hasOperatorName("*"))))));5961 EXPECT_TRUE(5962 notMatches(5963 CppString1,5964 returnStmt(forCallable(functionDecl(hasName("operator="))),5965 has(integerLiteral()))));5966 EXPECT_TRUE(5967 matches(5968 CppString1,5969 returnStmt(forCallable(functionDecl(hasName("operator()"))),5970 has(integerLiteral()))));5971 EXPECT_TRUE(matches(CppString2,5972 returnStmt(forCallable(functionDecl(hasName("F2"))))));5973 EXPECT_TRUE(notMatches(CppString2,5974 returnStmt(forCallable(functionDecl(hasName("F"))))));5975 5976 StringRef CodeWithDeepCallExpr = R"cpp(5977void Other();5978void Function() {5979 {5980 (5981 Other()5982 );5983 }5984}5985)cpp";5986 auto ForCallableFirst =5987 callExpr(forCallable(functionDecl(hasName("Function"))),5988 callee(functionDecl(hasName("Other")).bind("callee")))5989 .bind("call");5990 auto ForCallableSecond =5991 callExpr(callee(functionDecl(hasName("Other")).bind("callee")),5992 forCallable(functionDecl(hasName("Function"))))5993 .bind("call");5994 EXPECT_TRUE(matchAndVerifyResultTrue(5995 CodeWithDeepCallExpr, ForCallableFirst,5996 std::make_unique<VerifyIdIsBoundTo<CallExpr>>("call")));5997 EXPECT_TRUE(matchAndVerifyResultTrue(5998 CodeWithDeepCallExpr, ForCallableFirst,5999 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("callee")));6000 EXPECT_TRUE(matchAndVerifyResultTrue(6001 CodeWithDeepCallExpr, ForCallableSecond,6002 std::make_unique<VerifyIdIsBoundTo<CallExpr>>("call")));6003 EXPECT_TRUE(matchAndVerifyResultTrue(6004 CodeWithDeepCallExpr, ForCallableSecond,6005 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("callee")));6006 6007 // These tests are specific to forCallable().6008 StringRef ObjCString1 = "@interface I"6009 "-(void) foo;"6010 "@end"6011 "@implementation I"6012 "-(void) foo {"6013 " void (^block)() = ^{ 0x2b | ~0x2b; };"6014 "}"6015 "@end";6016 6017 EXPECT_TRUE(6018 matchesObjC(6019 ObjCString1,6020 binaryOperator(forCallable(blockDecl()))));6021 6022 EXPECT_TRUE(6023 notMatchesObjC(6024 ObjCString1,6025 binaryOperator(forCallable(objcMethodDecl()))));6026 6027 StringRef ObjCString2 = "@interface I"6028 "-(void) foo;"6029 "@end"6030 "@implementation I"6031 "-(void) foo {"6032 " 0x2b | ~0x2b;"6033 " void (^block)() = ^{};"6034 "}"6035 "@end";6036 6037 EXPECT_TRUE(6038 matchesObjC(6039 ObjCString2,6040 binaryOperator(forCallable(objcMethodDecl()))));6041 6042 EXPECT_TRUE(6043 notMatchesObjC(6044 ObjCString2,6045 binaryOperator(forCallable(blockDecl()))));6046}6047 6048namespace {6049class ForCallablePreservesBindingWithMultipleParentsTestCallback6050 : public BoundNodesCallback {6051public:6052 bool run(const BoundNodes *BoundNodes, ASTContext *Context) override {6053 FunctionDecl const *FunDecl =6054 BoundNodes->getNodeAs<FunctionDecl>("funDecl");6055 // Validate test assumptions. This would be expressed as ASSERT_* in6056 // a TEST().6057 if (!FunDecl) {6058 EXPECT_TRUE(false && "Incorrect test setup");6059 return false;6060 }6061 auto const *FunDef = FunDecl->getDefinition();6062 if (!FunDef || !FunDef->getBody() ||6063 FunDef->getNameAsString() != "Function") {6064 EXPECT_TRUE(false && "Incorrect test setup");6065 return false;6066 }6067 6068 ExpectCorrectResult(6069 "Baseline",6070 callExpr(callee(cxxMethodDecl().bind("callee"))).bind("call"), //6071 FunDecl);6072 6073 ExpectCorrectResult("ForCallable first",6074 callExpr(forCallable(equalsNode(FunDecl)),6075 callee(cxxMethodDecl().bind("callee")))6076 .bind("call"),6077 FunDecl);6078 6079 ExpectCorrectResult("ForCallable second",6080 callExpr(callee(cxxMethodDecl().bind("callee")),6081 forCallable(equalsNode(FunDecl)))6082 .bind("call"),6083 FunDecl);6084 6085 // This value does not really matter: the EXPECT_* will set the exit code.6086 return true;6087 }6088 6089private:6090 void ExpectCorrectResult(StringRef LogInfo,6091 ArrayRef<BoundNodes> Results) const {6092 EXPECT_EQ(Results.size(), 1u) << LogInfo;6093 if (Results.empty())6094 return;6095 auto const &R = Results.front();6096 EXPECT_TRUE(R.getNodeAs<CallExpr>("call")) << LogInfo;6097 EXPECT_TRUE(R.getNodeAs<CXXMethodDecl>("callee")) << LogInfo;6098 }6099 6100 template <typename MatcherT>6101 void ExpectCorrectResult(StringRef LogInfo, MatcherT Matcher,6102 FunctionDecl const *FunDef) const {6103 auto &Context = FunDef->getASTContext();6104 auto const &Results = match(findAll(Matcher), *FunDef->getBody(), Context);6105 ExpectCorrectResult(LogInfo, Results);6106 }6107};6108} // namespace6109 6110TEST(StatementMatcher, ForCallablePreservesBindingWithMultipleParents) {6111 // Tests in this file are fairly simple and therefore can rely on matches,6112 // matchAndVerifyResultTrue, etc. This test, however, needs a FunctionDecl* in6113 // order to call equalsNode in order to reproduce the observed issue (bindings6114 // being removed despite forCallable matching the node).6115 //6116 // Because of this and because the machinery to compile the code into an6117 // ASTUnit is not exposed outside matchAndVerifyResultConditionally, it is6118 // cheaper to have a custom BoundNodesCallback for the purpose of this test.6119 StringRef codeWithTemplateFunction = R"cpp(6120struct Klass {6121 void Method();6122 template <typename T>6123 void Function(T t); // Declaration6124};6125 6126void Instantiate(Klass k) {6127 k.Function(0);6128}6129 6130template <typename T>6131void Klass::Function(T t) { // Definition6132 // Compound statement has two parents: the declaration and the definition.6133 Method();6134}6135)cpp";6136 EXPECT_TRUE(matchAndVerifyResultTrue(6137 codeWithTemplateFunction,6138 callExpr(callee(functionDecl(hasName("Function")).bind("funDecl"))),6139 std::make_unique<6140 ForCallablePreservesBindingWithMultipleParentsTestCallback>()));6141}6142 6143TEST(Matcher, ForEachOverriden) {6144 const auto ForEachOverriddenInClass = [](const char *ClassName) {6145 return cxxMethodDecl(ofClass(hasName(ClassName)), isVirtual(),6146 forEachOverridden(cxxMethodDecl().bind("overridden")))6147 .bind("override");6148 };6149 static const char Code1[] = "class A { virtual void f(); };"6150 "class B : public A { void f(); };"6151 "class C : public B { void f(); };";6152 // C::f overrides A::f.6153 EXPECT_TRUE(matchAndVerifyResultTrue(6154 Code1, ForEachOverriddenInClass("C"),6155 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));6156 EXPECT_TRUE(matchAndVerifyResultTrue(6157 Code1, ForEachOverriddenInClass("C"),6158 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",6159 1)));6160 // B::f overrides A::f.6161 EXPECT_TRUE(matchAndVerifyResultTrue(6162 Code1, ForEachOverriddenInClass("B"),6163 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));6164 EXPECT_TRUE(matchAndVerifyResultTrue(6165 Code1, ForEachOverriddenInClass("B"),6166 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",6167 1)));6168 // A::f overrides nothing.6169 EXPECT_TRUE(notMatches(Code1, ForEachOverriddenInClass("A")));6170 6171 static const char Code2[] =6172 "class A1 { virtual void f(); };"6173 "class A2 { virtual void f(); };"6174 "class B : public A1, public A2 { void f(); };";6175 // B::f overrides A1::f and A2::f. This produces two matches.6176 EXPECT_TRUE(matchAndVerifyResultTrue(6177 Code2, ForEachOverriddenInClass("B"),6178 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 2)));6179 EXPECT_TRUE(matchAndVerifyResultTrue(6180 Code2, ForEachOverriddenInClass("B"),6181 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",6182 2)));6183 // A1::f overrides nothing.6184 EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1")));6185}6186 6187TEST(Matcher, HasAnyDeclaration) {6188 StringRef Fragment = "void foo(int p1);"6189 "void foo(int *p2);"6190 "void bar(int p3);"6191 "template <typename T> void baz(T t) { foo(t); }";6192 6193 EXPECT_TRUE(6194 matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(6195 hasParameter(0, parmVarDecl(hasName("p1"))))))));6196 EXPECT_TRUE(6197 matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(6198 hasParameter(0, parmVarDecl(hasName("p2"))))))));6199 EXPECT_TRUE(6200 notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(6201 hasParameter(0, parmVarDecl(hasName("p3"))))))));6202 EXPECT_TRUE(notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(6203 functionDecl(hasName("bar"))))));6204}6205 6206TEST(SubstTemplateTypeParmType, HasReplacementType) {6207 StringRef Fragment = "template<typename T>"6208 "double F(T t);"6209 "int i;"6210 "double j = F(i);";6211 EXPECT_TRUE(matches(Fragment, substTemplateTypeParmType(hasReplacementType(6212 qualType(asString("int"))))));6213 EXPECT_TRUE(notMatches(Fragment, substTemplateTypeParmType(hasReplacementType(6214 qualType(asString("double"))))));6215 EXPECT_TRUE(6216 notMatches("template<int N>"6217 "double F();"6218 "double j = F<5>();",6219 substTemplateTypeParmType(hasReplacementType(qualType()))));6220}6221 6222TEST(ClassTemplateSpecializationDecl, HasSpecializedTemplate) {6223 auto Matcher = classTemplateSpecializationDecl(6224 hasSpecializedTemplate(classTemplateDecl()));6225 EXPECT_TRUE(6226 matches("template<typename T> class A {}; typedef A<int> B;", Matcher));6227 EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher));6228}6229 6230TEST(CXXNewExpr, Array) {6231 StatementMatcher NewArray = cxxNewExpr(isArray());6232 6233 EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray));6234 EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray));6235 6236 StatementMatcher NewArraySize10 =6237 cxxNewExpr(hasArraySize(integerLiteral(equals(10))));6238 EXPECT_TRUE(6239 matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10));6240 EXPECT_TRUE(6241 notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10));6242}6243 6244TEST(CXXNewExpr, PlacementArgs) {6245 StatementMatcher IsPlacementNew = cxxNewExpr(hasAnyPlacementArg(anything()));6246 6247 EXPECT_TRUE(matches(R"(6248 void* operator new(decltype(sizeof(void*)), void*);6249 int *foo(void* Storage) {6250 return new (Storage) int;6251 })",6252 IsPlacementNew));6253 6254 EXPECT_TRUE(matches(R"(6255 void* operator new(decltype(sizeof(void*)), void*, unsigned);6256 int *foo(void* Storage) {6257 return new (Storage, 16) int;6258 })",6259 cxxNewExpr(hasPlacementArg(6260 1, ignoringImpCasts(integerLiteral(equals(16)))))));6261 6262 EXPECT_TRUE(notMatches(R"(6263 void* operator new(decltype(sizeof(void*)), void*);6264 int *foo(void* Storage) {6265 return new int;6266 })",6267 IsPlacementNew));6268}6269 6270TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {6271 EXPECT_TRUE(matches(6272 "const int x = 0;",6273 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6274 hasUnqualifiedLoc(loc(asString("int"))))))));6275}6276 6277TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {6278 EXPECT_TRUE(matches(6279 "volatile int x = 0;",6280 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6281 hasUnqualifiedLoc(loc(asString("int"))))))));6282}6283 6284TEST(HasUnqualifiedLoc, BindsToConstVolatileIntVarDecl) {6285 EXPECT_TRUE(matches(6286 "const volatile int x = 0;",6287 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6288 hasUnqualifiedLoc(loc(asString("int"))))))));6289}6290 6291TEST(HasUnqualifiedLoc, BindsToConstPointerVarDecl) {6292 auto matcher = varDecl(6293 hasName("x"),6294 hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))));6295 EXPECT_TRUE(matches("int* const x = 0;", matcher));6296 EXPECT_TRUE(notMatches("int const x = 0;", matcher));6297}6298 6299TEST(HasUnqualifiedLoc, BindsToPointerToConstVolatileIntVarDecl) {6300 EXPECT_TRUE(6301 matches("const volatile int* x = 0;",6302 varDecl(hasName("x"),6303 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(6304 hasUnqualifiedLoc(loc(asString("int"))))))))));6305}6306 6307TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {6308 EXPECT_TRUE(6309 matches("const int f() { return 5; }",6310 functionDecl(hasName("f"),6311 hasReturnTypeLoc(qualifiedTypeLoc(6312 hasUnqualifiedLoc(loc(asString("int"))))))));6313}6314 6315TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {6316 EXPECT_TRUE(matches(6317 "const float x = 0;",6318 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6319 hasUnqualifiedLoc(loc(asString("float"))))))));6320}6321 6322TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {6323 EXPECT_TRUE(notMatches(6324 "int x = 0;",6325 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6326 hasUnqualifiedLoc(loc(asString("float"))))))));6327}6328 6329TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {6330 EXPECT_TRUE(notMatches(6331 "const int x = 0;",6332 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(6333 hasUnqualifiedLoc(loc(asString("float"))))))));6334}6335 6336TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {6337 EXPECT_TRUE(matches(6338 "int f() { return 5; }",6339 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));6340}6341 6342TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {6343 EXPECT_TRUE(matches(6344 "float f() { return 5.0; }",6345 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));6346}6347 6348TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {6349 EXPECT_TRUE(matches(6350 "void f() {}",6351 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));6352}6353 6354TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {6355 EXPECT_TRUE(notMatches(6356 "int f() { return 5; }",6357 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));6358}6359 6360TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {6361 EXPECT_TRUE(notMatches(6362 "float f() { return 5.0; }",6363 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));6364}6365 6366TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {6367 auto matcher = varDecl(hasName("x"),6368 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));6369 EXPECT_TRUE(matches("int* x;", matcher));6370 EXPECT_TRUE(matches("float* x;", matcher));6371 EXPECT_TRUE(matches("char* x;", matcher));6372 EXPECT_TRUE(matches("void* x;", matcher));6373}6374 6375TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {6376 auto matcher = varDecl(hasName("x"),6377 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));6378 EXPECT_TRUE(notMatches("int x;", matcher));6379 EXPECT_TRUE(notMatches("float x;", matcher));6380 EXPECT_TRUE(notMatches("char x;", matcher));6381}6382 6383TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {6384 EXPECT_TRUE(6385 matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));6386}6387 6388TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {6389 EXPECT_TRUE(matches("int** x;",6390 pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));6391}6392 6393TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {6394 EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(6395 hasPointeeLoc(loc(asString("int"))))))));6396}6397 6398TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {6399 EXPECT_TRUE(matches("float* x;",6400 pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));6401}6402 6403TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {6404 EXPECT_TRUE(notMatches("float* x;",6405 pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));6406}6407 6408TEST(HasPointeeLoc, FloatPointeeDoesNotBindToTypeLocPointingToInt) {6409 EXPECT_TRUE(notMatches(6410 "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));6411}6412 6413TEST(HasReferentLoc, BindsToAnyReferentTypeLoc) {6414 auto matcher = varDecl(6415 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));6416 EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher));6417 EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher));6418 EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher));6419 EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher));6420 EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher));6421}6422 6423TEST(HasReferentLoc, DoesNotBindToTypeLocWithoutReferent) {6424 auto matcher = varDecl(6425 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));6426 EXPECT_TRUE(notMatches("int r;", matcher));6427 EXPECT_TRUE(notMatches("int r = 3;", matcher));6428 EXPECT_TRUE(notMatches("const int r = 3;", matcher));6429 EXPECT_TRUE(notMatches("int* r;", matcher));6430 EXPECT_TRUE(notMatches("float r;", matcher));6431 EXPECT_TRUE(notMatches("char r;", matcher));6432}6433 6434TEST(HasReferentLoc, BindsToAnyRvalueReference) {6435 auto matcher = varDecl(6436 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));6437 EXPECT_TRUE(matches("int&& r = 3;", matcher));6438 EXPECT_TRUE(matches("auto&& r = 3;", matcher));6439 EXPECT_TRUE(matches("float&& r = 3.0;", matcher));6440}6441 6442TEST(HasReferentLoc, BindsToIntReferenceTypeLoc) {6443 EXPECT_TRUE(matches("int rr = 3; int& r = rr;",6444 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));6445}6446 6447TEST(HasReferentLoc, BindsToIntRvalueReferenceTypeLoc) {6448 EXPECT_TRUE(matches("int&& r = 3;",6449 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));6450}6451 6452TEST(HasReferentLoc, BindsToFloatReferenceTypeLoc) {6453 EXPECT_TRUE(6454 matches("float rr = 3.0; float& r = rr;",6455 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));6456}6457 6458TEST(HasReferentLoc, BindsToParameterWithIntReferenceTypeLoc) {6459 EXPECT_TRUE(matches(6460 "int f(int& r) { return r; }",6461 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(6462 hasReferentLoc(loc(asString("int"))))))));6463}6464 6465TEST(HasReferentLoc, IntReferenceDoesNotBindToFloatReferenceTypeLoc) {6466 EXPECT_TRUE(6467 notMatches("float rr = 3.0; float& r = rr;",6468 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));6469}6470 6471TEST(HasReferentLoc, FloatReferenceDoesNotBindToIntReferenceTypeLoc) {6472 EXPECT_TRUE(6473 notMatches("int rr = 3; int& r = rr;",6474 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));6475}6476 6477TEST(HasReferentLoc, DoesNotBindToParameterWithoutIntReferenceTypeLoc) {6478 EXPECT_TRUE(notMatches(6479 "int f(int r) { return r; }",6480 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(6481 hasReferentLoc(loc(asString("int"))))))));6482}6483 6484TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {6485 EXPECT_TRUE(6486 matches("template<typename T> class A {}; A<int> a;",6487 varDecl(hasName("a"), hasTypeLoc(templateSpecializationTypeLoc(6488 hasAnyTemplateArgumentLoc(hasTypeLoc(6489 loc(asString("int")))))))));6490}6491 6492TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {6493 EXPECT_TRUE(6494 matches("template<typename T> class A {}; A<double> a;",6495 varDecl(hasName("a"), hasTypeLoc(templateSpecializationTypeLoc(6496 hasAnyTemplateArgumentLoc(hasTypeLoc(6497 loc(asString("double")))))))));6498}6499 6500TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {6501 EXPECT_TRUE(matches(6502 "template<typename T> class A {}; template<> class A<int> {};",6503 classTemplateSpecializationDecl(6504 hasName("A"),6505 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));6506}6507 6508TEST(HasAnyTemplateArgumentLoc,6509 BindsToExplicitSpecializationWithDoubleArgument) {6510 EXPECT_TRUE(matches(6511 "template<typename T> class A {}; template<> class A<double> {};",6512 classTemplateSpecializationDecl(6513 hasName("A"),6514 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));6515}6516 6517TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {6518 auto code = R"(6519 template<typename T, typename U> class A {};6520 template<> class A<double, int> {};6521 )";6522 EXPECT_TRUE(6523 matches(code, classTemplateSpecializationDecl(6524 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(6525 loc(asString("double")))))));6526 6527 EXPECT_TRUE(matches(6528 code, classTemplateSpecializationDecl(6529 hasName("A"),6530 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));6531}6532 6533TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {6534 EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",6535 classTemplateSpecializationDecl(6536 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(6537 loc(asString("double")))))));6538}6539 6540TEST(HasAnyTemplateArgumentLoc,6541 DoesNotBindToExplicitSpecializationWithIntArgument) {6542 EXPECT_TRUE(notMatches(6543 "template<typename T> class A {}; template<> class A<int> {};",6544 classTemplateSpecializationDecl(6545 hasName("A"),6546 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));6547}6548 6549TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {6550 EXPECT_TRUE(matches(6551 "template<typename T> class A {}; A<int> a;",6552 varDecl(hasName("a"),6553 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(6554 0, hasTypeLoc(loc(asString("int")))))))));6555}6556 6557TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {6558 EXPECT_TRUE(matches(6559 "template<typename T> class A {}; A<double> a;",6560 varDecl(hasName("a"),6561 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(6562 0, hasTypeLoc(loc(asString("double")))))))));6563}6564 6565TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {6566 EXPECT_TRUE(notMatches(6567 "template<typename T> class A {}; A<int> a;",6568 varDecl(hasName("a"),6569 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(6570 0, hasTypeLoc(loc(asString("double")))))))));6571}6572 6573TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {6574 EXPECT_TRUE(matches(6575 "template<typename T> class A {}; template<> class A<int> {};",6576 classTemplateSpecializationDecl(6577 hasName("A"),6578 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));6579}6580 6581TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {6582 EXPECT_TRUE(matches(6583 "template<typename T> class A {}; template<> class A<double> {};",6584 classTemplateSpecializationDecl(6585 hasName("A"),6586 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));6587}6588 6589TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {6590 auto code = R"(6591 template<typename T, typename U> class A {};6592 template<> class A<double, int> {};6593 )";6594 EXPECT_TRUE(matches(6595 code, classTemplateSpecializationDecl(6596 hasName("A"), hasTemplateArgumentLoc(6597 0, hasTypeLoc(loc(asString("double")))))));6598 EXPECT_TRUE(matches(6599 code, classTemplateSpecializationDecl(6600 hasName("A"),6601 hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));6602}6603 6604TEST(HasTemplateArgumentLoc,6605 DoesNotBindToExplicitSpecializationWithIntArgument) {6606 EXPECT_TRUE(notMatches(6607 "template<typename T> class A {}; template<> class A<int> {};",6608 classTemplateSpecializationDecl(6609 hasName("A"),6610 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));6611}6612 6613TEST(HasTemplateArgumentLoc,6614 DoesNotBindToSpecializationWithMisplacedArguments) {6615 auto code = R"(6616 template<typename T, typename U> class A {};6617 template<> class A<double, int> {};6618 )";6619 EXPECT_TRUE(notMatches(6620 code, classTemplateSpecializationDecl(6621 hasName("A"), hasTemplateArgumentLoc(6622 1, hasTypeLoc(loc(asString("double")))))));6623 EXPECT_TRUE(notMatches(6624 code, classTemplateSpecializationDecl(6625 hasName("A"),6626 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));6627}6628 6629TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {6630 auto code = R"(6631 template<typename T, typename U> class A {};6632 template<> class A<double, int> {};6633 )";6634 EXPECT_TRUE(notMatches(6635 code, classTemplateSpecializationDecl(6636 hasName("A"), hasTemplateArgumentLoc(6637 -1, hasTypeLoc(loc(asString("double")))))));6638 EXPECT_TRUE(notMatches(6639 code, classTemplateSpecializationDecl(6640 hasName("A"), hasTemplateArgumentLoc(6641 100, hasTypeLoc(loc(asString("int")))))));6642}6643 6644TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {6645 EXPECT_TRUE(matches(R"(6646 template<typename T> T f(T t) { return t; }6647 int g() { int i = f<int>(3); return i; }6648 )",6649 declRefExpr(to(functionDecl(hasName("f"))),6650 hasTemplateArgumentLoc(6651 0, hasTypeLoc(loc(asString("int")))))));6652}6653 6654TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithDoubleArgument) {6655 EXPECT_TRUE(matches(6656 R"(6657 template<typename T> T f(T t) { return t; }6658 double g() { double i = f<double>(3.0); return i; }6659 )",6660 declRefExpr(6661 to(functionDecl(hasName("f"))),6662 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));6663}6664 6665TEST(HasTemplateArgumentLoc, DoesNotBindToDeclRefExprWithDoubleArgument) {6666 EXPECT_TRUE(notMatches(6667 R"(6668 template<typename T> T f(T t) { return t; }6669 double g() { double i = f<double>(3.0); return i; }6670 )",6671 declRefExpr(6672 to(functionDecl(hasName("f"))),6673 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));6674}6675 6676TEST(HasNamedTypeLoc, BindsToElaboratedObjectDeclaration) {6677 EXPECT_TRUE(matches(6678 R"(6679 template <typename T>6680 class C {};6681 class C<int> c;6682 )",6683 varDecl(hasName("c"),6684 hasTypeLoc(templateSpecializationTypeLoc(6685 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))));6686}6687 6688TEST(HasNamedTypeLoc, BindsToNonElaboratedObjectDeclaration) {6689 EXPECT_TRUE(matches(6690 R"(6691 template <typename T>6692 class C {};6693 C<int> c;6694 )",6695 varDecl(hasName("c"),6696 hasTypeLoc(templateSpecializationTypeLoc(6697 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))));6698}6699 6700} // namespace ast_matchers6701} // namespace clang6702