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