1 //= unittests/ASTMatchers/ASTMatchersTraversalTest.cpp - matchers unit tests =//
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
7 //===----------------------------------------------------------------------===//
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"
22 namespace ast_matchers
{
24 TEST(DeclarationMatcher
, hasMethod
) {
25 EXPECT_TRUE(matches("class A { void func(); };",
26 cxxRecordDecl(hasMethod(hasName("func")))));
27 EXPECT_TRUE(notMatches("class A { void func(); };",
28 cxxRecordDecl(hasMethod(isPublic()))));
31 TEST(DeclarationMatcher
, ClassDerivedFromDependentTemplateSpecialization
) {
33 "template <typename T> struct A {"
34 " template <typename T2> struct F {};"
36 "template <typename T> struct B : A<T>::template F<T> {};"
38 cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
41 TEST(DeclarationMatcher
, hasDeclContext
) {
48 recordDecl(hasDeclContext(namespaceDecl(hasName("M"))))));
49 EXPECT_TRUE(notMatches(
55 recordDecl(hasDeclContext(namespaceDecl(hasName("N"))))));
57 EXPECT_TRUE(matches("namespace {"
62 recordDecl(hasDeclContext(namespaceDecl(
63 hasName("M"), hasDeclContext(namespaceDecl()))))));
65 EXPECT_TRUE(matches("class D{};", decl(hasDeclContext(decl()))));
68 TEST(HasDescendant
, MatchesDescendantTypes
) {
69 EXPECT_TRUE(matches("void f() { int i = 3; }",
70 decl(hasDescendant(loc(builtinType())))));
71 EXPECT_TRUE(matches("void f() { int i = 3; }",
72 stmt(hasDescendant(builtinType()))));
74 EXPECT_TRUE(matches("void f() { int i = 3; }",
75 stmt(hasDescendant(loc(builtinType())))));
76 EXPECT_TRUE(matches("void f() { int i = 3; }",
77 stmt(hasDescendant(qualType(builtinType())))));
79 EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }",
80 stmt(hasDescendant(isInteger()))));
82 EXPECT_TRUE(matchAndVerifyResultTrue(
83 "void f() { int a; float c; int d; int e; }",
84 functionDecl(forEachDescendant(
85 varDecl(hasDescendant(isInteger())).bind("x"))),
86 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 3)));
89 TEST(HasDescendant
, MatchesDescendantsOfTypes
) {
90 EXPECT_TRUE(matches("void f() { int*** i; }",
91 qualType(hasDescendant(builtinType()))));
92 EXPECT_TRUE(matches("void f() { int*** i; }",
93 qualType(hasDescendant(
94 pointerType(pointee(builtinType()))))));
95 EXPECT_TRUE(matches("void f() { int*** i; }",
96 typeLoc(hasDescendant(loc(builtinType())))));
98 EXPECT_TRUE(matchAndVerifyResultTrue(
99 "void f() { int*** i; }",
100 qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))),
101 std::make_unique
<VerifyIdIsBoundTo
<Type
>>("x", 2)));
105 TEST(Has
, MatchesChildrenOfTypes
) {
106 EXPECT_TRUE(matches("int i;",
107 varDecl(hasName("i"), has(isInteger()))));
108 EXPECT_TRUE(notMatches("int** i;",
109 varDecl(hasName("i"), has(isInteger()))));
110 EXPECT_TRUE(matchAndVerifyResultTrue(
111 "int (*f)(float, int);",
112 qualType(functionType(), forEach(qualType(isInteger()).bind("x"))),
113 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("x", 2)));
116 TEST(Has
, MatchesChildTypes
) {
119 varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));
120 EXPECT_TRUE(notMatches(
122 varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));
125 TEST(StatementMatcher
, Has
) {
126 StatementMatcher HasVariableI
=
127 expr(hasType(pointsTo(recordDecl(hasName("X")))),
128 has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i")))))));
131 "class X; X *x(int); void c() { int i; x(i); }", HasVariableI
));
132 EXPECT_TRUE(notMatches(
133 "class X; X *x(int); void c() { int i; x(42); }", HasVariableI
));
136 TEST(StatementMatcher
, HasDescendant
) {
137 StatementMatcher HasDescendantVariableI
=
138 expr(hasType(pointsTo(recordDecl(hasName("X")))),
139 hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));
142 "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",
143 HasDescendantVariableI
));
144 EXPECT_TRUE(notMatches(
145 "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",
146 HasDescendantVariableI
));
149 TEST(TypeMatcher
, MatchesClassType
) {
150 TypeMatcher TypeA
= hasDeclaration(recordDecl(hasName("A")));
152 EXPECT_TRUE(matches("class A { public: A *a; };", TypeA
));
153 EXPECT_TRUE(notMatches("class A {};", TypeA
));
155 TypeMatcher TypeDerivedFromA
=
156 hasDeclaration(cxxRecordDecl(isDerivedFrom("A")));
158 EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",
160 EXPECT_TRUE(notMatches("class A {};", TypeA
));
162 TypeMatcher TypeAHasClassB
= hasDeclaration(
163 recordDecl(hasName("A"), has(recordDecl(hasName("B")))));
166 matches("class A { public: A *a; class B {}; };", TypeAHasClassB
));
168 EXPECT_TRUE(matchesC("struct S {}; void f(void) { struct S s; }",
169 varDecl(hasType(namedDecl(hasName("S"))))));
172 TEST(TypeMatcher
, MatchesDeclTypes
) {
173 // TypedefType -> TypedefNameDecl
174 EXPECT_TRUE(matches("typedef int I; void f(I i);",
175 parmVarDecl(hasType(namedDecl(hasName("I"))))));
176 // ObjCObjectPointerType
177 EXPECT_TRUE(matchesObjC("@interface Foo @end void f(Foo *f);",
178 parmVarDecl(hasType(objcObjectPointerType()))));
179 // ObjCObjectPointerType -> ObjCInterfaceType -> ObjCInterfaceDecl
180 EXPECT_TRUE(matchesObjC(
181 "@interface Foo @end void f(Foo *f);",
182 parmVarDecl(hasType(pointsTo(objcInterfaceDecl(hasName("Foo")))))));
183 // TemplateTypeParmType
184 EXPECT_TRUE(matches("template <typename T> void f(T t);",
185 parmVarDecl(hasType(templateTypeParmType()))));
186 // TemplateTypeParmType -> TemplateTypeParmDecl
187 EXPECT_TRUE(matches("template <typename T> void f(T t);",
188 parmVarDecl(hasType(namedDecl(hasName("T"))))));
189 // InjectedClassNameType
190 EXPECT_TRUE(matches("template <typename T> struct S {"
193 parmVarDecl(hasType(elaboratedType(
194 namesType(injectedClassNameType()))))));
195 EXPECT_TRUE(notMatches("template <typename T> struct S {"
198 parmVarDecl(hasType(elaboratedType(
199 namesType(injectedClassNameType()))))));
200 // InjectedClassNameType -> CXXRecordDecl
201 EXPECT_TRUE(matches("template <typename T> struct S {"
204 parmVarDecl(hasType(namedDecl(hasName("S"))))));
206 static const char Using
[] = "template <typename T>"
211 "template <typename T>"
212 "struct S : private Base<T> {"
213 " using typename Base<T>::Foo;"
216 // UnresolvedUsingTypenameDecl
217 EXPECT_TRUE(matches(Using
, unresolvedUsingTypenameDecl(hasName("Foo"))));
218 // UnresolvedUsingTypenameType -> UnresolvedUsingTypenameDecl
219 EXPECT_TRUE(matches(Using
, parmVarDecl(hasType(namedDecl(hasName("Foo"))))));
222 TEST(HasDeclaration
, HasDeclarationOfEnumType
) {
223 EXPECT_TRUE(matches("enum X {}; void y(X *x) { x; }",
224 expr(hasType(pointsTo(
225 qualType(hasDeclaration(enumDecl(hasName("X")))))))));
228 TEST(HasDeclaration
, HasGetDeclTraitTest
) {
229 static_assert(internal::has_getDecl
<TypedefType
>::value
,
230 "Expected TypedefType to have a getDecl.");
231 static_assert(internal::has_getDecl
<RecordType
>::value
,
232 "Expected RecordType to have a getDecl.");
233 static_assert(!internal::has_getDecl
<TemplateSpecializationType
>::value
,
234 "Expected TemplateSpecializationType to *not* have a getDecl.");
237 TEST(HasDeclaration
, ElaboratedType
) {
239 "namespace n { template <typename T> struct X {}; }"
240 "void f(n::X<int>);",
241 parmVarDecl(hasType(qualType(hasDeclaration(cxxRecordDecl()))))));
243 "namespace n { template <typename T> struct X {}; }"
244 "void f(n::X<int>);",
245 parmVarDecl(hasType(elaboratedType(hasDeclaration(cxxRecordDecl()))))));
248 TEST(HasDeclaration
, HasDeclarationOfTypeWithDecl
) {
250 "typedef int X; X a;",
251 varDecl(hasName("a"), hasType(elaboratedType(namesType(
252 typedefType(hasDeclaration(decl()))))))));
254 // FIXME: Add tests for other types with getDecl() (e.g. RecordType)
257 TEST(HasDeclaration
, HasDeclarationOfTemplateSpecializationType
) {
259 "template <typename T> class A {}; A<int> a;",
260 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
261 hasDeclaration(namedDecl(hasName("A"))))))))));
263 "template <typename T> class A {};"
264 "template <typename T> class B { A<T> a; };",
265 fieldDecl(hasType(elaboratedType(namesType(templateSpecializationType(
266 hasDeclaration(namedDecl(hasName("A"))))))))));
268 "template <typename T> class A {}; A<int> a;",
269 varDecl(hasType(elaboratedType(namesType(
270 templateSpecializationType(hasDeclaration(cxxRecordDecl()))))))));
273 TEST(HasDeclaration
, HasDeclarationOfCXXNewExpr
) {
275 matches("int *A = new int();",
276 cxxNewExpr(hasDeclaration(functionDecl(parameterCountIs(1))))));
279 TEST(HasDeclaration
, HasDeclarationOfTypeAlias
) {
281 "template <typename T> using C = T; C<int> c;",
282 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
283 hasDeclaration(typeAliasTemplateDecl()))))))));
286 TEST(HasUnqualifiedDesugaredType
, DesugarsUsing
) {
288 matches("struct A {}; using B = A; B b;",
289 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
291 matches("struct A {}; using B = A; using C = B; C b;",
292 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
295 TEST(HasUnderlyingDecl
, Matches
) {
296 EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }"
297 "template <class T> void g() { using N::f; f(T()); }",
298 unresolvedLookupExpr(hasAnyDeclaration(
299 namedDecl(hasUnderlyingDecl(hasName("::N::f")))))));
301 "namespace N { template <class T> void f(T t); }"
302 "template <class T> void g() { N::f(T()); }",
303 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
304 EXPECT_TRUE(notMatches(
305 "namespace N { template <class T> void f(T t); }"
306 "template <class T> void g() { using N::f; f(T()); }",
307 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
310 TEST(HasType
, TakesQualTypeMatcherAndMatchesExpr
) {
311 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
313 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX
))));
315 notMatches("class X {}; void y(X *x) { x; }",
316 expr(hasType(ClassX
))));
318 matches("class X {}; void y(X *x) { x; }",
319 expr(hasType(pointsTo(ClassX
)))));
322 TEST(HasType
, TakesQualTypeMatcherAndMatchesValueDecl
) {
323 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
325 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX
))));
327 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX
))));
329 matches("class X {}; void y() { X *x; }",
330 varDecl(hasType(pointsTo(ClassX
)))));
333 TEST(HasType
, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier
) {
334 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
335 CXXBaseSpecifierMatcher BaseClassX
= cxxBaseSpecifier(hasType(ClassX
));
336 DeclarationMatcher ClassHasBaseClassX
=
337 cxxRecordDecl(hasDirectBase(BaseClassX
));
338 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX
));
339 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX
));
342 TEST(HasType
, TakesDeclMatcherAndMatchesExpr
) {
343 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
345 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX
))));
347 notMatches("class X {}; void y(X *x) { x; }",
348 expr(hasType(ClassX
))));
351 TEST(HasType
, TakesDeclMatcherAndMatchesValueDecl
) {
352 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
354 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX
))));
356 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX
))));
359 TEST(HasType
, TakesDeclMatcherAndMatchesCXXBaseSpecifier
) {
360 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
361 CXXBaseSpecifierMatcher BaseClassX
= cxxBaseSpecifier(hasType(ClassX
));
362 DeclarationMatcher ClassHasBaseClassX
=
363 cxxRecordDecl(hasDirectBase(BaseClassX
));
364 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX
));
365 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX
));
368 TEST(HasType
, MatchesTypedefDecl
) {
369 EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));
370 EXPECT_TRUE(matches("typedef const int T;",
371 typedefDecl(hasType(asString("const int")))));
372 EXPECT_TRUE(notMatches("typedef const int T;",
373 typedefDecl(hasType(asString("int")))));
374 EXPECT_TRUE(matches("typedef int foo; typedef foo bar;",
375 typedefDecl(hasType(asString("foo")), hasName("bar"))));
378 TEST(HasType
, MatchesTypedefNameDecl
) {
379 EXPECT_TRUE(matches("using X = int;", typedefNameDecl(hasType(asString("int")))));
380 EXPECT_TRUE(matches("using T = const int;",
381 typedefNameDecl(hasType(asString("const int")))));
382 EXPECT_TRUE(notMatches("using T = const int;",
383 typedefNameDecl(hasType(asString("int")))));
384 EXPECT_TRUE(matches("using foo = int; using bar = foo;",
385 typedefNameDecl(hasType(asString("foo")), hasName("bar"))));
388 TEST(HasTypeLoc
, MatchesBlockDecl
) {
389 EXPECT_TRUE(matchesConditionally(
390 "auto x = ^int (int a, int b) { return a + b; };",
391 blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true,
395 TEST(HasTypeLoc
, MatchesCXXBaseSpecifierAndCtorInitializer
) {
396 llvm::StringRef code
= R
"cpp(
398 class Bar : public Foo {
404 code
, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("Foo")))))));
406 matches(code
, cxxCtorInitializer(hasTypeLoc(loc(asString("Foo"))))));
409 TEST(HasTypeLoc
, MatchesCXXFunctionalCastExpr
) {
410 EXPECT_TRUE(matches("auto x = int(3);",
411 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int"))))));
414 TEST(HasTypeLoc
, MatchesCXXNewExpr
) {
415 EXPECT_TRUE(matches("auto* x = new int(3);",
416 cxxNewExpr(hasTypeLoc(loc(asString("int"))))));
417 EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();",
418 cxxNewExpr(hasTypeLoc(loc(asString("Foo"))))));
421 TEST(HasTypeLoc
, MatchesCXXTemporaryObjectExpr
) {
423 matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",
424 cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("Foo"))))));
427 TEST(HasTypeLoc
, MatchesCXXUnresolvedConstructExpr
) {
429 matches("template <typename T> T make() { return T(); }",
430 cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));
433 TEST(HasTypeLoc
, MatchesCompoundLiteralExpr
) {
435 matches("int* x = (int[2]) { 0, 1 };",
436 compoundLiteralExpr(hasTypeLoc(loc(asString("int[2]"))))));
439 TEST(HasTypeLoc
, MatchesDeclaratorDecl
) {
440 EXPECT_TRUE(matches("int x;",
441 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
442 EXPECT_TRUE(matches("int x(3);",
443 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
444 EXPECT_TRUE(matches("struct Foo { Foo(int, int); }; Foo x(1, 2);",
445 varDecl(hasName("x"), hasTypeLoc(loc(asString("Foo"))))));
447 // Make sure we don't crash on implicit constructors.
448 EXPECT_TRUE(notMatches("class X {}; X x;",
449 declaratorDecl(hasTypeLoc(loc(asString("int"))))));
452 TEST(HasTypeLoc
, MatchesExplicitCastExpr
) {
453 EXPECT_TRUE(matches("auto x = (int) 3;",
454 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
455 EXPECT_TRUE(matches("auto x = static_cast<int>(3);",
456 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
459 TEST(HasTypeLoc
, MatchesObjCPropertyDecl
) {
460 EXPECT_TRUE(matchesObjC(R
"objc(
462 @property int enabled;
465 objcPropertyDecl(hasTypeLoc(loc(asString("int"))))));
468 TEST(HasTypeLoc
, MatchesTemplateArgumentLoc
) {
469 EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;",
470 templateArgumentLoc(hasTypeLoc(loc(asString("int"))))));
473 TEST(HasTypeLoc
, MatchesTypedefNameDecl
) {
474 EXPECT_TRUE(matches("typedef int X;",
475 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
476 EXPECT_TRUE(matches("using X = int;",
477 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
480 TEST(Callee
, MatchesDeclarations
) {
481 StatementMatcher CallMethodX
= callExpr(callee(cxxMethodDecl(hasName("x"))));
483 EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX
));
484 EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX
));
486 CallMethodX
= traverse(TK_AsIs
, callExpr(callee(cxxConversionDecl())));
488 matches("struct Y { operator int() const; }; int i = Y();", CallMethodX
));
489 EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",
493 TEST(Callee
, MatchesMemberExpressions
) {
494 EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
495 callExpr(callee(memberExpr()))));
497 notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));
500 TEST(Matcher
, Argument
) {
501 StatementMatcher CallArgumentY
= callExpr(
502 hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
504 EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY
));
506 matches("class X { void x(int) { int y; x(y); } };", CallArgumentY
));
507 EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY
));
509 StatementMatcher WrongIndex
= callExpr(
510 hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
511 EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex
));
514 TEST(Matcher
, AnyArgument
) {
515 auto HasArgumentY
= hasAnyArgument(
516 ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
517 StatementMatcher CallArgumentY
= callExpr(HasArgumentY
);
518 StatementMatcher CtorArgumentY
= cxxConstructExpr(HasArgumentY
);
519 StatementMatcher UnresolvedCtorArgumentY
=
520 cxxUnresolvedConstructExpr(HasArgumentY
);
521 StatementMatcher ObjCCallArgumentY
= objcMessageExpr(HasArgumentY
);
522 EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY
));
523 EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY
));
524 EXPECT_TRUE(matches("struct Y { Y(int, int); };"
525 "void x() { int y; (void)Y(1, y); }",
527 EXPECT_TRUE(matches("struct Y { Y(int, int); };"
528 "void x() { int y; (void)Y(y, 42); }",
530 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",
531 UnresolvedCtorArgumentY
));
532 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",
533 UnresolvedCtorArgumentY
));
534 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
535 "void x(I* i) { int y; [i f:y]; }",
537 EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "
538 "void x(I* i) { int z; [i f:z]; }",
540 EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY
));
541 EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"
542 "void x() { int y; (void)Y(1, 2); }",
544 EXPECT_TRUE(notMatches("template <class Y>"
545 "void x() { int y; (void)Y(1, 2); }",
546 UnresolvedCtorArgumentY
));
548 StatementMatcher ImplicitCastedArgument
=
549 traverse(TK_AsIs
, callExpr(hasAnyArgument(implicitCastExpr())));
550 EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument
));
553 TEST(Matcher
, HasReceiver
) {
554 EXPECT_TRUE(matchesObjC(
555 "@interface NSString @end "
556 "void f(NSString *x) {"
557 "[x containsString];"
559 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
561 EXPECT_FALSE(matchesObjC(
562 "@interface NSString +(NSString *) stringWithFormat; @end "
563 "void f() { [NSString stringWithFormat]; }",
564 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
567 TEST(Matcher
, MatchesMethodsOnLambda
) {
568 StringRef Code
= R
"cpp(
577 auto lPtrDecay = +[] { };
583 Code
, cxxConstructorDecl(
584 hasBody(compoundStmt()),
585 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),
586 isCopyConstructor())));
588 Code
, cxxConstructorDecl(
589 hasBody(compoundStmt()),
590 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),
591 isMoveConstructor())));
593 Code
, cxxDestructorDecl(
594 hasBody(compoundStmt()),
595 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))))));
597 Code
, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt(
598 hasReturnValue(implicitCastExpr()))))),
599 hasAncestor(lambdaExpr(hasAncestor(
600 varDecl(hasName("lPtrDecay"))))))));
603 TEST(Matcher
, MatchesCoroutine
) {
604 FileContentMappings M
;
605 M
.push_back(std::make_pair("/coro_header", R
"cpp(
608 template <class... Args>
612 template <class... Args>
613 using void_t = typename void_t_imp<Args...>::type;
615 template <class T, class = void>
616 struct traits_sfinae_base {};
619 struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
620 using promise_type = typename T::promise_type;
623 template <class Ret, class... Args>
624 struct coroutine_traits : public traits_sfinae_base<Ret> {};
627 bool await_ready() noexcept;
628 template <typename F>
629 void await_suspend(F) noexcept;
630 void await_resume() noexcept;
633 void get_return_object();
634 awaitable initial_suspend();
635 awaitable final_suspend() noexcept;
636 awaitable yield_value(int); // expected-note 2{{candidate}}
637 void return_value(int); // expected-note 2{{here}}
638 void unhandled_exception();
640 template <typename... T>
641 struct std::coroutine_traits<void, T...> { using promise_type = promise; };
643 template <class PromiseType = void>
644 struct coroutine_handle {
645 static coroutine_handle from_address(void *) noexcept;
649 StringRef CoReturnCode
= R
"cpp(
650 #include <coro_header>
651 void check_match_co_return() {
655 EXPECT_TRUE(matchesConditionally(CoReturnCode
,
656 coreturnStmt(isExpansionInMainFile()), true,
657 {"-std=c++20", "-I/"}, M
));
658 StringRef CoAwaitCode
= R
"cpp(
659 #include <coro_header>
660 void check_match_co_await() {
664 EXPECT_TRUE(matchesConditionally(CoAwaitCode
,
665 coawaitExpr(isExpansionInMainFile()), true,
666 {"-std=c++20", "-I/"}, M
));
667 StringRef CoYieldCode
= R
"cpp(
668 #include <coro_header>
669 void check_match_co_yield() {
673 EXPECT_TRUE(matchesConditionally(CoYieldCode
,
674 coyieldExpr(isExpansionInMainFile()), true,
675 {"-std=c++20", "-I/"}, M
));
677 StringRef NonCoroCode
= R
"cpp(
678 #include <coro_header>
679 void non_coro_function() {
683 EXPECT_TRUE(matchesConditionally(CoReturnCode
, coroutineBodyStmt(), true,
684 {"-std=c++20", "-I/"}, M
));
685 EXPECT_TRUE(matchesConditionally(CoAwaitCode
, coroutineBodyStmt(), true,
686 {"-std=c++20", "-I/"}, M
));
687 EXPECT_TRUE(matchesConditionally(CoYieldCode
, coroutineBodyStmt(), true,
688 {"-std=c++20", "-I/"}, M
));
690 EXPECT_FALSE(matchesConditionally(NonCoroCode
, coroutineBodyStmt(), true,
691 {"-std=c++20", "-I/"}, M
));
693 StringRef CoroWithDeclCode
= R
"cpp(
694 #include <coro_header>
700 EXPECT_TRUE(matchesConditionally(
702 coroutineBodyStmt(hasBody(compoundStmt(
703 has(declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))),
704 true, {"-std=c++20", "-I/"}, M
));
706 StringRef CoroWithTryCatchDeclCode
= R
"cpp(
707 #include <coro_header>
713 EXPECT_TRUE(matchesConditionally(
714 CoroWithTryCatchDeclCode
,
715 coroutineBodyStmt(hasBody(compoundStmt(has(cxxTryStmt(has(compoundStmt(has(
716 declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))))),
717 true, {"-std=c++20", "-I/"}, M
));
720 TEST(Matcher
, isClassMessage
) {
721 EXPECT_TRUE(matchesObjC(
722 "@interface NSString +(NSString *) stringWithFormat; @end "
723 "void f() { [NSString stringWithFormat]; }",
724 objcMessageExpr(isClassMessage())));
726 EXPECT_FALSE(matchesObjC(
727 "@interface NSString @end "
728 "void f(NSString *x) {"
729 "[x containsString];"
731 objcMessageExpr(isClassMessage())));
734 TEST(Matcher
, isInstanceMessage
) {
735 EXPECT_TRUE(matchesObjC(
736 "@interface NSString @end "
737 "void f(NSString *x) {"
738 "[x containsString];"
740 objcMessageExpr(isInstanceMessage())));
742 EXPECT_FALSE(matchesObjC(
743 "@interface NSString +(NSString *) stringWithFormat; @end "
744 "void f() { [NSString stringWithFormat]; }",
745 objcMessageExpr(isInstanceMessage())));
749 TEST(Matcher
, isClassMethod
) {
750 EXPECT_TRUE(matchesObjC(
751 "@interface Bar + (void)bar; @end",
752 objcMethodDecl(isClassMethod())));
754 EXPECT_TRUE(matchesObjC(
755 "@interface Bar @end"
756 "@implementation Bar + (void)bar {} @end",
757 objcMethodDecl(isClassMethod())));
759 EXPECT_FALSE(matchesObjC(
760 "@interface Foo - (void)foo; @end",
761 objcMethodDecl(isClassMethod())));
763 EXPECT_FALSE(matchesObjC(
764 "@interface Foo @end "
765 "@implementation Foo - (void)foo {} @end",
766 objcMethodDecl(isClassMethod())));
769 TEST(Matcher
, isInstanceMethod
) {
770 EXPECT_TRUE(matchesObjC(
771 "@interface Foo - (void)foo; @end",
772 objcMethodDecl(isInstanceMethod())));
774 EXPECT_TRUE(matchesObjC(
775 "@interface Foo @end "
776 "@implementation Foo - (void)foo {} @end",
777 objcMethodDecl(isInstanceMethod())));
779 EXPECT_FALSE(matchesObjC(
780 "@interface Bar + (void)bar; @end",
781 objcMethodDecl(isInstanceMethod())));
783 EXPECT_FALSE(matchesObjC(
784 "@interface Bar @end"
785 "@implementation Bar + (void)bar {} @end",
786 objcMethodDecl(isInstanceMethod())));
789 TEST(MatcherCXXMemberCallExpr
, On
) {
790 StringRef Snippet1
= R
"cc(
794 void z(Y y) { y.m(); }
796 StringRef Snippet2
= R
"cc(
800 struct X : public Y {};
801 void z(X x) { x.m(); }
803 auto MatchesY
= cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))));
804 EXPECT_TRUE(matches(Snippet1
, MatchesY
));
805 EXPECT_TRUE(notMatches(Snippet2
, MatchesY
));
807 auto MatchesX
= cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))));
808 EXPECT_TRUE(matches(Snippet2
, MatchesX
));
810 // Parens are ignored.
811 StringRef Snippet3
= R
"cc(
816 void z(Y y) { (g()).m(); }
818 auto MatchesCall
= cxxMemberCallExpr(on(callExpr()));
819 EXPECT_TRUE(matches(Snippet3
, MatchesCall
));
822 TEST(MatcherCXXMemberCallExpr
, OnImplicitObjectArgument
) {
823 StringRef Snippet1
= R
"cc(
827 void z(Y y) { y.m(); }
829 StringRef Snippet2
= R
"cc(
833 struct X : public Y {};
834 void z(X x) { x.m(); }
836 auto MatchesY
= traverse(TK_AsIs
, cxxMemberCallExpr(onImplicitObjectArgument(
837 hasType(cxxRecordDecl(hasName("Y"))))));
838 EXPECT_TRUE(matches(Snippet1
, MatchesY
));
839 EXPECT_TRUE(matches(Snippet2
, MatchesY
));
841 auto MatchesX
= traverse(TK_AsIs
, cxxMemberCallExpr(onImplicitObjectArgument(
842 hasType(cxxRecordDecl(hasName("X"))))));
843 EXPECT_TRUE(notMatches(Snippet2
, MatchesX
));
845 // Parens are not ignored.
846 StringRef Snippet3
= R
"cc(
851 void z(Y y) { (g()).m(); }
853 auto MatchesCall
= traverse(
854 TK_AsIs
, cxxMemberCallExpr(onImplicitObjectArgument(callExpr())));
855 EXPECT_TRUE(notMatches(Snippet3
, MatchesCall
));
858 TEST(Matcher
, HasObjectExpr
) {
859 StringRef Snippet1
= R
"cc(
862 int f(X x) { return x.m; }
865 StringRef Snippet2
= R
"cc(
868 int f(X x) { return m; }
872 memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))));
873 EXPECT_TRUE(matches(Snippet1
, MatchesX
));
874 EXPECT_TRUE(notMatches(Snippet2
, MatchesX
));
876 auto MatchesXPointer
= memberExpr(
877 hasObjectExpression(hasType(pointsTo(cxxRecordDecl(hasName("X"))))));
878 EXPECT_TRUE(notMatches(Snippet1
, MatchesXPointer
));
879 EXPECT_TRUE(matches(Snippet2
, MatchesXPointer
));
882 TEST(ForEachArgumentWithParam
, ReportsNoFalsePositives
) {
883 StatementMatcher ArgumentY
=
884 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
885 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
886 StatementMatcher CallExpr
=
887 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
889 // IntParam does not match.
890 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr
));
891 // ArgumentY does not match.
892 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr
));
895 TEST(ForEachArgumentWithParam
, MatchesCXXMemberCallExpr
) {
896 StatementMatcher ArgumentY
=
897 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
898 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
899 StatementMatcher CallExpr
=
900 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
901 EXPECT_TRUE(matchAndVerifyResultTrue(
903 " const S& operator[](int i) { return *this; }"
909 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", 1)));
911 StatementMatcher CallExpr2
=
912 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
913 EXPECT_TRUE(matchAndVerifyResultTrue(
915 " static void g(int i);"
921 CallExpr2
, std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", 1)));
924 TEST(ForEachArgumentWithParam
, MatchesCallExpr
) {
925 StatementMatcher ArgumentY
=
926 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
927 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
928 StatementMatcher CallExpr
=
929 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
932 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr
,
933 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>(
936 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr
,
937 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>(
940 EXPECT_TRUE(matchAndVerifyResultTrue(
941 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
942 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", 2)));
943 EXPECT_TRUE(matchAndVerifyResultTrue(
944 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
945 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg", 2)));
948 TEST(ForEachArgumentWithParam
, MatchesConstructExpr
) {
949 StatementMatcher ArgumentY
=
950 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
951 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
952 StatementMatcher ConstructExpr
= traverse(
953 TK_AsIs
, cxxConstructExpr(forEachArgumentWithParam(ArgumentY
, IntParam
)));
955 EXPECT_TRUE(matchAndVerifyResultTrue(
962 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param")));
965 TEST(ForEachArgumentWithParam
, HandlesBoundNodesForNonMatches
) {
966 EXPECT_TRUE(matchAndVerifyResultTrue(
967 "void g(int i, int j) {"
976 forEachDescendant(varDecl().bind("v")),
977 forEachDescendant(callExpr(forEachArgumentWithParam(
978 declRefExpr(to(decl(equalsBoundNode("v")))), parmVarDecl())))),
979 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("v", 4)));
982 TEST_P(ASTMatchersTest
,
983 ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls
) {
984 if (!GetParam().isCXX23OrLater()) {
988 auto DeclRef
= declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");
989 auto SelfParam
= parmVarDecl().bind("param");
990 StatementMatcher CallExpr
=
991 callExpr(forEachArgumentWithParam(DeclRef
, SelfParam
));
995 int operator()(this const A &self);
1001 auto Args
= GetParam().getCommandLineArgs();
1002 auto Filename
= getFilenameForTesting(GetParam().Language
);
1004 EXPECT_TRUE(matchAndVerifyResultTrue(
1006 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", "self"), Args
,
1008 EXPECT_TRUE(matchAndVerifyResultTrue(
1010 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("declOfArg", "obj"), Args
,
1014 TEST(ForEachArgumentWithParamType
, ReportsNoFalsePositives
) {
1015 StatementMatcher ArgumentY
=
1016 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1017 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1018 StatementMatcher CallExpr
=
1019 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1021 // IntParam does not match.
1022 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr
));
1023 // ArgumentY does not match.
1024 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr
));
1027 TEST(ForEachArgumentWithParamType
, MatchesCXXMemberCallExpr
) {
1028 StatementMatcher ArgumentY
=
1029 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1030 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1031 StatementMatcher CallExpr
=
1032 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1033 EXPECT_TRUE(matchAndVerifyResultTrue(
1035 " const S& operator[](int i) { return *this; }"
1041 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 1)));
1043 StatementMatcher CallExpr2
=
1044 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1045 EXPECT_TRUE(matchAndVerifyResultTrue(
1047 " static void g(int i);"
1053 CallExpr2
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 1)));
1056 TEST(ForEachArgumentWithParamType
, MatchesCallExpr
) {
1057 StatementMatcher ArgumentY
=
1058 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1059 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1060 StatementMatcher CallExpr
=
1061 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1063 EXPECT_TRUE(matchAndVerifyResultTrue(
1064 "void f(int i) { int y; f(y); }", CallExpr
,
1065 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1066 EXPECT_TRUE(matchAndVerifyResultTrue(
1067 "void f(int i) { int y; f(y); }", CallExpr
,
1068 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1070 EXPECT_TRUE(matchAndVerifyResultTrue(
1071 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
1072 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 2)));
1073 EXPECT_TRUE(matchAndVerifyResultTrue(
1074 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
1075 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg", 2)));
1078 TEST(ForEachArgumentWithParamType
, MatchesConstructExpr
) {
1079 StatementMatcher ArgumentY
=
1080 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1081 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1082 StatementMatcher ConstructExpr
=
1083 cxxConstructExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1085 EXPECT_TRUE(matchAndVerifyResultTrue(
1091 ConstructExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1092 EXPECT_TRUE(matchAndVerifyResultTrue(
1098 ConstructExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1101 TEST(ForEachArgumentWithParamType
, HandlesKandRFunctions
) {
1102 StatementMatcher ArgumentY
=
1103 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1104 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1105 StatementMatcher CallExpr
=
1106 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1108 EXPECT_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); }",
1115 TEST(ForEachArgumentWithParamType
, HandlesBoundNodesForNonMatches
) {
1116 EXPECT_TRUE(matchAndVerifyResultTrue(
1117 "void g(int i, int j) {"
1126 forEachDescendant(varDecl().bind("v")),
1127 forEachDescendant(callExpr(forEachArgumentWithParamType(
1128 declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),
1129 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("v", 4)));
1132 TEST(ForEachArgumentWithParamType
, MatchesFunctionPtrCalls
) {
1133 StatementMatcher ArgumentY
=
1134 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1135 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1136 StatementMatcher CallExpr
=
1137 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1139 EXPECT_TRUE(matchAndVerifyResultTrue(
1141 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1142 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1143 EXPECT_TRUE(matchAndVerifyResultTrue(
1145 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1146 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1149 TEST(ForEachArgumentWithParamType
, MatchesMemberFunctionPtrCalls
) {
1150 StatementMatcher ArgumentY
=
1151 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1152 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1153 StatementMatcher CallExpr
=
1154 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1156 StringRef S
= "struct A {\n"
1157 " int f(int i) { return i + 1; }\n"
1158 " int (A::*x)(int);\n"
1166 EXPECT_TRUE(matchAndVerifyResultTrue(
1167 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1168 EXPECT_TRUE(matchAndVerifyResultTrue(
1169 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1172 TEST(ForEachArgumentWithParamType
, MatchesVariadicFunctionPtrCalls
) {
1173 StatementMatcher ArgumentY
=
1174 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1175 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1176 StatementMatcher CallExpr
=
1177 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1179 StringRef S
= R
"cpp(
1180 void fcntl(int fd, int cmd, ...) {}
1182 template <typename Func>
1188 void g() { f(fcntl); }
1191 EXPECT_TRUE(matchAndVerifyResultTrue(
1192 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1193 EXPECT_TRUE(matchAndVerifyResultTrue(
1194 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1197 TEST_P(ASTMatchersTest
,
1198 ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls
) {
1199 if (!GetParam().isCXX23OrLater()) {
1203 auto DeclRef
= declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");
1204 auto SelfTy
= qualType(asString("const A &")).bind("selfType");
1205 StatementMatcher CallExpr
=
1206 callExpr(forEachArgumentWithParamType(DeclRef
, SelfTy
));
1208 StringRef S
= R
"cpp(
1210 int operator()(this const A &self);
1216 auto Args
= GetParam().getCommandLineArgs();
1217 auto Filename
= getFilenameForTesting(GetParam().Language
);
1219 EXPECT_TRUE(matchAndVerifyResultTrue(
1220 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("selfType"),
1222 EXPECT_TRUE(matchAndVerifyResultTrue(
1224 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("declOfArg", "obj"), Args
,
1228 TEST(QualType
, hasCanonicalType
) {
1229 EXPECT_TRUE(notMatches("typedef int &int_ref;"
1232 varDecl(hasType(qualType(referenceType())))));
1234 matches("typedef int &int_ref;"
1237 varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));
1240 TEST(HasParameter
, CallsInnerMatcher
) {
1241 EXPECT_TRUE(matches("class X { void x(int) {} };",
1242 cxxMethodDecl(hasParameter(0, varDecl()))));
1243 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1244 cxxMethodDecl(hasParameter(0, hasName("x")))));
1245 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1246 objcMethodDecl(hasParameter(0, hasName("x")))));
1247 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1248 blockDecl(hasParameter(0, hasName("p")))));
1251 TEST(HasParameter
, DoesNotMatchIfIndexOutOfBounds
) {
1252 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1253 cxxMethodDecl(hasParameter(42, varDecl()))));
1256 TEST(HasType
, MatchesParameterVariableTypesStrictly
) {
1257 EXPECT_TRUE(matches(
1258 "class X { void x(X x) {} };",
1259 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1260 EXPECT_TRUE(notMatches(
1261 "class X { void x(const X &x) {} };",
1262 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1263 EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
1264 cxxMethodDecl(hasParameter(
1265 0, hasType(pointsTo(recordDecl(hasName("X"))))))));
1266 EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
1267 cxxMethodDecl(hasParameter(
1268 0, hasType(references(recordDecl(hasName("X"))))))));
1271 TEST(HasAnyParameter
, MatchesIndependentlyOfPosition
) {
1272 EXPECT_TRUE(matches(
1273 "class Y {}; class X { void x(X x, Y y) {} };",
1274 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1275 EXPECT_TRUE(matches(
1276 "class Y {}; class X { void x(Y y, X x) {} };",
1277 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1278 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1279 objcMethodDecl(hasAnyParameter(hasName("x")))));
1280 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1281 blockDecl(hasAnyParameter(hasName("p")))));
1284 TEST(Returns
, MatchesReturnTypes
) {
1285 EXPECT_TRUE(matches("class Y { int f() { return 1; } };",
1286 functionDecl(returns(asString("int")))));
1287 EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",
1288 functionDecl(returns(asString("float")))));
1289 EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",
1290 functionDecl(returns(hasDeclaration(
1291 recordDecl(hasName("Y")))))));
1294 TEST(HasAnyParameter
, DoesntMatchIfInnerMatcherDoesntMatch
) {
1295 EXPECT_TRUE(notMatches(
1296 "class Y {}; class X { void x(int) {} };",
1297 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1300 TEST(HasAnyParameter
, DoesNotMatchThisPointer
) {
1301 EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
1302 cxxMethodDecl(hasAnyParameter(
1303 hasType(pointsTo(recordDecl(hasName("X"))))))));
1306 TEST(HasName
, MatchesParameterVariableDeclarations
) {
1307 EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
1308 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1309 EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
1310 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1313 TEST(Matcher
, MatchesTypeTemplateArgument
) {
1314 EXPECT_TRUE(matches(
1315 "template<typename T> struct B {};"
1317 classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
1318 asString("int"))))));
1321 TEST(Matcher
, MatchesTemplateTemplateArgument
) {
1322 EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
1323 "template<typename T> class Y {};"
1325 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1326 refersToTemplate(templateName())))));
1329 TEST(Matcher
, MatchesDeclarationReferenceTemplateArgument
) {
1330 EXPECT_TRUE(matches(
1331 "struct B { int next; };"
1332 "template<int(B::*next_ptr)> struct A {};"
1334 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1335 refersToDeclaration(fieldDecl(hasName("next")))))));
1337 EXPECT_TRUE(notMatches(
1338 "template <typename T> struct A {};"
1340 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1341 refersToDeclaration(decl())))));
1343 EXPECT_TRUE(matches(
1344 "struct B { int next; };"
1345 "template<int(B::*next_ptr)> struct A {};"
1347 templateSpecializationType(hasAnyTemplateArgument(isExpr(
1348 hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));
1350 EXPECT_TRUE(notMatches(
1351 "template <typename T> struct A {};"
1353 templateSpecializationType(hasAnyTemplateArgument(
1354 refersToDeclaration(decl())))));
1358 TEST(Matcher
, MatchesSpecificArgument
) {
1359 EXPECT_TRUE(matches(
1360 "template<typename T, typename U> class A {};"
1362 classTemplateSpecializationDecl(hasTemplateArgument(
1363 1, refersToType(asString("int"))))));
1364 EXPECT_TRUE(notMatches(
1365 "template<typename T, typename U> class A {};"
1367 classTemplateSpecializationDecl(hasTemplateArgument(
1368 1, refersToType(asString("int"))))));
1370 EXPECT_TRUE(matches(
1371 "template<typename T, typename U> class A {};"
1373 templateSpecializationType(hasTemplateArgument(
1374 1, refersToType(asString("int"))))));
1375 EXPECT_TRUE(notMatches(
1376 "template<typename T, typename U> class A {};"
1378 templateSpecializationType(hasTemplateArgument(
1379 1, refersToType(asString("int"))))));
1381 EXPECT_TRUE(matches(
1382 "template<typename T> void f() {};"
1383 "void func() { f<int>(); }",
1384 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1385 EXPECT_TRUE(notMatches(
1386 "template<typename T> void f() {};",
1387 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1390 TEST(TemplateArgument
, Matches
) {
1391 EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
1392 classTemplateSpecializationDecl(
1393 hasAnyTemplateArgument(templateArgument()))));
1394 EXPECT_TRUE(matches(
1395 "template<typename T> struct C {}; C<int> c;",
1396 templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
1398 EXPECT_TRUE(matches(
1399 "template<typename T> void f() {};"
1400 "void func() { f<int>(); }",
1401 functionDecl(hasAnyTemplateArgument(templateArgument()))));
1404 TEST(TemplateTypeParmDecl
, CXXMethodDecl
) {
1405 const char input
[] =
1406 "template<typename T>\n"
1410 "template<typename U>\n"
1411 "void Class<U>::method() {}\n";
1412 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1413 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1416 TEST(TemplateTypeParmDecl
, VarDecl
) {
1417 const char input
[] =
1418 "template<typename T>\n"
1422 "template<typename U>\n"
1423 "U Class<U>::pi = U(3.1415926535897932385);\n";
1424 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1425 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1428 TEST(TemplateTypeParmDecl
, VarTemplatePartialSpecializationDecl
) {
1429 const char input
[] =
1430 "template<typename T>\n"
1432 " template<typename T2> static int field;\n"
1434 "template<typename U>\n"
1435 "template<typename U2>\n"
1436 "int Struct<U>::field<U2*> = 123;\n";
1438 matches(input
, templateTypeParmDecl(hasName("T")), langCxx14OrLater()));
1440 matches(input
, templateTypeParmDecl(hasName("T2")), langCxx14OrLater()));
1442 matches(input
, templateTypeParmDecl(hasName("U")), langCxx14OrLater()));
1444 matches(input
, templateTypeParmDecl(hasName("U2")), langCxx14OrLater()));
1447 TEST(TemplateTypeParmDecl
, ClassTemplatePartialSpecializationDecl
) {
1448 const char input
[] =
1449 "template<typename T>\n"
1451 " template<typename T2> struct Struct;\n"
1453 "template<typename U>\n"
1454 "template<typename U2>\n"
1455 "struct Class<U>::Struct<U2*> {};\n";
1456 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1457 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T2"))));
1458 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1459 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U2"))));
1462 TEST(TemplateTypeParmDecl
, EnumDecl
) {
1463 const char input
[] =
1464 "template<typename T>\n"
1466 " enum class Enum : T;\n"
1468 "template<typename U>\n"
1469 "enum class Struct<U>::Enum : U {\n"
1473 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1474 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1477 TEST(TemplateTypeParmDecl
, RecordDecl
) {
1478 const char input
[] =
1479 "template<typename T>\n"
1483 "template<typename U>\n"
1484 "struct Class<U>::Struct {\n"
1487 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1488 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1491 TEST(RefersToIntegralType
, Matches
) {
1492 EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1493 classTemplateSpecializationDecl(
1494 hasAnyTemplateArgument(refersToIntegralType(
1495 asString("int"))))));
1496 EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",
1497 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1498 refersToIntegralType(asString("int"))))));
1501 TEST(ConstructorDeclaration
, SimpleCase
) {
1502 EXPECT_TRUE(matches("class Foo { Foo(int i); };",
1503 cxxConstructorDecl(ofClass(hasName("Foo")))));
1504 EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
1505 cxxConstructorDecl(ofClass(hasName("Bar")))));
1508 TEST(DestructorDeclaration
, MatchesVirtualDestructor
) {
1509 EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
1510 cxxDestructorDecl(ofClass(hasName("Foo")))));
1513 TEST(DestructorDeclaration
, DoesNotMatchImplicitDestructor
) {
1514 EXPECT_TRUE(notMatches("class Foo {};",
1515 cxxDestructorDecl(ofClass(hasName("Foo")))));
1518 TEST(HasAnyConstructorInitializer
, SimpleCase
) {
1520 notMatches("class Foo { Foo() { } };",
1521 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1523 matches("class Foo {"
1524 " Foo() : foo_() { }"
1527 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1530 TEST(HasAnyConstructorInitializer
, ForField
) {
1531 static const char Code
[] =
1534 " Foo() : foo_(), bar_() { }"
1540 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1541 forField(hasType(recordDecl(hasName("Baz"))))))));
1542 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1543 forField(hasName("foo_"))))));
1544 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1545 forField(hasName("bar_"))))));
1546 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1547 forField(hasType(recordDecl(hasName("Bar"))))))));
1550 TEST(HasAnyConstructorInitializer
, WithInitializer
) {
1551 static const char Code
[] =
1553 " Foo() : foo_(0) { }"
1556 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1557 withInitializer(integerLiteral(equals(0)))))));
1558 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1559 withInitializer(integerLiteral(equals(1)))))));
1562 TEST(HasAnyConstructorInitializer
, IsWritten
) {
1563 static const char Code
[] =
1564 "struct Bar { Bar(){} };"
1566 " Foo() : foo_() { }"
1570 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1571 allOf(forField(hasName("foo_")), isWritten())))));
1572 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1573 allOf(forField(hasName("bar_")), isWritten())))));
1574 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1575 allOf(forField(hasName("bar_")), unless(isWritten()))))));
1578 TEST(HasAnyConstructorInitializer
, IsBaseInitializer
) {
1579 static const char Code
[] =
1583 " D(int i) : I(i) {}"
1588 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(allOf(
1589 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1591 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(allOf(
1592 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1594 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(allOf(
1595 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1597 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(allOf(
1598 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1602 TEST(IfStmt
, ChildTraversalMatchers
) {
1603 EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
1604 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1605 EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
1606 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1607 EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
1608 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1609 EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
1610 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1613 TEST(MatchBinaryOperator
, HasOperatorName
) {
1614 StatementMatcher OperatorOr
= binaryOperator(hasOperatorName("||"));
1616 EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr
));
1617 EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr
));
1620 TEST(MatchBinaryOperator
, HasAnyOperatorName
) {
1621 StatementMatcher Matcher
=
1622 binaryOperator(hasAnyOperatorName("+", "-", "*", "/"));
1624 EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher
));
1625 EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher
));
1626 EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher
));
1627 EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher
));
1628 EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher
));
1629 // Ensure '+= isn't mistaken.
1630 EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher
));
1633 TEST(MatchBinaryOperator
, HasLHSAndHasRHS
) {
1634 StatementMatcher OperatorTrueFalse
=
1635 binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),
1636 hasRHS(cxxBoolLiteral(equals(false))));
1638 EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse
));
1639 EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse
));
1640 EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse
));
1642 StatementMatcher OperatorIntPointer
= arraySubscriptExpr(
1643 hasLHS(hasType(isInteger())),
1644 traverse(TK_AsIs
, hasRHS(hasType(pointsTo(qualType())))));
1645 EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer
));
1646 EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer
));
1648 StringRef Code
= R
"cpp(
1651 bool operator==(const HasOpEqMem& other) const
1660 bool operator==(const HasOpFree& lhs, const HasOpFree& rhs)
1681 auto s1Expr
= declRefExpr(to(varDecl(hasName("s1"))));
1682 auto s2Expr
= declRefExpr(to(varDecl(hasName("s2"))));
1683 EXPECT_TRUE(matches(
1685 traverse(TK_IgnoreUnlessSpelledInSource
,
1686 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1687 hasOperatorName("=="), hasLHS(s1Expr
),
1689 EXPECT_TRUE(matches(
1690 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1691 cxxOperatorCallExpr(
1692 forFunction(functionDecl(hasName("opMem"))),
1693 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr
)))));
1694 EXPECT_TRUE(matches(
1695 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1696 cxxOperatorCallExpr(
1697 forFunction(functionDecl(hasName("opMem"))),
1698 hasOperatorName("=="), hasOperands(s1Expr
, s2Expr
)))));
1699 EXPECT_TRUE(matches(
1700 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1701 cxxOperatorCallExpr(
1702 forFunction(functionDecl(hasName("opMem"))),
1703 hasOperatorName("=="), hasEitherOperand(s2Expr
)))));
1705 EXPECT_TRUE(matches(
1707 traverse(TK_IgnoreUnlessSpelledInSource
,
1708 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1709 hasOperatorName("=="), hasLHS(s1Expr
),
1711 EXPECT_TRUE(matches(
1712 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1713 cxxOperatorCallExpr(
1714 forFunction(functionDecl(hasName("opFree"))),
1715 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr
)))));
1716 EXPECT_TRUE(matches(
1717 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1718 cxxOperatorCallExpr(
1719 forFunction(functionDecl(hasName("opFree"))),
1720 hasOperatorName("=="), hasOperands(s1Expr
, s2Expr
)))));
1721 EXPECT_TRUE(matches(
1722 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1723 cxxOperatorCallExpr(
1724 forFunction(functionDecl(hasName("opFree"))),
1725 hasOperatorName("=="), hasEitherOperand(s2Expr
)))));
1728 TEST(MatchBinaryOperator
, HasEitherOperand
) {
1729 StatementMatcher HasOperand
=
1730 binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));
1732 EXPECT_TRUE(matches("void x() { true || false; }", HasOperand
));
1733 EXPECT_TRUE(matches("void x() { false && true; }", HasOperand
));
1734 EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand
));
1737 TEST(MatchBinaryOperator
, HasOperands
) {
1738 StatementMatcher HasOperands
= binaryOperator(
1739 hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2))));
1740 EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands
));
1741 EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands
));
1742 EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands
));
1743 EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands
));
1744 EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands
));
1745 EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands
));
1748 TEST(MatchBinaryOperator
, HasOperandsEnsureOrdering
) {
1749 StatementMatcher HasOperandsWithBindings
= binaryOperator(hasOperands(
1750 cStyleCastExpr(has(declRefExpr(hasDeclaration(valueDecl().bind("d"))))),
1751 declRefExpr(hasDeclaration(valueDecl(equalsBoundNode("d"))))));
1752 EXPECT_TRUE(matches(
1753 "int a; int b = ((int) a) + a;",
1754 traverse(TK_IgnoreUnlessSpelledInSource
, HasOperandsWithBindings
)));
1755 EXPECT_TRUE(matches(
1756 "int a; int b = a + ((int) a);",
1757 traverse(TK_IgnoreUnlessSpelledInSource
, HasOperandsWithBindings
)));
1760 TEST(Matcher
, BinaryOperatorTypes
) {
1761 // Integration test that verifies the AST provides all binary operators in
1763 // FIXME: Operator ','
1765 matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));
1767 matches("bool b; bool c = (b = true);",
1768 binaryOperator(hasOperatorName("="))));
1770 matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));
1772 matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));
1773 EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));
1775 matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));
1777 matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));
1779 matches("int i = 1; int j = (i <<= 2);",
1780 binaryOperator(hasOperatorName("<<="))));
1781 EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));
1783 matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));
1785 matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));
1787 matches("int i = 1; int j = (i >>= 2);",
1788 binaryOperator(hasOperatorName(">>="))));
1790 matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));
1792 matches("int i = 42; int j = (i ^= 42);",
1793 binaryOperator(hasOperatorName("^="))));
1795 matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));
1797 matches("int i = 42; int j = (i %= 42);",
1798 binaryOperator(hasOperatorName("%="))));
1800 matches("bool b = 42 &23;", binaryOperator(hasOperatorName("&"))));
1802 matches("bool b = true && false;",
1803 binaryOperator(hasOperatorName("&&"))));
1805 matches("bool b = true; bool c = (b &= false);",
1806 binaryOperator(hasOperatorName("&="))));
1808 matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));
1810 matches("bool b = true || false;",
1811 binaryOperator(hasOperatorName("||"))));
1813 matches("bool b = true; bool c = (b |= false);",
1814 binaryOperator(hasOperatorName("|="))));
1816 matches("int i = 42 *23;", binaryOperator(hasOperatorName("*"))));
1818 matches("int i = 42; int j = (i *= 23);",
1819 binaryOperator(hasOperatorName("*="))));
1821 matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));
1823 matches("int i = 42; int j = (i /= 23);",
1824 binaryOperator(hasOperatorName("/="))));
1826 matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));
1828 matches("int i = 42; int j = (i += 23);",
1829 binaryOperator(hasOperatorName("+="))));
1831 matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));
1833 matches("int i = 42; int j = (i -= 23);",
1834 binaryOperator(hasOperatorName("-="))));
1836 matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",
1837 binaryOperator(hasOperatorName("->*"))));
1839 matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",
1840 binaryOperator(hasOperatorName(".*"))));
1842 // Member expressions as operators are not supported in matches.
1844 notMatches("struct A { void x(A *a) { a->x(this); } };",
1845 binaryOperator(hasOperatorName("->"))));
1847 // Initializer assignments are not represented as operator equals.
1849 notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));
1851 // Array indexing is not represented as operator.
1852 EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));
1854 // Overloaded operators do not match at all.
1855 EXPECT_TRUE(notMatches(
1856 "struct A { bool operator&&(const A &a) const { return false; } };"
1857 "void x() { A a, b; a && b; }",
1861 TEST(MatchUnaryOperator
, HasOperatorName
) {
1862 StatementMatcher OperatorNot
= unaryOperator(hasOperatorName("!"));
1864 EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot
));
1865 EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot
));
1868 TEST(MatchUnaryOperator
, HasAnyOperatorName
) {
1869 StatementMatcher Matcher
= unaryOperator(hasAnyOperatorName("-", "*", "++"));
1871 EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher
));
1872 EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher
));
1873 EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher
));
1874 EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher
));
1875 EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher
));
1876 EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher
));
1877 EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher
));
1880 TEST(MatchUnaryOperator
, HasUnaryOperand
) {
1881 StatementMatcher OperatorOnFalse
=
1882 unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));
1884 EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse
));
1885 EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse
));
1887 StringRef Code
= R
"cpp(
1890 bool operator!() const
1895 struct HasOpBangFree
1898 bool operator!(HasOpBangFree const&)
1916 auto s1Expr
= declRefExpr(to(varDecl(hasName("s1"))));
1917 EXPECT_TRUE(matches(
1918 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1919 cxxOperatorCallExpr(
1920 forFunction(functionDecl(hasName("opMem"))),
1921 hasOperatorName("!"), hasUnaryOperand(s1Expr
)))));
1922 EXPECT_TRUE(matches(
1924 traverse(TK_IgnoreUnlessSpelledInSource
,
1925 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1926 hasAnyOperatorName("+", "!"),
1927 hasUnaryOperand(s1Expr
)))));
1929 EXPECT_TRUE(matches(
1930 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1931 cxxOperatorCallExpr(
1932 forFunction(functionDecl(hasName("opFree"))),
1933 hasOperatorName("!"), hasUnaryOperand(s1Expr
)))));
1934 EXPECT_TRUE(matches(
1936 traverse(TK_IgnoreUnlessSpelledInSource
,
1937 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1938 hasAnyOperatorName("+", "!"),
1939 hasUnaryOperand(s1Expr
)))));
1942 struct HasIncOperatorsMem
1944 HasIncOperatorsMem& operator++();
1945 HasIncOperatorsMem operator++(int);
1947 struct HasIncOperatorsFree
1950 HasIncOperatorsFree& operator++(HasIncOperatorsFree&);
1951 HasIncOperatorsFree operator++(HasIncOperatorsFree&, int);
1953 void prefixIncOperatorMem()
1955 HasIncOperatorsMem s1;
1958 void prefixIncOperatorFree()
1960 HasIncOperatorsFree s1;
1963 void postfixIncOperatorMem()
1965 HasIncOperatorsMem s1;
1968 void postfixIncOperatorFree()
1970 HasIncOperatorsFree s1;
1976 HasOpPlusInt& operator+(int);
1978 void plusIntOperator()
1985 EXPECT_TRUE(matches(
1987 traverse(TK_IgnoreUnlessSpelledInSource
,
1988 cxxOperatorCallExpr(
1989 forFunction(functionDecl(hasName("prefixIncOperatorMem"))),
1990 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1992 EXPECT_TRUE(matches(
1994 traverse(TK_IgnoreUnlessSpelledInSource
,
1995 cxxOperatorCallExpr(
1996 forFunction(functionDecl(hasName("prefixIncOperatorFree"))),
1997 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1999 EXPECT_TRUE(matches(
2001 traverse(TK_IgnoreUnlessSpelledInSource
,
2002 cxxOperatorCallExpr(
2003 forFunction(functionDecl(hasName("postfixIncOperatorMem"))),
2004 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2006 EXPECT_TRUE(matches(
2008 traverse(TK_IgnoreUnlessSpelledInSource
,
2009 cxxOperatorCallExpr(
2010 forFunction(functionDecl(hasName("postfixIncOperatorFree"))),
2011 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2013 EXPECT_FALSE(matches(
2014 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2015 cxxOperatorCallExpr(
2016 forFunction(functionDecl(hasName("plusIntOperator"))),
2017 hasOperatorName("+"), hasUnaryOperand(expr())))));
2032 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2033 cxxOperatorCallExpr(hasOperatorName("*"),
2034 hasUnaryOperand(expr())))));
2037 TEST(Matcher
, UnaryOperatorTypes
) {
2038 // Integration test that verifies the AST provides all unary operators in
2040 EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));
2042 matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));
2043 EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));
2045 matches("bool *p; bool b = *p;", unaryOperator(hasOperatorName("*"))));
2047 matches("int i; int j = +i;", unaryOperator(hasOperatorName("+"))));
2049 matches("int i; int j = -i;", unaryOperator(hasOperatorName("-"))));
2051 matches("int i; int j = ++i;", unaryOperator(hasOperatorName("++"))));
2053 matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));
2055 matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));
2057 matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));
2059 // We don't match conversion operators.
2060 EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));
2062 // Function calls are not represented as operator.
2063 EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));
2065 // Overloaded operators do not match at all.
2066 // FIXME: We probably want to add that.
2067 EXPECT_TRUE(notMatches(
2068 "struct A { bool operator!() const { return false; } };"
2069 "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
2072 TEST_P(ASTMatchersTest
, HasInit
) {
2073 if (!GetParam().isCXX11OrLater()) {
2074 // FIXME: Add a test for `hasInit()` that does not depend on C++.
2078 EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));
2079 EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));
2080 EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));
2083 TEST_P(ASTMatchersTest
, HasFoldInit
) {
2084 if (!GetParam().isCXX17OrLater()) {
2088 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2089 "return (0 + ... + args); }",
2090 cxxFoldExpr(hasFoldInit(expr()))));
2091 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2092 "return (args + ... + 0); }",
2093 cxxFoldExpr(hasFoldInit(expr()))));
2094 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2095 "return (... + args); };",
2096 cxxFoldExpr(hasFoldInit(expr()))));
2099 TEST_P(ASTMatchersTest
, HasPattern
) {
2100 if (!GetParam().isCXX17OrLater()) {
2104 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2105 "return (0 + ... + args); }",
2106 cxxFoldExpr(hasPattern(expr()))));
2107 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2108 "return (args + ... + 0); }",
2109 cxxFoldExpr(hasPattern(expr()))));
2110 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2111 "return (... + args); };",
2112 cxxFoldExpr(hasPattern(expr()))));
2115 TEST_P(ASTMatchersTest
, HasLHSAndHasRHS
) {
2116 if (!GetParam().isCXX17OrLater()) {
2120 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2121 "return (0 + ... + args); }",
2122 cxxFoldExpr(hasLHS(expr()))));
2123 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2124 "return (args + ... + 0); }",
2125 cxxFoldExpr(hasLHS(expr()))));
2126 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2127 "return (... + args); };",
2128 cxxFoldExpr(hasLHS(expr()))));
2129 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2130 "return (args + ...); };",
2131 cxxFoldExpr(hasLHS(expr()))));
2133 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2134 "return (0 + ... + args); }",
2135 cxxFoldExpr(hasRHS(expr()))));
2136 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2137 "return (args + ... + 0); }",
2138 cxxFoldExpr(hasRHS(expr()))));
2139 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2140 "return (... + args); };",
2141 cxxFoldExpr(hasRHS(expr()))));
2142 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2143 "return (args + ...); };",
2144 cxxFoldExpr(hasRHS(expr()))));
2147 TEST_P(ASTMatchersTest
, HasEitherOperandAndHasOperands
) {
2148 if (!GetParam().isCXX17OrLater()) {
2152 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2153 "return (0 + ... + args); }",
2154 cxxFoldExpr(hasEitherOperand(integerLiteral()))));
2155 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2156 "return (args + ... + 0); }",
2157 cxxFoldExpr(hasEitherOperand(integerLiteral()))));
2159 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2160 "return (0 + ... + args); }",
2161 cxxFoldExpr(hasEitherOperand(
2162 declRefExpr(to(namedDecl(hasName("args"))))))));
2163 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2164 "return (args + ... + 0); }",
2165 cxxFoldExpr(hasEitherOperand(
2166 declRefExpr(to(namedDecl(hasName("args"))))))));
2167 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2168 "return (... + args); };",
2169 cxxFoldExpr(hasEitherOperand(
2170 declRefExpr(to(namedDecl(hasName("args"))))))));
2171 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2172 "return (args + ...); };",
2173 cxxFoldExpr(hasEitherOperand(
2174 declRefExpr(to(namedDecl(hasName("args"))))))));
2176 EXPECT_TRUE(matches(
2177 "template <typename... Args> auto sum(Args... args) { "
2178 "return (0 + ... + args); }",
2179 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2180 integerLiteral()))));
2181 EXPECT_TRUE(matches(
2182 "template <typename... Args> auto sum(Args... args) { "
2183 "return (args + ... + 0); }",
2184 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2185 integerLiteral()))));
2186 EXPECT_FALSE(matches(
2187 "template <typename... Args> auto sum(Args... args) { "
2188 "return (... + args); };",
2189 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2190 integerLiteral()))));
2191 EXPECT_FALSE(matches(
2192 "template <typename... Args> auto sum(Args... args) { "
2193 "return (args + ...); };",
2194 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2195 integerLiteral()))));
2198 TEST_P(ASTMatchersTest
, Callee
) {
2199 if (!GetParam().isCXX17OrLater()) {
2203 EXPECT_TRUE(matches(
2204 "struct Dummy {}; Dummy operator+(Dummy, Dummy); template "
2205 "<typename... Args> auto sum(Args... args) { return (0 + ... + args); }",
2206 cxxFoldExpr(callee(expr()))));
2207 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2208 "return (0 + ... + args); }",
2209 cxxFoldExpr(callee(expr()))));
2212 TEST(ArraySubscriptMatchers
, ArrayIndex
) {
2213 EXPECT_TRUE(matches(
2214 "int i[2]; void f() { i[1] = 1; }",
2215 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2216 EXPECT_TRUE(matches(
2217 "int i[2]; void f() { 1[i] = 1; }",
2218 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2219 EXPECT_TRUE(notMatches(
2220 "int i[2]; void f() { i[1] = 1; }",
2221 arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));
2224 TEST(ArraySubscriptMatchers
, MatchesArrayBase
) {
2226 matches("int i[2]; void f() { i[1] = 2; }",
2227 traverse(TK_AsIs
, arraySubscriptExpr(hasBase(implicitCastExpr(
2228 hasSourceExpression(declRefExpr())))))));
2231 TEST(Matcher
, OfClass
) {
2232 StatementMatcher Constructor
= cxxConstructExpr(hasDeclaration(cxxMethodDecl(
2233 ofClass(hasName("X")))));
2236 matches("class X { public: X(); }; void x(int) { X x; }", Constructor
));
2238 matches("class X { public: X(); }; void x(int) { X x = X(); }",
2241 notMatches("class Y { public: Y(); }; void x(int) { Y y; }",
2245 TEST(Matcher
, VisitsTemplateInstantiations
) {
2246 EXPECT_TRUE(matches(
2247 "class A { public: void x(); };"
2248 "template <typename T> class B { public: void y() { T t; t.x(); } };"
2249 "void f() { B<A> b; b.y(); }",
2250 callExpr(callee(cxxMethodDecl(hasName("x"))))));
2252 EXPECT_TRUE(matches(
2253 "class A { public: void x(); };"
2256 " template <typename T> class B { public: void y() { T t; t.x(); } };"
2259 " C::B<A> b; b.y();"
2261 recordDecl(hasName("C"), hasDescendant(callExpr(
2262 callee(cxxMethodDecl(hasName("x"))))))));
2265 TEST(Matcher
, HasCondition
) {
2266 StatementMatcher IfStmt
=
2267 ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
2268 EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt
));
2269 EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt
));
2271 StatementMatcher ForStmt
=
2272 forStmt(hasCondition(cxxBoolLiteral(equals(true))));
2273 EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt
));
2274 EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt
));
2276 StatementMatcher WhileStmt
=
2277 whileStmt(hasCondition(cxxBoolLiteral(equals(true))));
2278 EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt
));
2279 EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt
));
2281 StatementMatcher SwitchStmt
=
2282 switchStmt(hasCondition(integerLiteral(equals(42))));
2283 EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt
));
2284 EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt
));
2287 TEST(For
, ForLoopInternals
) {
2288 EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
2289 forStmt(hasCondition(anything()))));
2290 EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
2291 forStmt(hasLoopInit(anything()))));
2294 TEST(For
, ForRangeLoopInternals
) {
2295 EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
2296 cxxForRangeStmt(hasLoopVariable(anything()))));
2297 EXPECT_TRUE(matches(
2298 "void f(){ int a[] {1, 2}; for (int i : a); }",
2299 cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
2302 TEST(For
, NegativeForLoopInternals
) {
2303 EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
2304 forStmt(hasCondition(expr()))));
2305 EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
2306 forStmt(hasLoopInit(anything()))));
2309 TEST(HasBody
, FindsBodyOfForWhileDoLoops
) {
2310 EXPECT_TRUE(matches("void f() { for(;;) {} }",
2311 forStmt(hasBody(compoundStmt()))));
2312 EXPECT_TRUE(notMatches("void f() { for(;;); }",
2313 forStmt(hasBody(compoundStmt()))));
2314 EXPECT_TRUE(matches("void f() { while(true) {} }",
2315 whileStmt(hasBody(compoundStmt()))));
2316 EXPECT_TRUE(matches("void f() { do {} while(true); }",
2317 doStmt(hasBody(compoundStmt()))));
2318 EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
2319 cxxForRangeStmt(hasBody(compoundStmt()))));
2322 TEST(HasBody
, FindsBodyOfFunctions
) {
2323 EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));
2324 EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));
2325 EXPECT_TRUE(matchAndVerifyResultTrue(
2326 "void f(); void f() {}",
2327 functionDecl(hasBody(compoundStmt())).bind("func"),
2328 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("func", 1)));
2329 EXPECT_TRUE(matchAndVerifyResultTrue(
2330 "class C { void f(); }; void C::f() {}",
2331 cxxMethodDecl(hasBody(compoundStmt())).bind("met"),
2332 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("met", 1)));
2333 EXPECT_TRUE(matchAndVerifyResultTrue(
2334 "class C { C(); }; C::C() {}",
2335 cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),
2336 std::make_unique
<VerifyIdIsBoundTo
<CXXConstructorDecl
>>("ctr", 1)));
2337 EXPECT_TRUE(matchAndVerifyResultTrue(
2338 "class C { ~C(); }; C::~C() {}",
2339 cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),
2340 std::make_unique
<VerifyIdIsBoundTo
<CXXDestructorDecl
>>("dtr", 1)));
2343 TEST(HasAnyBody
, FindsAnyBodyOfFunctions
) {
2344 EXPECT_TRUE(matches("void f() {}", functionDecl(hasAnyBody(compoundStmt()))));
2345 EXPECT_TRUE(notMatches("void f();",
2346 functionDecl(hasAnyBody(compoundStmt()))));
2347 EXPECT_TRUE(matchAndVerifyResultTrue(
2348 "void f(); void f() {}",
2349 functionDecl(hasAnyBody(compoundStmt())).bind("func"),
2350 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("func", 2)));
2351 EXPECT_TRUE(matchAndVerifyResultTrue(
2352 "class C { void f(); }; void C::f() {}",
2353 cxxMethodDecl(hasAnyBody(compoundStmt())).bind("met"),
2354 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("met", 2)));
2355 EXPECT_TRUE(matchAndVerifyResultTrue(
2356 "class C { C(); }; C::C() {}",
2357 cxxConstructorDecl(hasAnyBody(compoundStmt())).bind("ctr"),
2358 std::make_unique
<VerifyIdIsBoundTo
<CXXConstructorDecl
>>("ctr", 2)));
2359 EXPECT_TRUE(matchAndVerifyResultTrue(
2360 "class C { ~C(); }; C::~C() {}",
2361 cxxDestructorDecl(hasAnyBody(compoundStmt())).bind("dtr"),
2362 std::make_unique
<VerifyIdIsBoundTo
<CXXDestructorDecl
>>("dtr", 2)));
2365 TEST(HasAnySubstatement
, MatchesForTopLevelCompoundStatement
) {
2366 // The simplest case: every compound statement is in a function
2367 // definition, and the function body itself must be a compound
2369 EXPECT_TRUE(matches("void f() { for (;;); }",
2370 compoundStmt(hasAnySubstatement(forStmt()))));
2373 TEST(HasAnySubstatement
, IsNotRecursive
) {
2374 // It's really "has any immediate substatement".
2375 EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
2376 compoundStmt(hasAnySubstatement(forStmt()))));
2379 TEST(HasAnySubstatement
, MatchesInNestedCompoundStatements
) {
2380 EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
2381 compoundStmt(hasAnySubstatement(forStmt()))));
2384 TEST(HasAnySubstatement
, FindsSubstatementBetweenOthers
) {
2385 EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
2386 compoundStmt(hasAnySubstatement(forStmt()))));
2389 TEST(Member
, MatchesMemberAllocationFunction
) {
2390 // Fails in C++11 mode
2391 EXPECT_TRUE(matchesConditionally(
2392 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2393 "class X { void *operator new(std::size_t); };",
2394 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2396 EXPECT_TRUE(matches("class X { void operator delete(void*); };",
2397 cxxMethodDecl(ofClass(hasName("X")))));
2399 // Fails in C++11 mode
2400 EXPECT_TRUE(matchesConditionally(
2401 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2402 "class X { void operator delete[](void*, std::size_t); };",
2403 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2406 TEST(HasDestinationType
, MatchesSimpleCase
) {
2407 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
2408 cxxStaticCastExpr(hasDestinationType(
2409 pointsTo(TypeMatcher(anything()))))));
2412 TEST(HasImplicitDestinationType
, MatchesSimpleCase
) {
2413 // This test creates an implicit const cast.
2414 EXPECT_TRUE(matches(
2415 "int x; const int i = x;",
2417 implicitCastExpr(hasImplicitDestinationType(isInteger())))));
2418 // This test creates an implicit array-to-pointer cast.
2420 matches("int arr[3]; int *p = arr;",
2421 traverse(TK_AsIs
, implicitCastExpr(hasImplicitDestinationType(
2422 pointsTo(TypeMatcher(anything())))))));
2425 TEST(HasImplicitDestinationType
, DoesNotMatchIncorrectly
) {
2426 // This test creates an implicit cast from int to char.
2427 EXPECT_TRUE(notMatches("char c = 0;",
2428 implicitCastExpr(hasImplicitDestinationType(
2429 unless(anything())))));
2430 // This test creates an implicit array-to-pointer cast.
2431 EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
2432 implicitCastExpr(hasImplicitDestinationType(
2433 unless(anything())))));
2436 TEST(Matcher
, IgnoresElidableConstructors
) {
2438 matches("struct H {};"
2439 "template<typename T> H B(T A);"
2444 cxxOperatorCallExpr(hasArgument(
2445 1, callExpr(hasArgument(
2446 0, ignoringElidableConstructorCall(callExpr()))))),
2447 langCxx11OrLater()));
2449 matches("struct H {};"
2450 "template<typename T> H B(T A);"
2455 cxxOperatorCallExpr(hasArgument(
2456 1, callExpr(hasArgument(0, ignoringElidableConstructorCall(
2457 integerLiteral()))))),
2458 langCxx11OrLater()));
2459 EXPECT_TRUE(matches(
2465 varDecl(hasInitializer(anyOf(
2466 ignoringElidableConstructorCall(callExpr()),
2467 exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())))))),
2468 langCxx11OrLater()));
2471 TEST(Matcher
, IgnoresElidableInReturn
) {
2472 auto matcher
= expr(ignoringElidableConstructorCall(declRefExpr()));
2473 EXPECT_TRUE(matches("struct H {};"
2478 matcher
, langCxx11OrLater()));
2479 EXPECT_TRUE(notMatches("struct H {};"
2483 matcher
, langCxx11OrLater()));
2486 TEST(Matcher
, IgnoreElidableConstructorDoesNotMatchConstructors
) {
2487 EXPECT_TRUE(matches("struct H {};"
2491 varDecl(hasInitializer(
2492 ignoringElidableConstructorCall(cxxConstructExpr()))),
2493 langCxx11OrLater()));
2496 TEST(Matcher
, IgnoresElidableDoesNotPreventMatches
) {
2497 EXPECT_TRUE(matches("void f() {"
2500 expr(ignoringElidableConstructorCall(integerLiteral())),
2501 langCxx11OrLater()));
2504 TEST(Matcher
, IgnoresElidableInVarInit
) {
2506 varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())));
2507 EXPECT_TRUE(matches("struct H {};"
2509 "void f(H D = G()) {"
2512 matcher
, langCxx11OrLater()));
2513 EXPECT_TRUE(matches("struct H {};"
2518 matcher
, langCxx11OrLater()));
2521 TEST(IgnoringImplicit
, MatchesImplicit
) {
2522 EXPECT_TRUE(matches("class C {}; C a = C();",
2523 varDecl(has(ignoringImplicit(cxxConstructExpr())))));
2526 TEST(IgnoringImplicit
, MatchesNestedImplicit
) {
2527 StringRef Code
= R
"(
2534 SomeType(const OtherType&) {}
2535 SomeType& operator=(OtherType const&) { return *this; }
2544 OtherType something()
2551 SomeType i = something();
2554 EXPECT_TRUE(matches(
2557 varDecl(hasName("i"),
2558 hasInitializer(exprWithCleanups(has(cxxConstructExpr(
2559 has(expr(ignoringImplicit(cxxConstructExpr(has(
2560 expr(ignoringImplicit(callExpr())))))))))))))));
2563 TEST(IgnoringImplicit
, DoesNotMatchIncorrectly
) {
2564 EXPECT_TRUE(notMatches("class C {}; C a = C();",
2565 traverse(TK_AsIs
, varDecl(has(cxxConstructExpr())))));
2568 TEST(Traversal
, traverseMatcher
) {
2570 StringRef VarDeclCode
= R
"cpp(
2577 auto Matcher
= varDecl(hasInitializer(floatLiteral()));
2579 EXPECT_TRUE(notMatches(VarDeclCode
, traverse(TK_AsIs
, Matcher
)));
2581 matches(VarDeclCode
, traverse(TK_IgnoreUnlessSpelledInSource
, Matcher
)));
2583 auto ParentMatcher
= floatLiteral(hasParent(varDecl(hasName("i"))));
2585 EXPECT_TRUE(notMatches(VarDeclCode
, traverse(TK_AsIs
, ParentMatcher
)));
2586 EXPECT_TRUE(matches(VarDeclCode
,
2587 traverse(TK_IgnoreUnlessSpelledInSource
, ParentMatcher
)));
2589 EXPECT_TRUE(matches(
2590 VarDeclCode
, decl(traverse(TK_AsIs
, anyOf(cxxRecordDecl(), varDecl())))));
2593 matches(VarDeclCode
,
2594 floatLiteral(traverse(TK_AsIs
, hasParent(implicitCastExpr())))));
2597 matches(VarDeclCode
, floatLiteral(traverse(TK_IgnoreUnlessSpelledInSource
,
2598 hasParent(varDecl())))));
2601 matches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2602 unless(parmVarDecl())))));
2605 notMatches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2606 has(implicitCastExpr())))));
2608 EXPECT_TRUE(matches(VarDeclCode
,
2609 varDecl(traverse(TK_AsIs
, has(implicitCastExpr())))));
2611 EXPECT_TRUE(matches(
2612 VarDeclCode
, traverse(TK_IgnoreUnlessSpelledInSource
,
2613 // The has() below strips away the ImplicitCastExpr
2614 // before the traverse(AsIs) gets to process it.
2615 varDecl(has(traverse(TK_AsIs
, floatLiteral()))))));
2618 matches(VarDeclCode
, functionDecl(traverse(TK_AsIs
, hasName("foo")))));
2620 EXPECT_TRUE(matches(
2622 functionDecl(traverse(TK_IgnoreUnlessSpelledInSource
, hasName("foo")))));
2624 EXPECT_TRUE(matches(
2625 VarDeclCode
, functionDecl(traverse(TK_AsIs
, hasAnyName("foo", "bar")))));
2628 matches(VarDeclCode
, functionDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2629 hasAnyName("foo", "bar")))));
2631 StringRef Code
= R
"cpp(
2642 matches(Code
, callExpr(traverse(TK_IgnoreUnlessSpelledInSource
,
2643 hasArgument(0, floatLiteral())))));
2646 matches(Code
, callExpr(traverse(TK_IgnoreUnlessSpelledInSource
,
2647 hasAnyArgument(floatLiteral())))));
2649 EXPECT_TRUE(matches(
2651 void takesBool(bool){}
2653 template <typename T>
2654 void neverInstantiatedTemplate() {
2658 traverse(TK_IgnoreUnlessSpelledInSource
,
2659 callExpr(unless(callExpr(hasDeclaration(functionDecl())))))));
2662 matches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2663 hasType(builtinType())))));
2666 matches(VarDeclCode
,
2667 functionDecl(hasName("foo"),
2668 traverse(TK_AsIs
, hasDescendant(floatLiteral())))));
2670 EXPECT_TRUE(notMatches(
2671 Code
, traverse(TK_AsIs
, floatLiteral(hasParent(callExpr(
2672 callee(functionDecl(hasName("foo")))))))));
2673 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2674 floatLiteral(hasParent(callExpr(callee(
2675 functionDecl(hasName("foo")))))))));
2683 EXPECT_TRUE(matches(
2684 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2685 varDecl(hasInitializer(integerLiteral(equals(3)))))));
2686 EXPECT_TRUE(matches(
2688 traverse(TK_IgnoreUnlessSpelledInSource
,
2689 integerLiteral(equals(3), hasParent(varDecl(hasName("i")))))));
2692 const char *SomeString{"str
"};
2695 matches(Code
, traverse(TK_AsIs
, stringLiteral(hasParent(implicitCastExpr(
2696 hasParent(initListExpr())))))));
2698 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2699 stringLiteral(hasParent(initListExpr())))));
2704 String(const char*, int = -1) {}
2707 void stringConstruct()
2713 EXPECT_TRUE(matches(
2718 hasName("stringConstruct"),
2719 hasDescendant(varDecl(
2721 hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(
2722 0, ignoringImplicit(cxxConstructExpr(hasArgument(
2723 0, ignoringImplicit(stringLiteral()))))))))))))));
2725 EXPECT_TRUE(matches(
2729 functionDecl(hasName("stringConstruct"),
2730 hasDescendant(cxxOperatorCallExpr(
2731 isAssignmentOperator(),
2732 hasArgument(1, ignoringImplicit(
2733 cxxConstructExpr(hasArgument(
2734 0, ignoringImplicit(stringLiteral())))))
2737 EXPECT_TRUE(matches(
2738 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2739 functionDecl(hasName("stringConstruct"),
2740 hasDescendant(varDecl(
2742 hasInitializer(stringLiteral())))))));
2745 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2746 functionDecl(hasName("stringConstruct"),
2747 hasDescendant(cxxOperatorCallExpr(
2748 isAssignmentOperator(),
2749 hasArgument(1, stringLiteral())))))));
2754 struct C2 { operator C1(); };
2756 void conversionOperator()
2763 EXPECT_TRUE(matches(
2768 hasName("conversionOperator"),
2773 ignoringImplicit(cxxConstructExpr(hasArgument(
2774 0, ignoringImplicit(
2775 cxxMemberCallExpr(onImplicitObjectArgument(
2776 ignoringParenImpCasts(unaryOperator(
2777 hasOperatorName("*")))))))))))
2780 EXPECT_TRUE(matches(
2782 traverse(TK_IgnoreUnlessSpelledInSource
,
2783 functionDecl(hasName("conversionOperator"),
2784 hasDescendant(varDecl(
2785 hasName("c1"), hasInitializer(unaryOperator(
2786 hasOperatorName("*")))))))));
2790 template <unsigned alignment>
2791 void template_test() {
2792 static_assert(alignment, "");
2794 void actual_template_test() {
2799 EXPECT_TRUE(matches(
2802 staticAssertDecl(has(implicitCastExpr(has(
2803 substNonTypeTemplateParmExpr(has(integerLiteral())))))))));
2804 EXPECT_TRUE(matches(
2805 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2806 staticAssertDecl(has(declRefExpr(
2807 to(nonTypeTemplateParmDecl(hasName("alignment"))),
2808 hasType(asString("unsigned int"))))))));
2810 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, staticAssertDecl(hasDescendant(
2811 integerLiteral())))));
2812 EXPECT_FALSE(matches(
2813 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2814 staticAssertDecl(hasDescendant(integerLiteral())))));
2818 struct OneParamCtor {
2819 explicit OneParamCtor(int);
2821 struct TwoParamCtor {
2822 explicit TwoParamCtor(int, int);
2825 void varDeclCtors() {
2827 auto var1 = OneParamCtor(5);
2828 auto var2 = TwoParamCtor(6, 7);
2831 OneParamCtor var3(5);
2832 TwoParamCtor var4(6, 7);
2836 auto var5 = OneParamCtor(i);
2837 auto var6 = TwoParamCtor(i, 7);
2840 OneParamCtor var7(i);
2841 TwoParamCtor var8(i, 7);
2846 EXPECT_TRUE(matches(
2848 traverse(TK_AsIs
, varDecl(hasName("var1"), hasInitializer(hasDescendant(
2849 cxxConstructExpr()))))));
2850 EXPECT_TRUE(matches(
2852 traverse(TK_AsIs
, varDecl(hasName("var2"), hasInitializer(hasDescendant(
2853 cxxConstructExpr()))))));
2854 EXPECT_TRUE(matches(
2855 Code
, traverse(TK_AsIs
, varDecl(hasName("var3"),
2856 hasInitializer(cxxConstructExpr())))));
2857 EXPECT_TRUE(matches(
2858 Code
, traverse(TK_AsIs
, varDecl(hasName("var4"),
2859 hasInitializer(cxxConstructExpr())))));
2860 EXPECT_TRUE(matches(
2862 traverse(TK_AsIs
, varDecl(hasName("var5"), hasInitializer(hasDescendant(
2863 cxxConstructExpr()))))));
2864 EXPECT_TRUE(matches(
2866 traverse(TK_AsIs
, varDecl(hasName("var6"), hasInitializer(hasDescendant(
2867 cxxConstructExpr()))))));
2868 EXPECT_TRUE(matches(
2869 Code
, traverse(TK_AsIs
, varDecl(hasName("var7"),
2870 hasInitializer(cxxConstructExpr())))));
2871 EXPECT_TRUE(matches(
2872 Code
, traverse(TK_AsIs
, varDecl(hasName("var8"),
2873 hasInitializer(cxxConstructExpr())))));
2875 EXPECT_TRUE(matches(
2877 traverse(TK_IgnoreUnlessSpelledInSource
,
2878 varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));
2879 EXPECT_TRUE(matches(
2881 traverse(TK_IgnoreUnlessSpelledInSource
,
2882 varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));
2883 EXPECT_TRUE(matches(
2885 traverse(TK_IgnoreUnlessSpelledInSource
,
2886 varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));
2887 EXPECT_TRUE(matches(
2889 traverse(TK_IgnoreUnlessSpelledInSource
,
2890 varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));
2891 EXPECT_TRUE(matches(
2893 traverse(TK_IgnoreUnlessSpelledInSource
,
2894 varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));
2895 EXPECT_TRUE(matches(
2897 traverse(TK_IgnoreUnlessSpelledInSource
,
2898 varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));
2899 EXPECT_TRUE(matches(
2901 traverse(TK_IgnoreUnlessSpelledInSource
,
2902 varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));
2903 EXPECT_TRUE(matches(
2905 traverse(TK_IgnoreUnlessSpelledInSource
,
2906 varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));
2910 template<typename T>
2911 struct TemplStruct {
2921 template<typename T>
2922 void TemplStruct<T>::outOfLine(T)
2927 template<typename T>
2935 TemplStruct<int> ti;
2936 TemplStruct<double> td;
2937 (void)timesTwo<int>(2);
2938 (void)timesTwo<double>(2);
2941 template class TemplStruct<float>;
2943 extern template class TemplStruct<long>;
2945 template<> class TemplStruct<bool> {
2949 void boolSpecializationMethodOnly() {}
2954 template float timesTwo(float);
2955 template<> bool timesTwo<bool>(bool){
2960 auto M
= cxxRecordDecl(hasName("TemplStruct"),
2961 has(fieldDecl(hasType(asString("int")))));
2962 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2963 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2966 auto M
= cxxRecordDecl(hasName("TemplStruct"),
2967 has(fieldDecl(hasType(asString("double")))));
2968 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2969 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2973 functionDecl(hasName("timesTwo"),
2974 hasParameter(0, parmVarDecl(hasType(asString("int")))));
2975 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2976 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2980 functionDecl(hasName("timesTwo"),
2981 hasParameter(0, parmVarDecl(hasType(asString("double")))));
2982 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2983 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2986 // Match on the integer literal in the explicit instantiation:
2988 functionDecl(hasName("timesTwo"),
2989 hasParameter(0, parmVarDecl(hasType(asString("float")))),
2990 hasDescendant(integerLiteral(equals(2))));
2991 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDef
)));
2992 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDef
)));
2995 functionDecl(hasName("timesTwo"),
2996 hasTemplateArgument(0, refersToType(asString("float"))));
2997 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MTempl
)));
2998 // TODO: If we could match on explicit instantiations of function templates,
2999 // this would be EXPECT_TRUE. See Sema::ActOnExplicitInstantiation.
3001 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MTempl
)));
3004 auto M
= functionDecl(hasName("timesTwo"),
3005 hasParameter(0, parmVarDecl(hasType(booleanType()))));
3006 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3007 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3010 // Match on the field within the explicit instantiation:
3011 auto MRecord
= cxxRecordDecl(hasName("TemplStruct"),
3012 has(fieldDecl(hasType(asString("float")))));
3013 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MRecord
)));
3015 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MRecord
)));
3017 // Match on the explicit template instantiation itself:
3018 auto MTempl
= classTemplateSpecializationDecl(
3019 hasName("TemplStruct"),
3020 hasTemplateArgument(0,
3021 templateArgument(refersToType(asString("float")))));
3022 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MTempl
)));
3024 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MTempl
)));
3027 // The template argument is matchable, but the instantiation is not:
3028 auto M
= classTemplateSpecializationDecl(
3029 hasName("TemplStruct"),
3030 hasTemplateArgument(0,
3031 templateArgument(refersToType(asString("float")))),
3032 has(cxxConstructorDecl(hasName("TemplStruct"))));
3033 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3034 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3037 // The template argument is matchable, but the instantiation is not:
3038 auto M
= classTemplateSpecializationDecl(
3039 hasName("TemplStruct"),
3040 hasTemplateArgument(0,
3041 templateArgument(refersToType(asString("long")))),
3042 has(cxxConstructorDecl(hasName("TemplStruct"))));
3043 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3044 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3047 // Instantiated, out-of-line methods are not matchable.
3049 cxxMethodDecl(hasName("outOfLine"), isDefinition(),
3050 hasParameter(0, parmVarDecl(hasType(asString("float")))));
3051 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3052 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3055 // Explicit specialization is written in source and it matches:
3056 auto M
= classTemplateSpecializationDecl(
3057 hasName("TemplStruct"),
3058 hasTemplateArgument(0, templateArgument(refersToType(booleanType()))),
3059 has(cxxConstructorDecl(hasName("TemplStruct"))),
3060 has(cxxMethodDecl(hasName("boolSpecializationMethodOnly"))));
3061 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3062 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3070 B func1() { return 42; }
3073 auto M
= expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit")));
3074 EXPECT_TRUE(matchAndVerifyResultTrue(
3075 Code
, traverse(TK_AsIs
, M
),
3076 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3077 EXPECT_TRUE(matchAndVerifyResultTrue(
3078 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3079 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3082 auto M
= expr(unless(integerLiteral(equals(24)))).bind("intLit");
3083 EXPECT_TRUE(matchAndVerifyResultTrue(
3084 Code
, traverse(TK_AsIs
, M
),
3085 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 6),
3088 EXPECT_TRUE(matchAndVerifyResultTrue(
3089 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3090 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1),
3095 expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr())));
3096 EXPECT_TRUE(matchAndVerifyResultTrue(
3097 Code
, traverse(TK_AsIs
, M
),
3098 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3099 EXPECT_TRUE(matchAndVerifyResultTrue(
3100 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3101 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3104 auto M
= expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr()));
3105 EXPECT_TRUE(matchAndVerifyResultTrue(
3106 Code
, traverse(TK_AsIs
, M
),
3107 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3108 EXPECT_TRUE(matchAndVerifyResultTrue(
3109 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3110 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3113 auto M
= expr(integerLiteral(equals(42)).bind("intLit"), expr());
3114 EXPECT_TRUE(matchAndVerifyResultTrue(
3115 Code
, traverse(TK_AsIs
, M
),
3116 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3117 EXPECT_TRUE(matchAndVerifyResultTrue(
3118 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3119 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3122 auto M
= expr(optionally(integerLiteral(equals(42)).bind("intLit")));
3123 EXPECT_TRUE(matchAndVerifyResultTrue(
3124 Code
, traverse(TK_AsIs
, M
),
3125 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3126 EXPECT_TRUE(matchAndVerifyResultTrue(
3127 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3128 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3131 auto M
= expr().bind("allExprs");
3132 EXPECT_TRUE(matchAndVerifyResultTrue(
3133 Code
, traverse(TK_AsIs
, M
),
3134 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("allExprs", 6),
3136 EXPECT_TRUE(matchAndVerifyResultTrue(
3137 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3138 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("allExprs", 1)));
3145 auto &[f, s, t] = arr;
3151 auto M
= bindingDecl(hasName("f"));
3153 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3155 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3156 true, {"-std=c++17"}));
3159 auto M
= bindingDecl(hasName("f"), has(expr()));
3161 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3163 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3164 true, {"-std=c++17"}));
3167 auto M
= integerLiteral(hasAncestor(bindingDecl(hasName("f"))));
3169 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3171 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3172 true, {"-std=c++17"}));
3175 auto M
= declRefExpr(hasAncestor(bindingDecl(hasName("f"))));
3177 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3179 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3180 true, {"-std=c++17"}));
3184 TEST(Traversal
, traverseNoImplicit
) {
3185 StringRef Code
= R
"cpp(
3188 NonTrivial(const NonTrivial&) {}
3189 NonTrivial& operator=(const NonTrivial&) { return *this; }
3194 struct NoSpecialMethods {
3198 struct ContainsArray {
3200 ContainsArray& operator=(const ContainsArray &other) = default;
3205 NoSpecialMethods nc1;
3206 NoSpecialMethods nc2(nc1);
3214 struct HasCtorInits : NoSpecialMethods, NonTrivial
3218 HasCtorInits() : NoSpecialMethods(), m_i(42) {}
3221 struct CtorInitsNonTrivial : NonTrivial
3225 CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}
3230 auto M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3231 has(cxxRecordDecl(hasName("NoSpecialMethods"))));
3232 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3233 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3235 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3236 has(cxxConstructorDecl(isCopyConstructor())));
3237 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3238 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3240 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3241 has(cxxMethodDecl(isCopyAssignmentOperator())));
3242 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3243 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3245 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3246 has(cxxConstructorDecl(isDefaultConstructor())));
3247 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3248 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3250 M
= cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));
3251 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3252 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3254 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3255 hasMethod(cxxConstructorDecl(isCopyConstructor())));
3256 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3257 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3259 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3260 hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));
3261 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3262 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3264 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3265 hasMethod(cxxConstructorDecl(isDefaultConstructor())));
3266 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3267 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3269 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3270 hasMethod(cxxDestructorDecl()));
3271 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3272 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3275 // Because the copy-assignment operator is not spelled in the
3276 // source (ie, isImplicit()), we don't match it
3278 cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),
3279 callee(cxxMethodDecl(isCopyAssignmentOperator())));
3280 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3281 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3284 // Compiler generates a forStmt to copy the array
3285 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, forStmt())));
3287 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, forStmt())));
3290 // The defaulted method declaration can be matched, but not its
3291 // definition, in IgnoreUnlessSpelledInSource mode
3292 auto MDecl
= cxxMethodDecl(ofClass(cxxRecordDecl(hasName("ContainsArray"))),
3293 isCopyAssignmentOperator(), isDefaulted());
3295 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDecl
)));
3296 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDecl
)));
3298 auto MDef
= cxxMethodDecl(MDecl
, has(compoundStmt()));
3300 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDef
)));
3301 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDef
)));
3303 auto MBody
= cxxMethodDecl(MDecl
, hasBody(compoundStmt()));
3305 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MBody
)));
3307 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MBody
)));
3309 auto MIsDefn
= cxxMethodDecl(MDecl
, isDefinition());
3311 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MIsDefn
)));
3313 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MIsDefn
)));
3315 auto MIsInline
= cxxMethodDecl(MDecl
, isInline());
3317 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, MIsInline
)));
3319 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MIsInline
)));
3321 // The parameter of the defaulted method can still be matched.
3323 cxxMethodDecl(MDecl
, hasParameter(0, parmVarDecl(hasName("other"))));
3325 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MParm
)));
3326 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MParm
)));
3330 cxxConstructorDecl(hasName("HasCtorInits"),
3331 has(cxxCtorInitializer(forField(hasName("m_i")))));
3332 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3333 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3337 cxxConstructorDecl(hasName("HasCtorInits"),
3338 has(cxxCtorInitializer(forField(hasName("m_nt")))));
3339 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3340 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3343 auto M
= cxxConstructorDecl(hasName("HasCtorInits"),
3344 hasAnyConstructorInitializer(cxxCtorInitializer(
3345 forField(hasName("m_nt")))));
3346 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3347 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3351 cxxConstructorDecl(hasName("HasCtorInits"),
3352 forEachConstructorInitializer(
3353 cxxCtorInitializer(forField(hasName("m_nt")))));
3354 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3355 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3358 auto M
= cxxConstructorDecl(
3359 hasName("CtorInitsNonTrivial"),
3360 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(
3361 hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));
3362 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3363 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3366 auto M
= cxxConstructorDecl(
3367 hasName("HasCtorInits"),
3368 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(
3369 cxxConstructorDecl(hasName("NoSpecialMethods"))))))));
3370 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3371 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3374 auto M
= cxxCtorInitializer(forField(hasName("m_nt")));
3375 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3376 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3392 auto M
= cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3393 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3394 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3398 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3399 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3400 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3404 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3405 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3406 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3409 auto M
= cxxForRangeStmt(has(declStmt()));
3410 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3411 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3415 cxxForRangeStmt(hasLoopVariable(varDecl(hasName("i"))),
3416 hasRangeInit(declRefExpr(to(varDecl(hasName("arr"))))));
3417 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3418 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3421 auto M
= cxxForRangeStmt(unless(hasInitStatement(stmt())));
3422 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3423 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3426 auto M
= cxxForRangeStmt(hasBody(stmt()));
3427 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3428 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3431 auto M
= cxxForRangeStmt(hasDescendant(ifStmt()));
3432 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3433 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3436 EXPECT_TRUE(matches(
3437 Code
, traverse(TK_AsIs
, cxxForRangeStmt(has(declStmt(
3438 hasSingleDecl(varDecl(hasName("i")))))))));
3440 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3441 cxxForRangeStmt(has(varDecl(hasName("i")))))));
3444 EXPECT_TRUE(matches(
3445 Code
, traverse(TK_AsIs
, cxxForRangeStmt(has(declStmt(hasSingleDecl(
3446 varDecl(hasInitializer(declRefExpr(
3447 to(varDecl(hasName("arr")))))))))))));
3448 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3449 cxxForRangeStmt(has(declRefExpr(
3450 to(varDecl(hasName("arr")))))))));
3453 auto M
= cxxForRangeStmt(has(compoundStmt()));
3454 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3455 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3458 auto M
= binaryOperator(hasOperatorName("!="));
3459 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3460 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3463 auto M
= unaryOperator(hasOperatorName("++"));
3464 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3465 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3468 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__range"))));
3469 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3470 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3473 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__begin"))));
3474 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3475 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3478 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__end"))));
3479 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3480 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3483 auto M
= ifStmt(hasParent(compoundStmt(hasParent(cxxForRangeStmt()))));
3484 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3485 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3488 auto M
= cxxForRangeStmt(
3489 has(varDecl(hasName("i"), hasParent(cxxForRangeStmt()))));
3490 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3491 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3494 auto M
= cxxForRangeStmt(hasDescendant(varDecl(
3495 hasName("i"), hasParent(declStmt(hasParent(cxxForRangeStmt()))))));
3496 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3497 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3500 auto M
= cxxForRangeStmt(hasRangeInit(declRefExpr(
3501 to(varDecl(hasName("arr"))), hasParent(cxxForRangeStmt()))));
3502 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3503 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3507 auto M
= cxxForRangeStmt(hasRangeInit(declRefExpr(
3508 to(varDecl(hasName("arr"))), hasParent(varDecl(hasParent(declStmt(
3509 hasParent(cxxForRangeStmt()))))))));
3510 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3511 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3519 Range getRange(int);
3523 for (auto i : getRange(42))
3529 auto M
= integerLiteral(equals(42));
3530 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3531 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3534 auto M
= callExpr(hasDescendant(integerLiteral(equals(42))));
3535 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3536 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3539 auto M
= compoundStmt(hasDescendant(integerLiteral(equals(42))));
3540 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3541 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3548 for (auto& a = arr; auto i : a)
3555 auto M
= cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3557 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3559 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3560 true, {"-std=c++20"}));
3564 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3566 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3568 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3569 true, {"-std=c++20"}));
3573 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3575 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3577 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3578 true, {"-std=c++20"}));
3582 cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i"))))));
3584 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3586 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3587 true, {"-std=c++20"}));
3590 auto M
= cxxForRangeStmt(
3591 hasInitStatement(declStmt(hasSingleDecl(varDecl(
3593 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3594 hasLoopVariable(varDecl(hasName("i"))),
3595 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3597 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3599 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3600 true, {"-std=c++20"}));
3603 auto M
= cxxForRangeStmt(
3604 has(declStmt(hasSingleDecl(varDecl(
3606 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3607 hasLoopVariable(varDecl(hasName("i"))),
3608 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3610 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3612 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3613 true, {"-std=c++20"}));
3616 auto M
= cxxForRangeStmt(hasInitStatement(declStmt(
3617 hasSingleDecl(varDecl(hasName("a"))), hasParent(cxxForRangeStmt()))));
3619 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3621 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3622 true, {"-std=c++20"}));
3630 Range getRange(int);
3636 for (auto j = getNum(42); auto i : getRange(j))
3642 auto M
= integerLiteral(equals(42));
3644 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3646 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3647 true, {"-std=c++20"}));
3650 auto M
= compoundStmt(hasDescendant(integerLiteral(equals(42))));
3652 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3654 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3655 true, {"-std=c++20"}));
3659 void hasDefaultArg(int i, int j = 0)
3662 void callDefaultArg()
3667 auto hasDefaultArgCall
= [](auto InnerMatcher
) {
3668 return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),
3672 auto M
= hasDefaultArgCall(has(integerLiteral(equals(42))));
3673 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3674 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3677 auto M
= hasDefaultArgCall(has(cxxDefaultArgExpr()));
3678 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3679 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3682 auto M
= hasDefaultArgCall(argumentCountIs(2));
3683 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3684 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3687 auto M
= hasDefaultArgCall(argumentCountIs(1));
3688 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3689 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3692 auto M
= hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));
3693 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3694 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3697 auto M
= hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));
3698 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3699 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3712 auto M
= cxxDestructorDecl(isDefaulted(),
3713 ofClass(cxxRecordDecl(has(fieldDecl()))));
3714 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3715 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3720 static constexpr bool getTrue() { return true; }
3725 explicit(S::getTrue()) A();
3731 EXPECT_TRUE(matchesConditionally(
3736 hasExplicitSpecifier(expr(ignoringImplicit(
3737 callExpr(has(ignoringImplicit(declRefExpr())))))))),
3738 true, {"-std=c++20"}));
3739 EXPECT_TRUE(matchesConditionally(
3741 traverse(TK_IgnoreUnlessSpelledInSource
,
3744 hasExplicitSpecifier(callExpr(has(declRefExpr()))))),
3745 true, {"-std=c++20"}));
3749 template <typename MatcherT
>
3750 bool matcherTemplateWithBinding(StringRef Code
, const MatcherT
&M
) {
3751 return matchAndVerifyResultTrue(
3752 Code
, M
.bind("matchedStmt"),
3753 std::make_unique
<VerifyIdIsBoundTo
<ReturnStmt
>>("matchedStmt", 1));
3756 TEST(Traversal
, traverseWithBinding
) {
3757 // Some existing matcher code expects to take a matcher as a
3758 // template arg and bind to it. Verify that that works.
3760 llvm::StringRef Code
= R
"cpp(
3766 EXPECT_TRUE(matcherTemplateWithBinding(
3767 Code
, traverse(TK_AsIs
,
3768 returnStmt(has(implicitCastExpr(has(floatLiteral())))))));
3771 TEST(Traversal
, traverseMatcherNesting
) {
3773 StringRef Code
= R
"cpp(
3786 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3787 callExpr(has(callExpr(traverse(
3788 TK_AsIs
, callExpr(has(implicitCastExpr(
3789 has(floatLiteral())))))))))));
3791 EXPECT_TRUE(matches(
3793 traverse(TK_IgnoreUnlessSpelledInSource
,
3794 traverse(TK_AsIs
, implicitCastExpr(has(floatLiteral()))))));
3797 TEST(Traversal
, traverseMatcherThroughImplicit
) {
3798 StringRef Code
= R
"cpp(
3803 void constructImplicit() {
3809 auto Matcher
= traverse(TK_IgnoreUnlessSpelledInSource
, implicitCastExpr());
3811 // Verfiy that it does not segfault
3812 EXPECT_FALSE(matches(Code
, Matcher
));
3815 TEST(Traversal
, traverseMatcherThroughMemoization
) {
3817 StringRef Code
= R
"cpp(
3824 auto Matcher
= varDecl(hasInitializer(floatLiteral()));
3826 // Matchers such as hasDescendant memoize their result regarding AST
3827 // nodes. In the matcher below, the first use of hasDescendant(Matcher)
3828 // fails, and the use of it inside the traverse() matcher should pass
3829 // causing the overall matcher to be a true match.
3830 // This test verifies that the first false result is not re-used, which
3831 // would cause the overall matcher to be incorrectly false.
3833 EXPECT_TRUE(matches(
3835 functionDecl(anyOf(hasDescendant(Matcher
),
3836 traverse(TK_IgnoreUnlessSpelledInSource
,
3837 functionDecl(hasDescendant(Matcher
)))))));
3840 TEST(Traversal
, traverseUnlessSpelledInSource
) {
3842 StringRef Code
= R
"cpp(
3915 [a, b = c](int d) { int e = d; };
3919 [] <typename TemplateType> (TemplateType t, TemplateType u) { int e = t + u; };
3925 auto l = [&] { ++count; };
3933 traverse(TK_IgnoreUnlessSpelledInSource
,
3934 returnStmt(forFunction(functionDecl(hasName("func1"))),
3935 hasReturnValue(integerLiteral(equals(42))))),
3936 langCxx20OrLater()));
3940 traverse(TK_IgnoreUnlessSpelledInSource
,
3941 integerLiteral(equals(42),
3942 hasParent(returnStmt(forFunction(
3943 functionDecl(hasName("func1"))))))),
3944 langCxx20OrLater()));
3946 EXPECT_TRUE(matches(
3948 traverse(TK_IgnoreUnlessSpelledInSource
,
3949 returnStmt(forFunction(functionDecl(hasName("func2"))),
3950 hasReturnValue(cxxTemporaryObjectExpr(
3951 hasArgument(0, integerLiteral(equals(42))))))),
3952 langCxx20OrLater()));
3953 EXPECT_TRUE(matches(
3956 TK_IgnoreUnlessSpelledInSource
,
3957 integerLiteral(equals(42),
3958 hasParent(cxxTemporaryObjectExpr(hasParent(returnStmt(
3959 forFunction(functionDecl(hasName("func2"))))))))),
3960 langCxx20OrLater()));
3964 traverse(TK_IgnoreUnlessSpelledInSource
,
3965 returnStmt(forFunction(functionDecl(hasName("func3"))),
3966 hasReturnValue(cxxConstructExpr(hasArgument(
3967 0, integerLiteral(equals(42))))))),
3968 langCxx20OrLater()));
3970 EXPECT_TRUE(matches(
3973 TK_IgnoreUnlessSpelledInSource
,
3974 integerLiteral(equals(42),
3975 hasParent(cxxConstructExpr(hasParent(returnStmt(
3976 forFunction(functionDecl(hasName("func3"))))))))),
3977 langCxx20OrLater()));
3981 traverse(TK_IgnoreUnlessSpelledInSource
,
3982 returnStmt(forFunction(functionDecl(hasName("func4"))),
3983 hasReturnValue(cxxTemporaryObjectExpr()))),
3984 langCxx20OrLater()));
3988 traverse(TK_IgnoreUnlessSpelledInSource
,
3989 returnStmt(forFunction(functionDecl(hasName("func5"))),
3990 hasReturnValue(cxxTemporaryObjectExpr()))),
3991 langCxx20OrLater()));
3995 traverse(TK_IgnoreUnlessSpelledInSource
,
3996 returnStmt(forFunction(functionDecl(hasName("func6"))),
3997 hasReturnValue(cxxTemporaryObjectExpr()))),
3998 langCxx20OrLater()));
4002 traverse(TK_IgnoreUnlessSpelledInSource
,
4003 returnStmt(forFunction(functionDecl(hasName("func7"))),
4004 hasReturnValue(cxxTemporaryObjectExpr()))),
4005 langCxx20OrLater()));
4009 traverse(TK_IgnoreUnlessSpelledInSource
,
4010 returnStmt(forFunction(functionDecl(hasName("func8"))),
4011 hasReturnValue(cxxFunctionalCastExpr(
4012 hasSourceExpression(initListExpr()))))),
4013 langCxx20OrLater()));
4017 traverse(TK_IgnoreUnlessSpelledInSource
,
4018 returnStmt(forFunction(functionDecl(hasName("func9"))),
4019 hasReturnValue(cxxFunctionalCastExpr(
4020 hasSourceExpression(initListExpr()))))),
4021 langCxx20OrLater()));
4023 EXPECT_TRUE(matches(
4026 TK_IgnoreUnlessSpelledInSource
,
4027 returnStmt(forFunction(functionDecl(hasName("func10"))),
4028 hasReturnValue(declRefExpr(to(varDecl(hasName("a"))))))),
4029 langCxx20OrLater()));
4033 traverse(TK_IgnoreUnlessSpelledInSource
,
4034 declRefExpr(to(varDecl(hasName("a"))),
4035 hasParent(returnStmt(forFunction(
4036 functionDecl(hasName("func10"))))))),
4037 langCxx20OrLater()));
4039 EXPECT_TRUE(matches(
4042 TK_IgnoreUnlessSpelledInSource
,
4043 returnStmt(forFunction(functionDecl(hasName("func11"))),
4044 hasReturnValue(declRefExpr(to(varDecl(hasName("b"))))))),
4045 langCxx20OrLater()));
4049 traverse(TK_IgnoreUnlessSpelledInSource
,
4050 declRefExpr(to(varDecl(hasName("b"))),
4051 hasParent(returnStmt(forFunction(
4052 functionDecl(hasName("func11"))))))),
4053 langCxx20OrLater()));
4055 EXPECT_TRUE(matches(
4058 TK_IgnoreUnlessSpelledInSource
,
4059 returnStmt(forFunction(functionDecl(hasName("func12"))),
4060 hasReturnValue(declRefExpr(to(varDecl(hasName("c"))))))),
4061 langCxx20OrLater()));
4065 traverse(TK_IgnoreUnlessSpelledInSource
,
4066 declRefExpr(to(varDecl(hasName("c"))),
4067 hasParent(returnStmt(forFunction(
4068 functionDecl(hasName("func12"))))))),
4069 langCxx20OrLater()));
4071 EXPECT_TRUE(matches(
4074 TK_IgnoreUnlessSpelledInSource
,
4075 lambdaExpr(forFunction(functionDecl(hasName("func13"))),
4076 has(compoundStmt(hasDescendant(varDecl(hasName("e"))))),
4077 has(declRefExpr(to(varDecl(hasName("a"))))),
4078 has(varDecl(hasName("b"), hasInitializer(declRefExpr(to(
4079 varDecl(hasName("c"))))))),
4080 has(parmVarDecl(hasName("d"))))),
4081 langCxx20OrLater()));
4085 traverse(TK_IgnoreUnlessSpelledInSource
,
4086 declRefExpr(to(varDecl(hasName("a"))),
4087 hasParent(lambdaExpr(forFunction(
4088 functionDecl(hasName("func13"))))))),
4089 langCxx20OrLater()));
4091 EXPECT_TRUE(matches(
4093 traverse(TK_IgnoreUnlessSpelledInSource
,
4094 varDecl(hasName("b"),
4095 hasInitializer(declRefExpr(to(varDecl(hasName("c"))))),
4096 hasParent(lambdaExpr(
4097 forFunction(functionDecl(hasName("func13"))))))),
4098 langCxx20OrLater()));
4100 EXPECT_TRUE(matches(Code
,
4101 traverse(TK_IgnoreUnlessSpelledInSource
,
4102 compoundStmt(hasParent(lambdaExpr(forFunction(
4103 functionDecl(hasName("func13"))))))),
4104 langCxx20OrLater()));
4106 EXPECT_TRUE(matches(
4108 traverse(TK_IgnoreUnlessSpelledInSource
,
4109 templateTypeParmDecl(hasName("TemplateType"),
4110 hasParent(lambdaExpr(forFunction(
4111 functionDecl(hasName("func14"))))))),
4112 langCxx20OrLater()));
4114 EXPECT_TRUE(matches(
4116 traverse(TK_IgnoreUnlessSpelledInSource
,
4117 lambdaExpr(forFunction(functionDecl(hasName("func14"))),
4118 has(templateTypeParmDecl(hasName("TemplateType"))))),
4119 langCxx20OrLater()));
4121 EXPECT_TRUE(matches(
4123 traverse(TK_IgnoreUnlessSpelledInSource
,
4124 functionDecl(hasName("func14"), hasDescendant(floatLiteral()))),
4125 langCxx20OrLater()));
4127 EXPECT_TRUE(matches(
4129 traverse(TK_IgnoreUnlessSpelledInSource
,
4131 hasDescendant(varDecl(hasName("count")).bind("countVar")),
4133 declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))),
4134 langCxx20OrLater()));
4138 int explicit_captured = 0;
4139 int implicit_captured = 0;
4140 auto l = [&, explicit_captured](int i) {
4141 if (i || explicit_captured || implicit_captured) return;
4146 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, ifStmt())));
4148 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, ifStmt())));
4150 auto lambdaExplicitCapture
= declRefExpr(
4151 to(varDecl(hasName("explicit_captured"))), unless(hasAncestor(ifStmt())));
4152 auto lambdaImplicitCapture
= declRefExpr(
4153 to(varDecl(hasName("implicit_captured"))), unless(hasAncestor(ifStmt())));
4155 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, lambdaExplicitCapture
)));
4156 EXPECT_TRUE(matches(
4157 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, lambdaExplicitCapture
)));
4159 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, lambdaImplicitCapture
)));
4160 EXPECT_FALSE(matches(
4161 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, lambdaImplicitCapture
)));
4168 bool operator==(const S& other)
4183 auto M
= unaryOperator(
4184 hasOperatorName("!"),
4185 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="))));
4187 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4189 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4190 true, {"-std=c++20"}));
4193 auto M
= declRefExpr(to(varDecl(hasName("s1"))));
4195 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4197 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4198 true, {"-std=c++20"}));
4201 auto M
= cxxOperatorCallExpr(hasOverloadedOperatorName("=="));
4203 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4205 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4206 true, {"-std=c++20"}));
4209 auto M
= cxxOperatorCallExpr(hasOverloadedOperatorName("!="));
4211 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4213 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4214 true, {"-std=c++20"}));
4216 auto withDescendants
= [](StringRef lName
, StringRef rName
) {
4217 return stmt(hasDescendant(declRefExpr(to(varDecl(hasName(lName
))))),
4218 hasDescendant(declRefExpr(to(varDecl(hasName(rName
))))));
4221 auto M
= cxxRewrittenBinaryOperator(withDescendants("s1", "s2"));
4223 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4225 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4226 true, {"-std=c++20"}));
4229 auto M
= cxxRewrittenBinaryOperator(
4230 has(declRefExpr(to(varDecl(hasName("s1"))))),
4231 has(declRefExpr(to(varDecl(hasName("s2"))))));
4233 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4235 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4236 true, {"-std=c++20"}));
4239 auto M
= cxxRewrittenBinaryOperator(
4240 hasLHS(expr(hasParent(cxxRewrittenBinaryOperator()))),
4241 hasRHS(expr(hasParent(cxxRewrittenBinaryOperator()))));
4243 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4245 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4246 true, {"-std=c++20"}));
4249 EXPECT_TRUE(matchesConditionally(
4252 cxxRewrittenBinaryOperator(
4253 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4254 isComparisonOperator(),
4255 hasLHS(ignoringImplicit(
4256 declRefExpr(to(varDecl(hasName("s1")))))),
4257 hasRHS(ignoringImplicit(
4258 declRefExpr(to(varDecl(hasName("s2")))))),
4259 hasEitherOperand(ignoringImplicit(
4260 declRefExpr(to(varDecl(hasName("s2")))))),
4261 hasOperands(ignoringImplicit(
4262 declRefExpr(to(varDecl(hasName("s1"))))),
4263 ignoringImplicit(declRefExpr(
4264 to(varDecl(hasName("s2")))))))),
4265 true, {"-std=c++20"}));
4266 EXPECT_TRUE(matchesConditionally(
4268 traverse(TK_IgnoreUnlessSpelledInSource
,
4269 cxxRewrittenBinaryOperator(
4270 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4271 isComparisonOperator(),
4272 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4273 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4274 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4275 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4276 declRefExpr(to(varDecl(hasName("s2"))))))),
4277 true, {"-std=c++20"}));
4282 struct strong_ordering {
4284 constexpr operator int() const { return n; }
4285 static const strong_ordering equal, greater, less;
4287 constexpr strong_ordering strong_ordering::equal = {0};
4288 constexpr strong_ordering strong_ordering::greater = {1};
4289 constexpr strong_ordering strong_ordering::less = {-1};
4292 struct HasSpaceshipMem {
4294 constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
4299 HasSpaceshipMem hs1, hs2;
4303 HasSpaceshipMem hs3, hs4;
4307 HasSpaceshipMem hs5, hs6;
4311 HasSpaceshipMem hs7, hs8;
4315 HasSpaceshipMem hs9, hs10;
4319 HasSpaceshipMem hs11, hs12;
4324 auto withArgs
= [](StringRef lName
, StringRef rName
) {
4325 return cxxOperatorCallExpr(
4326 hasArgument(0, declRefExpr(to(varDecl(hasName(lName
))))),
4327 hasArgument(1, declRefExpr(to(varDecl(hasName(rName
))))));
4330 auto M
= ifStmt(hasCondition(cxxOperatorCallExpr(
4331 hasOverloadedOperatorName("=="), withArgs("hs1", "hs2"))));
4333 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4335 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4336 true, {"-std=c++20"}));
4340 unaryOperator(hasOperatorName("!"),
4341 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4342 withArgs("hs3", "hs4"))));
4344 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4346 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4347 true, {"-std=c++20"}));
4351 unaryOperator(hasOperatorName("!"),
4352 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4353 withArgs("hs3", "hs4"))));
4355 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4357 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4358 true, {"-std=c++20"}));
4361 auto M
= binaryOperator(
4362 hasOperatorName("<"),
4363 hasLHS(hasDescendant(cxxOperatorCallExpr(
4364 hasOverloadedOperatorName("<=>"), withArgs("hs5", "hs6")))),
4365 hasRHS(integerLiteral(equals(0))));
4367 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4369 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4370 true, {"-std=c++20"}));
4373 auto M
= cxxRewrittenBinaryOperator(withDescendants("hs3", "hs4"));
4375 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4377 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4378 true, {"-std=c++20"}));
4381 auto M
= declRefExpr(to(varDecl(hasName("hs3"))));
4383 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4385 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4386 true, {"-std=c++20"}));
4389 auto M
= cxxRewrittenBinaryOperator(has(
4390 unaryOperator(hasOperatorName("!"), withDescendants("hs3", "hs4"))));
4392 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4394 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4395 true, {"-std=c++20"}));
4398 auto M
= cxxRewrittenBinaryOperator(
4399 has(declRefExpr(to(varDecl(hasName("hs3"))))),
4400 has(declRefExpr(to(varDecl(hasName("hs4"))))));
4402 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4404 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4405 true, {"-std=c++20"}));
4408 EXPECT_TRUE(matchesConditionally(
4411 cxxRewrittenBinaryOperator(
4412 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4413 isComparisonOperator(),
4414 hasLHS(ignoringImplicit(
4415 declRefExpr(to(varDecl(hasName("hs3")))))),
4416 hasRHS(ignoringImplicit(
4417 declRefExpr(to(varDecl(hasName("hs4")))))),
4418 hasEitherOperand(ignoringImplicit(
4419 declRefExpr(to(varDecl(hasName("hs3")))))),
4420 hasOperands(ignoringImplicit(
4421 declRefExpr(to(varDecl(hasName("hs3"))))),
4422 ignoringImplicit(declRefExpr(
4423 to(varDecl(hasName("hs4")))))))),
4424 true, {"-std=c++20"}));
4425 EXPECT_TRUE(matchesConditionally(
4427 traverse(TK_IgnoreUnlessSpelledInSource
,
4428 cxxRewrittenBinaryOperator(
4429 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4430 isComparisonOperator(),
4431 hasLHS(declRefExpr(to(varDecl(hasName("hs3"))))),
4432 hasRHS(declRefExpr(to(varDecl(hasName("hs4"))))),
4433 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs3"))))),
4434 hasOperands(declRefExpr(to(varDecl(hasName("hs3")))),
4435 declRefExpr(to(varDecl(hasName("hs4"))))))),
4436 true, {"-std=c++20"}));
4439 EXPECT_TRUE(matchesConditionally(
4442 cxxRewrittenBinaryOperator(
4443 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4444 isComparisonOperator(),
4445 hasLHS(ignoringImplicit(
4446 declRefExpr(to(varDecl(hasName("hs5")))))),
4447 hasRHS(ignoringImplicit(
4448 declRefExpr(to(varDecl(hasName("hs6")))))),
4449 hasEitherOperand(ignoringImplicit(
4450 declRefExpr(to(varDecl(hasName("hs5")))))),
4451 hasOperands(ignoringImplicit(
4452 declRefExpr(to(varDecl(hasName("hs5"))))),
4453 ignoringImplicit(declRefExpr(
4454 to(varDecl(hasName("hs6")))))))),
4455 true, {"-std=c++20"}));
4456 EXPECT_TRUE(matchesConditionally(
4458 traverse(TK_IgnoreUnlessSpelledInSource
,
4459 cxxRewrittenBinaryOperator(
4460 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4461 isComparisonOperator(),
4462 hasLHS(declRefExpr(to(varDecl(hasName("hs5"))))),
4463 hasRHS(declRefExpr(to(varDecl(hasName("hs6"))))),
4464 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs5"))))),
4465 hasOperands(declRefExpr(to(varDecl(hasName("hs5")))),
4466 declRefExpr(to(varDecl(hasName("hs6"))))))),
4467 true, {"-std=c++20"}));
4470 EXPECT_TRUE(matchesConditionally(
4473 cxxRewrittenBinaryOperator(
4474 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4475 isComparisonOperator(),
4476 hasLHS(ignoringImplicit(
4477 declRefExpr(to(varDecl(hasName("hs7")))))),
4478 hasRHS(ignoringImplicit(
4479 declRefExpr(to(varDecl(hasName("hs8")))))),
4480 hasEitherOperand(ignoringImplicit(
4481 declRefExpr(to(varDecl(hasName("hs7")))))),
4482 hasOperands(ignoringImplicit(
4483 declRefExpr(to(varDecl(hasName("hs7"))))),
4484 ignoringImplicit(declRefExpr(
4485 to(varDecl(hasName("hs8")))))))),
4486 true, {"-std=c++20"}));
4487 EXPECT_TRUE(matchesConditionally(
4489 traverse(TK_IgnoreUnlessSpelledInSource
,
4490 cxxRewrittenBinaryOperator(
4491 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4492 isComparisonOperator(),
4493 hasLHS(declRefExpr(to(varDecl(hasName("hs7"))))),
4494 hasRHS(declRefExpr(to(varDecl(hasName("hs8"))))),
4495 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs7"))))),
4496 hasOperands(declRefExpr(to(varDecl(hasName("hs7")))),
4497 declRefExpr(to(varDecl(hasName("hs8"))))))),
4498 true, {"-std=c++20"}));
4501 EXPECT_TRUE(matchesConditionally(
4504 cxxRewrittenBinaryOperator(
4505 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4506 isComparisonOperator(),
4507 hasLHS(ignoringImplicit(
4508 declRefExpr(to(varDecl(hasName("hs9")))))),
4509 hasRHS(ignoringImplicit(
4510 declRefExpr(to(varDecl(hasName("hs10")))))),
4511 hasEitherOperand(ignoringImplicit(
4512 declRefExpr(to(varDecl(hasName("hs9")))))),
4513 hasOperands(ignoringImplicit(
4514 declRefExpr(to(varDecl(hasName("hs9"))))),
4515 ignoringImplicit(declRefExpr(
4516 to(varDecl(hasName("hs10")))))))),
4517 true, {"-std=c++20"}));
4518 EXPECT_TRUE(matchesConditionally(
4520 traverse(TK_IgnoreUnlessSpelledInSource
,
4521 cxxRewrittenBinaryOperator(
4522 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4523 isComparisonOperator(),
4524 hasLHS(declRefExpr(to(varDecl(hasName("hs9"))))),
4525 hasRHS(declRefExpr(to(varDecl(hasName("hs10"))))),
4526 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs9"))))),
4527 hasOperands(declRefExpr(to(varDecl(hasName("hs9")))),
4528 declRefExpr(to(varDecl(hasName("hs10"))))))),
4529 true, {"-std=c++20"}));
4532 EXPECT_TRUE(matchesConditionally(
4535 cxxRewrittenBinaryOperator(
4536 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4537 isComparisonOperator(),
4538 hasLHS(ignoringImplicit(
4539 declRefExpr(to(varDecl(hasName("hs11")))))),
4540 hasRHS(ignoringImplicit(
4541 declRefExpr(to(varDecl(hasName("hs12")))))),
4542 hasEitherOperand(ignoringImplicit(
4543 declRefExpr(to(varDecl(hasName("hs11")))))),
4544 hasOperands(ignoringImplicit(
4545 declRefExpr(to(varDecl(hasName("hs11"))))),
4546 ignoringImplicit(declRefExpr(
4547 to(varDecl(hasName("hs12")))))))),
4548 true, {"-std=c++20"}));
4549 EXPECT_TRUE(matchesConditionally(
4552 TK_IgnoreUnlessSpelledInSource
,
4553 cxxRewrittenBinaryOperator(
4554 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4555 isComparisonOperator(),
4556 hasLHS(declRefExpr(to(varDecl(hasName("hs11"))))),
4557 hasRHS(declRefExpr(to(varDecl(hasName("hs12"))))),
4558 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs11"))))),
4559 hasOperands(declRefExpr(to(varDecl(hasName("hs11")))),
4560 declRefExpr(to(varDecl(hasName("hs12"))))))),
4561 true, {"-std=c++20"}));
4569 bool operator==(const S& other) const
4576 bool operator==(const HasOpEqMem&) const { return true; }
4579 struct HasOpEqFree {
4581 bool operator==(const HasOpEqFree&, const HasOpEqFree&) { return true; }
4615 EXPECT_TRUE(matchesConditionally(
4619 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4620 isComparisonOperator(),
4621 hasLHS(ignoringImplicit(
4622 declRefExpr(to(varDecl(hasName("s1")))))),
4623 hasRHS(ignoringImplicit(
4624 declRefExpr(to(varDecl(hasName("s2")))))),
4625 hasEitherOperand(ignoringImplicit(
4626 declRefExpr(to(varDecl(hasName("s2")))))),
4627 hasOperands(ignoringImplicit(
4628 declRefExpr(to(varDecl(hasName("s1"))))),
4629 ignoringImplicit(declRefExpr(
4630 to(varDecl(hasName("s2")))))))),
4631 true, {"-std=c++20"}));
4632 EXPECT_TRUE(matchesConditionally(
4634 traverse(TK_AsIs
, binaryOperation(hasOperatorName("!="),
4635 hasLHS(ignoringImplicit(declRefExpr(
4636 to(varDecl(hasName("i1")))))),
4637 hasRHS(ignoringImplicit(declRefExpr(
4638 to(varDecl(hasName("i2")))))))),
4639 true, {"-std=c++20"}));
4640 EXPECT_TRUE(matchesConditionally(
4642 traverse(TK_AsIs
, binaryOperation(hasOperatorName("=="),
4643 hasLHS(ignoringImplicit(declRefExpr(
4644 to(varDecl(hasName("M1")))))),
4645 hasRHS(ignoringImplicit(declRefExpr(
4646 to(varDecl(hasName("M2")))))))),
4647 true, {"-std=c++20"}));
4648 EXPECT_TRUE(matchesConditionally(
4650 traverse(TK_AsIs
, binaryOperation(hasOperatorName("=="),
4651 hasLHS(ignoringImplicit(declRefExpr(
4652 to(varDecl(hasName("F1")))))),
4653 hasRHS(ignoringImplicit(declRefExpr(
4654 to(varDecl(hasName("F2")))))))),
4655 true, {"-std=c++20"}));
4656 EXPECT_TRUE(matchesConditionally(
4658 traverse(TK_IgnoreUnlessSpelledInSource
,
4660 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4661 isComparisonOperator(),
4662 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4663 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4664 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4665 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4666 declRefExpr(to(varDecl(hasName("s2"))))))),
4667 true, {"-std=c++20"}));
4668 EXPECT_TRUE(matchesConditionally(
4671 TK_IgnoreUnlessSpelledInSource
,
4672 binaryOperation(hasOperatorName("!="),
4673 hasLHS(declRefExpr(to(varDecl(hasName("i1"))))),
4674 hasRHS(declRefExpr(to(varDecl(hasName("i2"))))))),
4675 true, {"-std=c++20"}));
4676 EXPECT_TRUE(matchesConditionally(
4679 TK_IgnoreUnlessSpelledInSource
,
4680 binaryOperation(hasOperatorName("=="),
4681 hasLHS(declRefExpr(to(varDecl(hasName("M1"))))),
4682 hasRHS(declRefExpr(to(varDecl(hasName("M2"))))))),
4683 true, {"-std=c++20"}));
4684 EXPECT_TRUE(matchesConditionally(
4687 TK_IgnoreUnlessSpelledInSource
,
4688 binaryOperation(hasOperatorName("=="),
4689 hasLHS(declRefExpr(to(varDecl(hasName("F1"))))),
4690 hasRHS(declRefExpr(to(varDecl(hasName("F2"))))))),
4691 true, {"-std=c++20"}));
4695 TEST(IgnoringImpCasts
, PathologicalLambda
) {
4697 // Test that deeply nested lambdas are not a performance penalty
4698 StringRef Code
= R
"cpp(
4763 EXPECT_TRUE(matches(Code
, integerLiteral(equals(42))));
4764 EXPECT_TRUE(matches(Code
, functionDecl(hasDescendant(integerLiteral(equals(42))))));
4767 TEST(IgnoringImpCasts
, MatchesImpCasts
) {
4768 // This test checks that ignoringImpCasts matches when implicit casts are
4769 // present and its inner matcher alone does not match.
4770 // Note that this test creates an implicit const cast.
4771 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4772 varDecl(hasInitializer(ignoringImpCasts(
4773 declRefExpr(to(varDecl(hasName("x")))))))));
4774 // This test creates an implict cast from int to char.
4775 EXPECT_TRUE(matches("char x = 0;",
4776 varDecl(hasInitializer(ignoringImpCasts(
4777 integerLiteral(equals(0)))))));
4780 TEST(IgnoringImpCasts
, DoesNotMatchIncorrectly
) {
4781 // These tests verify that ignoringImpCasts does not match if the inner
4782 // matcher does not match.
4783 // Note that the first test creates an implicit const cast.
4784 EXPECT_TRUE(notMatches("int x; const int y = x;",
4785 varDecl(hasInitializer(ignoringImpCasts(
4786 unless(anything()))))));
4787 EXPECT_TRUE(notMatches("int x; int y = x;",
4788 varDecl(hasInitializer(ignoringImpCasts(
4789 unless(anything()))))));
4791 // These tests verify that ignoringImplictCasts does not look through explicit
4792 // casts or parentheses.
4793 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4794 varDecl(hasInitializer(ignoringImpCasts(
4795 integerLiteral())))));
4796 EXPECT_TRUE(notMatches(
4799 varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))))));
4800 EXPECT_TRUE(notMatches("float i = (float)0;",
4801 varDecl(hasInitializer(ignoringImpCasts(
4802 integerLiteral())))));
4803 EXPECT_TRUE(notMatches("float i = float(0);",
4804 varDecl(hasInitializer(ignoringImpCasts(
4805 integerLiteral())))));
4808 TEST(IgnoringImpCasts
, MatchesWithoutImpCasts
) {
4809 // This test verifies that expressions that do not have implicit casts
4810 // still match the inner matcher.
4811 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4812 varDecl(hasInitializer(ignoringImpCasts(
4813 declRefExpr(to(varDecl(hasName("x")))))))));
4816 TEST(IgnoringParenCasts
, MatchesParenCasts
) {
4817 // This test checks that ignoringParenCasts matches when parentheses and/or
4818 // casts are present and its inner matcher alone does not match.
4819 EXPECT_TRUE(matches("int x = (0);",
4820 varDecl(hasInitializer(ignoringParenCasts(
4821 integerLiteral(equals(0)))))));
4822 EXPECT_TRUE(matches("int x = (((((0)))));",
4823 varDecl(hasInitializer(ignoringParenCasts(
4824 integerLiteral(equals(0)))))));
4826 // This test creates an implict cast from int to char in addition to the
4828 EXPECT_TRUE(matches("char x = (0);",
4829 varDecl(hasInitializer(ignoringParenCasts(
4830 integerLiteral(equals(0)))))));
4832 EXPECT_TRUE(matches("char x = (char)0;",
4833 varDecl(hasInitializer(ignoringParenCasts(
4834 integerLiteral(equals(0)))))));
4835 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
4836 varDecl(hasInitializer(ignoringParenCasts(
4837 integerLiteral(equals(0)))))));
4840 TEST(IgnoringParenCasts
, MatchesWithoutParenCasts
) {
4841 // This test verifies that expressions that do not have any casts still match.
4842 EXPECT_TRUE(matches("int x = 0;",
4843 varDecl(hasInitializer(ignoringParenCasts(
4844 integerLiteral(equals(0)))))));
4847 TEST(IgnoringParenCasts
, DoesNotMatchIncorrectly
) {
4848 // These tests verify that ignoringImpCasts does not match if the inner
4849 // matcher does not match.
4850 EXPECT_TRUE(notMatches("int x = ((0));",
4851 varDecl(hasInitializer(ignoringParenCasts(
4852 unless(anything()))))));
4854 // This test creates an implicit cast from int to char in addition to the
4856 EXPECT_TRUE(notMatches("char x = ((0));",
4857 varDecl(hasInitializer(ignoringParenCasts(
4858 unless(anything()))))));
4860 EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
4861 varDecl(hasInitializer(ignoringParenCasts(
4862 unless(anything()))))));
4865 TEST(IgnoringParenAndImpCasts
, MatchesParenImpCasts
) {
4866 // This test checks that ignoringParenAndImpCasts matches when
4867 // parentheses and/or implicit casts are present and its inner matcher alone
4869 // Note that this test creates an implicit const cast.
4870 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4871 varDecl(hasInitializer(ignoringParenImpCasts(
4872 declRefExpr(to(varDecl(hasName("x")))))))));
4873 // This test creates an implicit cast from int to char.
4874 EXPECT_TRUE(matches("const char x = (0);",
4875 varDecl(hasInitializer(ignoringParenImpCasts(
4876 integerLiteral(equals(0)))))));
4879 TEST(IgnoringParenAndImpCasts
, MatchesWithoutParenImpCasts
) {
4880 // This test verifies that expressions that do not have parentheses or
4881 // implicit casts still match.
4882 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4883 varDecl(hasInitializer(ignoringParenImpCasts(
4884 declRefExpr(to(varDecl(hasName("x")))))))));
4885 EXPECT_TRUE(matches("int x = 0;",
4886 varDecl(hasInitializer(ignoringParenImpCasts(
4887 integerLiteral(equals(0)))))));
4890 TEST(IgnoringParenAndImpCasts
, DoesNotMatchIncorrectly
) {
4891 // These tests verify that ignoringParenImpCasts does not match if
4892 // the inner matcher does not match.
4893 // This test creates an implicit cast.
4894 EXPECT_TRUE(notMatches("char c = ((3));",
4895 varDecl(hasInitializer(ignoringParenImpCasts(
4896 unless(anything()))))));
4897 // These tests verify that ignoringParenAndImplictCasts does not look
4898 // through explicit casts.
4899 EXPECT_TRUE(notMatches("float y = (float(0));",
4900 varDecl(hasInitializer(ignoringParenImpCasts(
4901 integerLiteral())))));
4902 EXPECT_TRUE(notMatches("float y = (float)0;",
4903 varDecl(hasInitializer(ignoringParenImpCasts(
4904 integerLiteral())))));
4905 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4906 varDecl(hasInitializer(ignoringParenImpCasts(
4907 integerLiteral())))));
4910 TEST(HasSourceExpression
, MatchesImplicitCasts
) {
4911 EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
4912 "void r() {string a_string; URL url = a_string; }",
4913 traverse(TK_AsIs
, implicitCastExpr(hasSourceExpression(
4914 cxxConstructExpr())))));
4917 TEST(HasSourceExpression
, MatchesExplicitCasts
) {
4919 matches("float x = static_cast<float>(42);",
4920 traverse(TK_AsIs
, explicitCastExpr(hasSourceExpression(
4921 hasDescendant(expr(integerLiteral())))))));
4924 TEST(UsingDeclaration
, MatchesSpecificTarget
) {
4925 EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",
4926 usingDecl(hasAnyUsingShadowDecl(
4927 hasTargetDecl(functionDecl())))));
4928 EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",
4929 usingDecl(hasAnyUsingShadowDecl(
4930 hasTargetDecl(functionDecl())))));
4933 TEST(UsingDeclaration
, ThroughUsingDeclaration
) {
4934 EXPECT_TRUE(matches(
4935 "namespace a { void f(); } using a::f; void g() { f(); }",
4936 declRefExpr(throughUsingDecl(anything()))));
4937 EXPECT_TRUE(notMatches(
4938 "namespace a { void f(); } using a::f; void g() { a::f(); }",
4939 declRefExpr(throughUsingDecl(anything()))));
4942 TEST(SingleDecl
, IsSingleDecl
) {
4943 StatementMatcher SingleDeclStmt
=
4944 declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));
4945 EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt
));
4946 EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt
));
4947 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4951 TEST(DeclStmt
, ContainsDeclaration
) {
4952 DeclarationMatcher MatchesInit
= varDecl(hasInitializer(anything()));
4954 EXPECT_TRUE(matches("void f() {int a = 4;}",
4955 declStmt(containsDeclaration(0, MatchesInit
))));
4956 EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
4957 declStmt(containsDeclaration(0, MatchesInit
),
4958 containsDeclaration(1, MatchesInit
))));
4959 unsigned WrongIndex
= 42;
4960 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4961 declStmt(containsDeclaration(WrongIndex
,
4965 TEST(SwitchCase
, MatchesEachCase
) {
4966 EXPECT_TRUE(notMatches("void x() { switch(42); }",
4967 switchStmt(forEachSwitchCase(caseStmt()))));
4968 EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
4969 switchStmt(forEachSwitchCase(caseStmt()))));
4970 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
4971 switchStmt(forEachSwitchCase(caseStmt()))));
4972 EXPECT_TRUE(notMatches(
4973 "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
4974 ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
4975 EXPECT_TRUE(matches(
4976 "void x() { switch(42) { case 1+1: case 4:; } }",
4977 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4978 constantExpr(has(integerLiteral())))))))));
4979 EXPECT_TRUE(notMatches(
4980 "void x() { switch(42) { case 1+1: case 2+2:; } }",
4981 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4982 constantExpr(has(integerLiteral())))))))));
4983 EXPECT_TRUE(notMatches(
4984 "void x() { switch(42) { case 1 ... 2:; } }",
4985 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4986 constantExpr(has(integerLiteral())))))))));
4987 EXPECT_TRUE(matchAndVerifyResultTrue(
4988 "void x() { switch (42) { case 1: case 2: case 3: default:; } }",
4989 switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
4990 std::make_unique
<VerifyIdIsBoundTo
<CaseStmt
>>("x", 3)));
4993 TEST(Declaration
, HasExplicitSpecifier
) {
4995 EXPECT_TRUE(notMatches("void f();",
4996 functionDecl(hasExplicitSpecifier(constantExpr())),
4997 langCxx20OrLater()));
4999 notMatches("template<bool b> struct S { explicit operator int(); };",
5001 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
5002 langCxx20OrLater()));
5004 notMatches("template<bool b> struct S { explicit(b) operator int(); };",
5006 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
5007 langCxx20OrLater()));
5009 matches("struct S { explicit(true) operator int(); };",
5010 traverse(TK_AsIs
, cxxConversionDecl(hasExplicitSpecifier(
5011 constantExpr(has(cxxBoolLiteral()))))),
5012 langCxx20OrLater()));
5014 matches("struct S { explicit(false) operator int(); };",
5015 traverse(TK_AsIs
, cxxConversionDecl(hasExplicitSpecifier(
5016 constantExpr(has(cxxBoolLiteral()))))),
5017 langCxx20OrLater()));
5019 notMatches("template<bool b> struct S { explicit(b) S(int); };",
5020 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
5021 constantExpr(has(cxxBoolLiteral()))))),
5022 langCxx20OrLater()));
5024 matches("struct S { explicit(true) S(int); };",
5025 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
5026 constantExpr(has(cxxBoolLiteral()))))),
5027 langCxx20OrLater()));
5029 matches("struct S { explicit(false) S(int); };",
5030 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
5031 constantExpr(has(cxxBoolLiteral()))))),
5032 langCxx20OrLater()));
5034 notMatches("template<typename T> struct S { S(int); };"
5035 "template<bool b = true> explicit(b) S(int) -> S<int>;",
5036 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
5037 constantExpr(has(cxxBoolLiteral()))))),
5038 langCxx20OrLater()));
5040 matches("template<typename T> struct S { S(int); };"
5041 "explicit(true) S(int) -> S<int>;",
5042 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
5043 constantExpr(has(cxxBoolLiteral()))))),
5044 langCxx20OrLater()));
5046 matches("template<typename T> struct S { S(int); };"
5047 "explicit(false) S(int) -> S<int>;",
5048 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
5049 constantExpr(has(cxxBoolLiteral()))))),
5050 langCxx20OrLater()));
5053 TEST(ForEachConstructorInitializer
, MatchesInitializers
) {
5054 EXPECT_TRUE(matches(
5055 "struct X { X() : i(42), j(42) {} int i, j; };",
5056 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
5059 TEST(LambdaCapture
, InvalidLambdaCapture
) {
5061 EXPECT_FALSE(matches(
5063 struct A { A()=default; A(A const&)=delete; };
5064 A a; [a]() -> void {}();
5067 traverse(TK_IgnoreUnlessSpelledInSource
,
5068 lambdaExpr(has(lambdaCapture()))),
5069 langCxx11OrLater()));
5072 TEST(ForEachLambdaCapture
, MatchesCaptures
) {
5073 EXPECT_TRUE(matches(
5074 "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
5075 lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));
5076 auto matcher
= lambdaExpr(forEachLambdaCapture(
5077 lambdaCapture(capturesVar(varDecl(hasType(isInteger())))).bind("LC")));
5078 EXPECT_TRUE(matchAndVerifyResultTrue(
5079 "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",
5080 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5081 EXPECT_TRUE(matchAndVerifyResultTrue(
5082 "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "
5084 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5087 TEST(ForEachLambdaCapture
, IgnoreUnlessSpelledInSource
) {
5089 traverse(TK_IgnoreUnlessSpelledInSource
,
5090 lambdaExpr(forEachLambdaCapture(
5091 lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))
5094 notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",
5095 matcher
, langCxx11OrLater()));
5097 notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",
5098 matcher
, langCxx11OrLater()));
5099 EXPECT_TRUE(matchAndVerifyResultTrue(
5104 auto f = [=, &y]() { return x + y + z; };
5107 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
5110 TEST(ForEachLambdaCapture
, MatchImplicitCapturesOnly
) {
5112 lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));
5113 EXPECT_TRUE(matchAndVerifyResultTrue(
5114 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
5115 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5116 EXPECT_TRUE(matchAndVerifyResultTrue(
5117 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
5118 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5121 TEST(ForEachLambdaCapture
, MatchExplicitCapturesOnly
) {
5122 auto matcher
= lambdaExpr(
5123 forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));
5124 EXPECT_TRUE(matchAndVerifyResultTrue(
5125 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
5126 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
5127 EXPECT_TRUE(matchAndVerifyResultTrue(
5128 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
5129 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
5132 TEST(HasConditionVariableStatement
, DoesNotMatchCondition
) {
5133 EXPECT_TRUE(notMatches(
5134 "void x() { if(true) {} }",
5135 ifStmt(hasConditionVariableStatement(declStmt()))));
5136 EXPECT_TRUE(notMatches(
5137 "void x() { int x; if((x = 42)) {} }",
5138 ifStmt(hasConditionVariableStatement(declStmt()))));
5141 TEST(HasConditionVariableStatement
, MatchesConditionVariables
) {
5142 EXPECT_TRUE(matches(
5143 "void x() { if(int* a = 0) {} }",
5144 ifStmt(hasConditionVariableStatement(declStmt()))));
5147 TEST(ForEach
, BindsOneNode
) {
5148 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
5149 recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),
5150 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("x", 1)));
5153 TEST(ForEach
, BindsMultipleNodes
) {
5154 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",
5155 recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),
5156 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 3)));
5159 TEST(ForEach
, BindsRecursiveCombinations
) {
5160 EXPECT_TRUE(matchAndVerifyResultTrue(
5161 "class C { class D { int x; int y; }; class E { int y; int z; }; };",
5162 recordDecl(hasName("C"),
5163 forEach(recordDecl(forEach(fieldDecl().bind("f"))))),
5164 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 4)));
5167 TEST(ForEach
, DoesNotIgnoreImplicit
) {
5168 StringRef Code
= R
"cpp(
5176 EXPECT_TRUE(matchAndVerifyResultFalse(
5177 Code
, binaryOperator(forEach(declRefExpr().bind("dre"))),
5178 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 0)));
5180 EXPECT_TRUE(matchAndVerifyResultTrue(
5182 binaryOperator(forEach(
5183 implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))),
5184 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
5186 EXPECT_TRUE(matchAndVerifyResultTrue(
5189 forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))),
5190 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
5192 EXPECT_TRUE(matchAndVerifyResultTrue(
5194 traverse(TK_IgnoreUnlessSpelledInSource
,
5195 binaryOperator(forEach(declRefExpr().bind("dre")))),
5196 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
5199 TEST(ForEachDescendant
, BindsOneNode
) {
5200 EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",
5201 recordDecl(hasName("C"),
5202 forEachDescendant(fieldDecl(hasName("x")).bind("x"))),
5203 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("x", 1)));
5206 TEST(ForEachDescendant
, NestedForEachDescendant
) {
5207 DeclarationMatcher m
= recordDecl(
5208 isDefinition(), decl().bind("x"), hasName("C"));
5209 EXPECT_TRUE(matchAndVerifyResultTrue(
5210 "class A { class B { class C {}; }; };",
5211 recordDecl(hasName("A"), anyOf(m
, forEachDescendant(m
))),
5212 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", "C")));
5214 // Check that a partial match of 'm' that binds 'x' in the
5215 // first part of anyOf(m, anything()) will not overwrite the
5216 // binding created by the earlier binding in the hasDescendant.
5217 EXPECT_TRUE(matchAndVerifyResultTrue(
5218 "class A { class B { class C {}; }; };",
5219 recordDecl(hasName("A"), allOf(hasDescendant(m
), anyOf(m
, anything()))),
5220 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", "C")));
5223 TEST(ForEachDescendant
, BindsMultipleNodes
) {
5224 EXPECT_TRUE(matchAndVerifyResultTrue(
5225 "class C { class D { int x; int y; }; "
5226 " class E { class F { int y; int z; }; }; };",
5227 recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),
5228 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 4)));
5231 TEST(ForEachDescendant
, BindsRecursiveCombinations
) {
5232 EXPECT_TRUE(matchAndVerifyResultTrue(
5233 "class C { class D { "
5234 " class E { class F { class G { int y; int z; }; }; }; }; };",
5235 recordDecl(hasName("C"), forEachDescendant(recordDecl(
5236 forEachDescendant(fieldDecl().bind("f"))))),
5237 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 8)));
5240 TEST(ForEachDescendant
, BindsCombinations
) {
5241 EXPECT_TRUE(matchAndVerifyResultTrue(
5242 "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "
5244 compoundStmt(forEachDescendant(ifStmt().bind("if")),
5245 forEachDescendant(whileStmt().bind("while"))),
5246 std::make_unique
<VerifyIdIsBoundTo
<IfStmt
>>("if", 6)));
5249 TEST(ForEachTemplateArgument
, OnFunctionDecl
) {
5250 const std::string Code
= R
"(
5251 template <typename T, typename U> void f(T, U) {}
5257 EXPECT_TRUE(matches(
5258 Code
, functionDecl(forEachTemplateArgument(refersToType(builtinType()))),
5259 langCxx11OrLater()));
5261 functionDecl(forEachTemplateArgument(
5262 templateArgument(refersToType(builtinType().bind("BT")))
5266 EXPECT_TRUE(matchAndVerifyResultTrue(
5268 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("FN", 2)));
5269 EXPECT_TRUE(matchAndVerifyResultTrue(
5271 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgument
>>("TA", 2)));
5272 EXPECT_TRUE(matchAndVerifyResultTrue(
5274 std::make_unique
<VerifyIdIsBoundTo
<BuiltinType
>>("BT", 2)));
5277 TEST(ForEachTemplateArgument
, OnClassTemplateSpecialization
) {
5278 const std::string Code
= R
"(
5279 template <typename T, unsigned N, unsigned M>
5282 static constexpr unsigned R = 2;
5284 Matrix<int, R * 2, R * 4> M;
5286 EXPECT_TRUE(matches(
5287 Code
, templateSpecializationType(forEachTemplateArgument(isExpr(expr()))),
5288 langCxx11OrLater()));
5289 auto matcher
= templateSpecializationType(
5290 forEachTemplateArgument(
5291 templateArgument(isExpr(expr().bind("E"))).bind("TA")))
5294 EXPECT_TRUE(matchAndVerifyResultTrue(
5296 std::make_unique
<VerifyIdIsBoundTo
<TemplateSpecializationType
>>("TST",
5298 EXPECT_TRUE(matchAndVerifyResultTrue(
5300 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgument
>>("TA", 2)));
5301 EXPECT_TRUE(matchAndVerifyResultTrue(
5302 Code
, matcher
, std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("E", 2)));
5305 TEST(Has
, DoesNotDeleteBindings
) {
5306 EXPECT_TRUE(matchAndVerifyResultTrue(
5307 "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),
5308 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5311 TEST(TemplateArgumentLoc
, Matches
) {
5312 EXPECT_TRUE(matchAndVerifyResultTrue(
5314 template <typename A, int B, template <typename> class C> class X {};
5317 template <typename> class C {};
5320 templateArgumentLoc().bind("x"),
5321 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgumentLoc
>>("x", 3)));
5324 TEST(LoopingMatchers
, DoNotOverwritePreviousMatchResultOnFailure
) {
5325 // Those matchers cover all the cases where an inner matcher is called
5326 // and there is not a 1:1 relationship between the match of the outer
5327 // matcher and the match of the inner matcher.
5328 // The pattern to look for is:
5329 // ... return InnerMatcher.matches(...); ...
5330 // In which case no special handling is needed.
5332 // On the other hand, if there are multiple alternative matches
5333 // (for example forEach*) or matches might be discarded (for example has*)
5334 // the implementation must make sure that the discarded matches do not
5335 // affect the bindings.
5336 // When new such matchers are added, add a test here that:
5337 // - matches a simple node, and binds it as the first thing in the matcher:
5338 // recordDecl(decl().bind("x"), hasName("X")))
5339 // - uses the matcher under test afterwards in a way that not the first
5340 // alternative is matched; for anyOf, that means the first branch
5341 // would need to return false; for hasAncestor, it means that not
5342 // the direct parent matches the inner matcher.
5344 EXPECT_TRUE(matchAndVerifyResultTrue(
5345 "class X { int y; };",
5347 recordDecl().bind("x"), hasName("::X"),
5348 anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),
5349 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("x", 1)));
5350 EXPECT_TRUE(matchAndVerifyResultTrue(
5351 "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),
5352 anyOf(unless(anything()), anything())),
5353 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("x", 1)));
5354 EXPECT_TRUE(matchAndVerifyResultTrue(
5355 "template<typename T1, typename T2> class X {}; X<float, int> x;",
5356 classTemplateSpecializationDecl(
5358 hasAnyTemplateArgument(refersToType(asString("int")))),
5359 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5360 EXPECT_TRUE(matchAndVerifyResultTrue(
5361 "class X { void f(); void g(); };",
5362 cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
5363 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5364 EXPECT_TRUE(matchAndVerifyResultTrue(
5365 "class X { X() : a(1), b(2) {} double a; int b; };",
5366 recordDecl(decl().bind("x"),
5367 has(cxxConstructorDecl(
5368 hasAnyConstructorInitializer(forField(hasName("b")))))),
5369 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5370 EXPECT_TRUE(matchAndVerifyResultTrue(
5371 "void x(int, int) { x(0, 42); }",
5372 callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),
5373 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("x", 1)));
5374 EXPECT_TRUE(matchAndVerifyResultTrue(
5375 "void x(int, int y) {}",
5376 functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),
5377 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5378 EXPECT_TRUE(matchAndVerifyResultTrue(
5379 "void x() { return; if (true) {} }",
5380 functionDecl(decl().bind("x"),
5381 has(compoundStmt(hasAnySubstatement(ifStmt())))),
5382 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5383 EXPECT_TRUE(matchAndVerifyResultTrue(
5384 "namespace X { void b(int); void b(); }"
5386 usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(
5387 functionDecl(parameterCountIs(1))))),
5388 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5389 EXPECT_TRUE(matchAndVerifyResultTrue(
5390 "class A{}; class B{}; class C : B, A {};",
5391 cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A")),
5392 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5393 EXPECT_TRUE(matchAndVerifyResultTrue(
5394 "class A{}; typedef A B; typedef A C; typedef A D;"
5396 cxxRecordDecl(decl().bind("x"), isDerivedFrom("C")),
5397 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5398 EXPECT_TRUE(matchAndVerifyResultTrue(
5399 "class A { class B { void f() {} }; };",
5400 functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5401 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5402 EXPECT_TRUE(matchAndVerifyResultTrue(
5403 "template <typename T> struct A { struct B {"
5404 " void f() { if(true) {} }"
5406 "void t() { A<int>::B b; b.f(); }",
5407 ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5408 std::make_unique
<VerifyIdIsBoundTo
<Stmt
>>("x", 2)));
5409 EXPECT_TRUE(matchAndVerifyResultTrue(
5411 recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),
5412 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5413 EXPECT_TRUE(matchAndVerifyResultTrue(
5414 "class A { A() : s(), i(42) {} const char *s; int i; };",
5415 cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),
5416 forEachConstructorInitializer(forField(hasName("i")))),
5417 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5420 TEST(ForEachDescendant
, BindsCorrectNodes
) {
5421 EXPECT_TRUE(matchAndVerifyResultTrue(
5422 "class C { void f(); int i; };",
5423 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5424 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("decl", 1)));
5425 EXPECT_TRUE(matchAndVerifyResultTrue(
5426 "class C { void f() {} int i; };",
5427 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5428 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("decl", 1)));
5431 TEST(FindAll
, BindsNodeOnMatch
) {
5432 EXPECT_TRUE(matchAndVerifyResultTrue(
5434 recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),
5435 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("v", 1)));
5438 TEST(FindAll
, BindsDescendantNodeOnMatch
) {
5439 EXPECT_TRUE(matchAndVerifyResultTrue(
5440 "class A { int a; int b; };",
5441 recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),
5442 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("v", 2)));
5445 TEST(FindAll
, BindsNodeAndDescendantNodesOnOneMatch
) {
5446 EXPECT_TRUE(matchAndVerifyResultTrue(
5447 "class A { int a; int b; };",
5448 recordDecl(hasName("::A"),
5449 findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),
5450 fieldDecl().bind("v"))))),
5451 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("v", 3)));
5453 EXPECT_TRUE(matchAndVerifyResultTrue(
5454 "class A { class B {}; class C {}; };",
5455 recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),
5456 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("v", 3)));
5459 TEST(HasAncenstor
, MatchesDeclarationAncestors
) {
5460 EXPECT_TRUE(matches(
5461 "class A { class B { class C {}; }; };",
5462 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));
5465 TEST(HasAncenstor
, FailsIfNoAncestorMatches
) {
5466 EXPECT_TRUE(notMatches(
5467 "class A { class B { class C {}; }; };",
5468 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));
5471 TEST(HasAncestor
, MatchesDeclarationsThatGetVisitedLater
) {
5472 EXPECT_TRUE(matches(
5473 "class A { class B { void f() { C c; } class C {}; }; };",
5474 varDecl(hasName("c"), hasType(recordDecl(hasName("C"),
5475 hasAncestor(recordDecl(hasName("A"))))))));
5478 TEST(HasAncenstor
, MatchesStatementAncestors
) {
5479 EXPECT_TRUE(matches(
5480 "void f() { if (true) { while (false) { 42; } } }",
5481 integerLiteral(equals(42), hasAncestor(ifStmt()))));
5484 TEST(HasAncestor
, DrillsThroughDifferentHierarchies
) {
5485 EXPECT_TRUE(matches(
5486 "void f() { if (true) { int x = 42; } }",
5487 integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));
5490 TEST(HasAncestor
, BindsRecursiveCombinations
) {
5491 EXPECT_TRUE(matchAndVerifyResultTrue(
5492 "class C { class D { class E { class F { int y; }; }; }; };",
5493 fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),
5494 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("r", 1)));
5497 TEST(HasAncestor
, BindsCombinationsWithHasDescendant
) {
5498 EXPECT_TRUE(matchAndVerifyResultTrue(
5499 "class C { class D { class E { class F { int y; }; }; }; };",
5500 fieldDecl(hasAncestor(
5502 hasDescendant(recordDecl(isDefinition(),
5503 hasAncestor(recordDecl())))
5506 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("d", "E")));
5509 TEST(HasAncestor
, MatchesClosestAncestor
) {
5510 EXPECT_TRUE(matchAndVerifyResultTrue(
5511 "template <typename T> struct C {"
5513 " struct I { void g(T) { int x; } } i; i.g(42);"
5516 "template struct C<int>;",
5517 varDecl(hasName("x"),
5518 hasAncestor(functionDecl(hasParameter(
5519 0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),
5520 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("f", "g", 2)));
5523 TEST(HasAncestor
, MatchesInTemplateInstantiations
) {
5524 EXPECT_TRUE(matches(
5525 "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
5527 fieldDecl(hasType(asString("int")),
5528 hasAncestor(recordDecl(hasName("A"))))));
5531 TEST(HasAncestor
, MatchesInImplicitCode
) {
5532 EXPECT_TRUE(matches(
5533 "struct X {}; struct A { A() {} X x; };",
5535 hasAnyConstructorInitializer(withInitializer(expr(
5536 hasAncestor(recordDecl(hasName("A")))))))));
5539 TEST(HasParent
, MatchesOnlyParent
) {
5540 EXPECT_TRUE(matches(
5541 "void f() { if (true) { int x = 42; } }",
5542 compoundStmt(hasParent(ifStmt()))));
5543 EXPECT_TRUE(notMatches(
5544 "void f() { for (;;) { int x = 42; } }",
5545 compoundStmt(hasParent(ifStmt()))));
5546 EXPECT_TRUE(notMatches(
5547 "void f() { if (true) for (;;) { int x = 42; } }",
5548 compoundStmt(hasParent(ifStmt()))));
5551 TEST(MatcherMemoize
, HasParentDiffersFromHas
) {
5552 // Test introduced after detecting a bug in memoization
5553 constexpr auto code
= "void f() { throw 1; }";
5554 EXPECT_TRUE(notMatches(
5556 cxxThrowExpr(hasParent(expr()))));
5557 EXPECT_TRUE(matches(
5559 cxxThrowExpr(has(expr()))));
5560 EXPECT_TRUE(matches(
5562 cxxThrowExpr(anyOf(hasParent(expr()), has(expr())))));
5565 TEST(MatcherMemoize
, HasDiffersFromHasDescendant
) {
5566 // Test introduced after detecting a bug in memoization
5567 constexpr auto code
= "void f() { throw 1+1; }";
5568 EXPECT_TRUE(notMatches(
5570 cxxThrowExpr(has(integerLiteral()))));
5571 EXPECT_TRUE(matches(
5573 cxxThrowExpr(hasDescendant(integerLiteral()))));
5575 notMatches(code
, cxxThrowExpr(allOf(hasDescendant(integerLiteral()),
5576 has(integerLiteral())))));
5578 TEST(HasAncestor
, MatchesAllAncestors
) {
5579 EXPECT_TRUE(matches(
5580 "template <typename T> struct C { static void f() { 42; } };"
5581 "void t() { C<int>::f(); }",
5585 hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
5586 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
5589 TEST(HasAncestor
, ImplicitArrayCopyCtorDeclRefExpr
) {
5590 EXPECT_TRUE(matches("struct MyClass {\n"
5592 " static MyClass Create() { return MyClass(); }\n"
5594 declRefExpr(to(decl(hasAncestor(decl()))))));
5597 TEST(HasAncestor
, AnonymousUnionMemberExpr
) {
5598 EXPECT_TRUE(matches("int F() {\n"
5599 " union { int i; };\n"
5602 memberExpr(member(hasAncestor(decl())))));
5603 EXPECT_TRUE(matches("void f() {\n"
5605 " struct { int a; int b; };\n"
5609 memberExpr(member(hasAncestor(decl())))));
5610 EXPECT_TRUE(matches("void f() {\n"
5612 " struct { int a; int b; };\n"
5616 declRefExpr(to(decl(hasAncestor(decl()))))));
5618 TEST(HasAncestor
, NonParmDependentTemplateParmVarDeclRefExpr
) {
5619 EXPECT_TRUE(matches("struct PartitionAllocator {\n"
5620 " template<typename T>\n"
5621 " static int quantizedSize(int count) {\n"
5624 " void f() { quantizedSize<int>(10); }\n"
5626 declRefExpr(to(decl(hasAncestor(decl()))))));
5629 TEST(HasAncestor
, AddressOfExplicitSpecializationFunction
) {
5630 EXPECT_TRUE(matches("template <class T> void f();\n"
5631 "template <> void f<int>();\n"
5632 "void (*get_f())() { return f<int>; }\n",
5633 declRefExpr(to(decl(hasAncestor(decl()))))));
5636 TEST(HasParent
, MatchesAllParents
) {
5637 EXPECT_TRUE(matches(
5638 "template <typename T> struct C { static void f() { 42; } };"
5639 "void t() { C<int>::f(); }",
5642 hasParent(compoundStmt(hasParent(functionDecl(
5643 hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));
5645 matches("template <typename T> struct C { static void f() { 42; } };"
5646 "void t() { C<int>::f(); }",
5649 hasParent(compoundStmt(hasParent(functionDecl(hasParent(
5650 cxxRecordDecl(unless(isTemplateInstantiation()))))))))));
5651 EXPECT_TRUE(matches(
5652 "template <typename T> struct C { static void f() { 42; } };"
5653 "void t() { C<int>::f(); }",
5654 integerLiteral(equals(42),
5655 hasParent(compoundStmt(
5656 allOf(hasParent(functionDecl(hasParent(
5657 cxxRecordDecl(isTemplateInstantiation())))),
5658 hasParent(functionDecl(hasParent(cxxRecordDecl(
5659 unless(isTemplateInstantiation())))))))))));
5661 notMatches("template <typename T> struct C { static void f() {} };"
5662 "void t() { C<int>::f(); }",
5663 compoundStmt(hasParent(recordDecl()))));
5666 TEST(HasParent
, NoDuplicateParents
) {
5667 class HasDuplicateParents
: public BoundNodesCallback
{
5669 bool run(const BoundNodes
*Nodes
, ASTContext
*Context
) override
{
5670 const Stmt
*Node
= Nodes
->getNodeAs
<Stmt
>("node");
5671 std::set
<const void *> Parents
;
5672 for (const auto &Parent
: Context
->getParents(*Node
)) {
5673 if (!Parents
.insert(Parent
.getMemoizationData()).second
) {
5680 EXPECT_FALSE(matchAndVerifyResultTrue(
5681 "template <typename T> int Foo() { return 1 + 2; }\n"
5682 "int x = Foo<int>() + Foo<unsigned>();",
5683 stmt().bind("node"), std::make_unique
<HasDuplicateParents
>()));
5686 TEST(HasAnyBase
, BindsInnerBoundNodes
) {
5687 EXPECT_TRUE(matchAndVerifyResultTrue(
5688 "struct Inner {}; struct Proxy : Inner {}; struct Main : public "
5690 cxxRecordDecl(hasName("Main"),
5691 hasAnyBase(cxxBaseSpecifier(hasType(
5692 cxxRecordDecl(hasName("Inner")).bind("base-class")))))
5694 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("base-class",
5698 TEST(TypeMatching
, PointeeTypes
) {
5699 EXPECT_TRUE(matches("int b; int &a = b;",
5700 referenceType(pointee(builtinType()))));
5701 EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));
5703 EXPECT_TRUE(matches("int *a;",
5704 loc(pointerType(pointee(builtinType())))));
5706 EXPECT_TRUE(matches(
5708 pointerType(pointee(isConstQualified(), builtinType()))));
5709 EXPECT_TRUE(notMatches(
5711 pointerType(pointee(isConstQualified(), builtinType()))));
5714 TEST(ElaboratedTypeNarrowing
, hasQualifier
) {
5715 EXPECT_TRUE(matches(
5722 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5723 EXPECT_TRUE(notMatches(
5728 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5729 EXPECT_TRUE(notMatches(
5732 elaboratedType(hasQualifier(nestedNameSpecifier()))));
5735 TEST(ElaboratedTypeNarrowing
, namesType
) {
5736 EXPECT_TRUE(matches(
5743 elaboratedType(elaboratedType(namesType(recordType(
5744 hasDeclaration(namedDecl(hasName("D")))))))));
5745 EXPECT_TRUE(notMatches(
5750 elaboratedType(elaboratedType(namesType(typedefType())))));
5753 TEST(NNS
, BindsNestedNameSpecifiers
) {
5754 EXPECT_TRUE(matchAndVerifyResultTrue(
5755 "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
5756 nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
5757 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>(
5758 "nns", "ns::struct E::")));
5761 TEST(NNS
, BindsNestedNameSpecifierLocs
) {
5762 EXPECT_TRUE(matchAndVerifyResultTrue(
5763 "namespace ns { struct B {}; } ns::B b;",
5764 loc(nestedNameSpecifier()).bind("loc"),
5765 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("loc", 1)));
5768 TEST(NNS
, DescendantsOfNestedNameSpecifiers
) {
5769 StringRef Fragment
=
5770 "namespace a { struct A { struct B { struct C {}; }; }; };"
5771 "void f() { a::A::B::C c; }";
5772 EXPECT_TRUE(matches(
5774 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5775 hasDescendant(nestedNameSpecifier(
5776 specifiesNamespace(hasName("a")))))));
5777 EXPECT_TRUE(notMatches(
5779 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5780 has(nestedNameSpecifier(
5781 specifiesNamespace(hasName("a")))))));
5782 EXPECT_TRUE(matches(
5784 nestedNameSpecifier(specifiesType(asString("struct a::A")),
5785 has(nestedNameSpecifier(
5786 specifiesNamespace(hasName("a")))))));
5788 // Not really useful because a NestedNameSpecifier can af at most one child,
5789 // but to complete the interface.
5790 EXPECT_TRUE(matchAndVerifyResultTrue(
5792 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5793 forEach(nestedNameSpecifier().bind("x"))),
5794 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>("x", 1)));
5797 TEST(NNS
, NestedNameSpecifiersAsDescendants
) {
5798 StringRef Fragment
=
5799 "namespace a { struct A { struct B { struct C {}; }; }; };"
5800 "void f() { a::A::B::C c; }";
5801 EXPECT_TRUE(matches(
5803 decl(hasDescendant(nestedNameSpecifier(specifiesType(
5804 asString("struct a::A")))))));
5805 EXPECT_TRUE(matchAndVerifyResultTrue(
5807 functionDecl(hasName("f"),
5808 forEachDescendant(nestedNameSpecifier().bind("x"))),
5809 // Nested names: a, a::A and a::A::B.
5810 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>("x", 3)));
5813 TEST(NNSLoc
, DescendantsOfNestedNameSpecifierLocs
) {
5814 StringRef Fragment
=
5815 "namespace a { struct A { struct B { struct C {}; }; }; };"
5816 "void f() { a::A::B::C c; }";
5817 EXPECT_TRUE(matches(
5819 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5820 hasDescendant(loc(nestedNameSpecifier(
5821 specifiesNamespace(hasName("a"))))))));
5822 EXPECT_TRUE(notMatches(
5824 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5825 has(loc(nestedNameSpecifier(
5826 specifiesNamespace(hasName("a"))))))));
5827 EXPECT_TRUE(matches(
5829 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
5830 has(loc(nestedNameSpecifier(
5831 specifiesNamespace(hasName("a"))))))));
5833 EXPECT_TRUE(matchAndVerifyResultTrue(
5835 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5836 forEach(nestedNameSpecifierLoc().bind("x"))),
5837 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("x", 1)));
5840 TEST(NNSLoc
, NestedNameSpecifierLocsAsDescendants
) {
5841 StringRef Fragment
=
5842 "namespace a { struct A { struct B { struct C {}; }; }; };"
5843 "void f() { a::A::B::C c; }";
5844 EXPECT_TRUE(matches(
5846 decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
5847 asString("struct a::A"))))))));
5848 EXPECT_TRUE(matchAndVerifyResultTrue(
5850 functionDecl(hasName("f"),
5851 forEachDescendant(nestedNameSpecifierLoc().bind("x"))),
5852 // Nested names: a, a::A and a::A::B.
5853 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("x", 3)));
5856 TEST(Attr
, AttrsAsDescendants
) {
5857 StringRef Fragment
= "namespace a { struct [[clang::warn_unused_result]] "
5858 "F{}; [[noreturn]] void foo(); }";
5859 EXPECT_TRUE(matches(Fragment
, namespaceDecl(hasDescendant(attr()))));
5860 EXPECT_TRUE(matchAndVerifyResultTrue(
5862 namespaceDecl(hasName("a"),
5863 forEachDescendant(attr(unless(isImplicit())).bind("x"))),
5864 std::make_unique
<VerifyIdIsBoundTo
<Attr
>>("x", 2)));
5867 TEST(Attr
, ParentsOfAttrs
) {
5868 StringRef Fragment
=
5869 "namespace a { struct [[clang::warn_unused_result]] F{}; }";
5870 EXPECT_TRUE(matches(Fragment
, attr(hasAncestor(namespaceDecl()))));
5873 template <typename T
> class VerifyMatchOnNode
: public BoundNodesCallback
{
5875 VerifyMatchOnNode(StringRef Id
, const internal::Matcher
<T
> &InnerMatcher
,
5877 : Id(Id
), InnerMatcher(InnerMatcher
), InnerId(InnerId
) {}
5879 bool run(const BoundNodes
*Nodes
, ASTContext
*Context
) override
{
5880 const T
*Node
= Nodes
->getNodeAs
<T
>(Id
);
5881 return selectFirst
<T
>(InnerId
, match(InnerMatcher
, *Node
, *Context
)) !=
5887 internal::Matcher
<T
> InnerMatcher
;
5888 std::string InnerId
;
5891 TEST(MatchFinder
, CanMatchDeclarationsRecursively
) {
5892 EXPECT_TRUE(matchAndVerifyResultTrue(
5893 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5894 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5895 "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),
5897 EXPECT_TRUE(matchAndVerifyResultFalse(
5898 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5899 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5900 "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),
5904 TEST(MatchFinder
, CanMatchStatementsRecursively
) {
5905 EXPECT_TRUE(matchAndVerifyResultTrue(
5906 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5907 std::make_unique
<VerifyMatchOnNode
<Stmt
>>(
5908 "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));
5909 EXPECT_TRUE(matchAndVerifyResultFalse(
5910 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5911 std::make_unique
<VerifyMatchOnNode
<Stmt
>>(
5912 "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));
5915 TEST(MatchFinder
, CanMatchSingleNodesRecursively
) {
5916 EXPECT_TRUE(matchAndVerifyResultTrue(
5917 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5918 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5919 "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));
5920 EXPECT_TRUE(matchAndVerifyResultFalse(
5921 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5922 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5923 "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));
5926 TEST(StatementMatcher
, HasReturnValue
) {
5927 StatementMatcher RetVal
= returnStmt(hasReturnValue(binaryOperator()));
5928 EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal
));
5929 EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal
));
5930 EXPECT_FALSE(matches("void F() { return; }", RetVal
));
5933 TEST(StatementMatcher
, ForFunction
) {
5934 StringRef CppString1
= "struct PosVec {"
5935 " PosVec& operator=(const PosVec&) {"
5936 " auto x = [] { return 1; };"
5940 StringRef CppString2
= "void F() {"
5950 returnStmt(forFunction(hasName("operator=")),
5951 has(unaryOperator(hasOperatorName("*"))))));
5955 returnStmt(forFunction(hasName("operator=")),
5956 has(integerLiteral()))));
5960 returnStmt(forFunction(hasName("operator()")),
5961 has(integerLiteral()))));
5962 EXPECT_TRUE(matches(CppString2
, returnStmt(forFunction(hasName("F2")))));
5963 EXPECT_TRUE(notMatches(CppString2
, returnStmt(forFunction(hasName("F")))));
5966 TEST(StatementMatcher
, ForCallable
) {
5967 // These tests are copied over from the forFunction() test above.
5968 StringRef CppString1
= "struct PosVec {"
5969 " PosVec& operator=(const PosVec&) {"
5970 " auto x = [] { return 1; };"
5974 StringRef CppString2
= "void F() {"
5985 returnStmt(forCallable(functionDecl(hasName("operator="))),
5986 has(unaryOperator(hasOperatorName("*"))))));
5990 returnStmt(forCallable(functionDecl(hasName("operator="))),
5991 has(integerLiteral()))));
5995 returnStmt(forCallable(functionDecl(hasName("operator()"))),
5996 has(integerLiteral()))));
5997 EXPECT_TRUE(matches(CppString2
,
5998 returnStmt(forCallable(functionDecl(hasName("F2"))))));
5999 EXPECT_TRUE(notMatches(CppString2
,
6000 returnStmt(forCallable(functionDecl(hasName("F"))))));
6002 StringRef CodeWithDeepCallExpr
= R
"cpp(
6012 auto ForCallableFirst
=
6013 callExpr(forCallable(functionDecl(hasName("Function"))),
6014 callee(functionDecl(hasName("Other")).bind("callee")))
6016 auto ForCallableSecond
=
6017 callExpr(callee(functionDecl(hasName("Other")).bind("callee")),
6018 forCallable(functionDecl(hasName("Function"))))
6020 EXPECT_TRUE(matchAndVerifyResultTrue(
6021 CodeWithDeepCallExpr
, ForCallableFirst
,
6022 std::make_unique
<VerifyIdIsBoundTo
<CallExpr
>>("call")));
6023 EXPECT_TRUE(matchAndVerifyResultTrue(
6024 CodeWithDeepCallExpr
, ForCallableFirst
,
6025 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("callee")));
6026 EXPECT_TRUE(matchAndVerifyResultTrue(
6027 CodeWithDeepCallExpr
, ForCallableSecond
,
6028 std::make_unique
<VerifyIdIsBoundTo
<CallExpr
>>("call")));
6029 EXPECT_TRUE(matchAndVerifyResultTrue(
6030 CodeWithDeepCallExpr
, ForCallableSecond
,
6031 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("callee")));
6033 // These tests are specific to forCallable().
6034 StringRef ObjCString1
= "@interface I"
6039 " void (^block)() = ^{ 0x2b | ~0x2b; };"
6046 binaryOperator(forCallable(blockDecl()))));
6051 binaryOperator(forCallable(objcMethodDecl()))));
6053 StringRef ObjCString2
= "@interface I"
6059 " void (^block)() = ^{};"
6066 binaryOperator(forCallable(objcMethodDecl()))));
6071 binaryOperator(forCallable(blockDecl()))));
6075 class ForCallablePreservesBindingWithMultipleParentsTestCallback
6076 : public BoundNodesCallback
{
6078 bool run(const BoundNodes
*BoundNodes
, ASTContext
*Context
) override
{
6079 FunctionDecl
const *FunDecl
=
6080 BoundNodes
->getNodeAs
<FunctionDecl
>("funDecl");
6081 // Validate test assumptions. This would be expressed as ASSERT_* in
6084 EXPECT_TRUE(false && "Incorrect test setup");
6087 auto const *FunDef
= FunDecl
->getDefinition();
6088 if (!FunDef
|| !FunDef
->getBody() ||
6089 FunDef
->getNameAsString() != "Function") {
6090 EXPECT_TRUE(false && "Incorrect test setup");
6094 ExpectCorrectResult(
6096 callExpr(callee(cxxMethodDecl().bind("callee"))).bind("call"), //
6099 ExpectCorrectResult("ForCallable first",
6100 callExpr(forCallable(equalsNode(FunDecl
)),
6101 callee(cxxMethodDecl().bind("callee")))
6105 ExpectCorrectResult("ForCallable second",
6106 callExpr(callee(cxxMethodDecl().bind("callee")),
6107 forCallable(equalsNode(FunDecl
)))
6111 // This value does not really matter: the EXPECT_* will set the exit code.
6116 void ExpectCorrectResult(StringRef LogInfo
,
6117 ArrayRef
<BoundNodes
> Results
) const {
6118 EXPECT_EQ(Results
.size(), 1u) << LogInfo
;
6119 if (Results
.empty())
6121 auto const &R
= Results
.front();
6122 EXPECT_TRUE(R
.getNodeAs
<CallExpr
>("call")) << LogInfo
;
6123 EXPECT_TRUE(R
.getNodeAs
<CXXMethodDecl
>("callee")) << LogInfo
;
6126 template <typename MatcherT
>
6127 void ExpectCorrectResult(StringRef LogInfo
, MatcherT Matcher
,
6128 FunctionDecl
const *FunDef
) const {
6129 auto &Context
= FunDef
->getASTContext();
6130 auto const &Results
= match(findAll(Matcher
), *FunDef
->getBody(), Context
);
6131 ExpectCorrectResult(LogInfo
, Results
);
6136 TEST(StatementMatcher
, ForCallablePreservesBindingWithMultipleParents
) {
6137 // Tests in this file are fairly simple and therefore can rely on matches,
6138 // matchAndVerifyResultTrue, etc. This test, however, needs a FunctionDecl* in
6139 // order to call equalsNode in order to reproduce the observed issue (bindings
6140 // being removed despite forCallable matching the node).
6142 // Because of this and because the machinery to compile the code into an
6143 // ASTUnit is not exposed outside matchAndVerifyResultConditionally, it is
6144 // cheaper to have a custom BoundNodesCallback for the purpose of this test.
6145 StringRef codeWithTemplateFunction
= R
"cpp(
6148 template <typename T>
6149 void Function(T t); // Declaration
6152 void Instantiate(Klass k) {
6156 template <typename T>
6157 void Klass::Function(T t) { // Definition
6158 // Compound statement has two parents: the declaration and the definition.
6162 EXPECT_TRUE(matchAndVerifyResultTrue(
6163 codeWithTemplateFunction
,
6164 callExpr(callee(functionDecl(hasName("Function")).bind("funDecl"))),
6166 ForCallablePreservesBindingWithMultipleParentsTestCallback
>()));
6169 TEST(Matcher
, ForEachOverriden
) {
6170 const auto ForEachOverriddenInClass
= [](const char *ClassName
) {
6171 return cxxMethodDecl(ofClass(hasName(ClassName
)), isVirtual(),
6172 forEachOverridden(cxxMethodDecl().bind("overridden")))
6175 static const char Code1
[] = "class A { virtual void f(); };"
6176 "class B : public A { void f(); };"
6177 "class C : public B { void f(); };";
6178 // C::f overrides A::f.
6179 EXPECT_TRUE(matchAndVerifyResultTrue(
6180 Code1
, ForEachOverriddenInClass("C"),
6181 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 1)));
6182 EXPECT_TRUE(matchAndVerifyResultTrue(
6183 Code1
, ForEachOverriddenInClass("C"),
6184 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
6186 // B::f overrides A::f.
6187 EXPECT_TRUE(matchAndVerifyResultTrue(
6188 Code1
, ForEachOverriddenInClass("B"),
6189 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 1)));
6190 EXPECT_TRUE(matchAndVerifyResultTrue(
6191 Code1
, ForEachOverriddenInClass("B"),
6192 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
6194 // A::f overrides nothing.
6195 EXPECT_TRUE(notMatches(Code1
, ForEachOverriddenInClass("A")));
6197 static const char Code2
[] =
6198 "class A1 { virtual void f(); };"
6199 "class A2 { virtual void f(); };"
6200 "class B : public A1, public A2 { void f(); };";
6201 // B::f overrides A1::f and A2::f. This produces two matches.
6202 EXPECT_TRUE(matchAndVerifyResultTrue(
6203 Code2
, ForEachOverriddenInClass("B"),
6204 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 2)));
6205 EXPECT_TRUE(matchAndVerifyResultTrue(
6206 Code2
, ForEachOverriddenInClass("B"),
6207 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
6209 // A1::f overrides nothing.
6210 EXPECT_TRUE(notMatches(Code2
, ForEachOverriddenInClass("A1")));
6213 TEST(Matcher
, HasAnyDeclaration
) {
6214 StringRef Fragment
= "void foo(int p1);"
6215 "void foo(int *p2);"
6217 "template <typename T> void baz(T t) { foo(t); }";
6220 matches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6221 hasParameter(0, parmVarDecl(hasName("p1"))))))));
6223 matches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6224 hasParameter(0, parmVarDecl(hasName("p2"))))))));
6226 notMatches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6227 hasParameter(0, parmVarDecl(hasName("p3"))))))));
6228 EXPECT_TRUE(notMatches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(
6229 functionDecl(hasName("bar"))))));
6232 TEST(SubstTemplateTypeParmType
, HasReplacementType
) {
6233 StringRef Fragment
= "template<typename T>"
6237 EXPECT_TRUE(matches(Fragment
, substTemplateTypeParmType(hasReplacementType(
6238 qualType(asString("int"))))));
6239 EXPECT_TRUE(notMatches(Fragment
, substTemplateTypeParmType(hasReplacementType(
6240 qualType(asString("double"))))));
6242 notMatches("template<int N>"
6244 "double j = F<5>();",
6245 substTemplateTypeParmType(hasReplacementType(qualType()))));
6248 TEST(ClassTemplateSpecializationDecl
, HasSpecializedTemplate
) {
6249 auto Matcher
= classTemplateSpecializationDecl(
6250 hasSpecializedTemplate(classTemplateDecl()));
6252 matches("template<typename T> class A {}; typedef A<int> B;", Matcher
));
6253 EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher
));
6256 TEST(CXXNewExpr
, Array
) {
6257 StatementMatcher NewArray
= cxxNewExpr(isArray());
6259 EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray
));
6260 EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray
));
6262 StatementMatcher NewArraySize10
=
6263 cxxNewExpr(hasArraySize(integerLiteral(equals(10))));
6265 matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10
));
6267 notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10
));
6270 TEST(CXXNewExpr
, PlacementArgs
) {
6271 StatementMatcher IsPlacementNew
= cxxNewExpr(hasAnyPlacementArg(anything()));
6273 EXPECT_TRUE(matches(R
"(
6274 void* operator new(decltype(sizeof(void*)), void*);
6275 int *foo(void* Storage) {
6276 return new (Storage) int;
6280 EXPECT_TRUE(matches(R
"(
6281 void* operator new(decltype(sizeof(void*)), void*, unsigned);
6282 int *foo(void* Storage) {
6283 return new (Storage, 16) int;
6285 cxxNewExpr(hasPlacementArg(
6286 1, ignoringImpCasts(integerLiteral(equals(16)))))));
6288 EXPECT_TRUE(notMatches(R
"(
6289 void* operator new(decltype(sizeof(void*)), void*);
6290 int *foo(void* Storage) {
6296 TEST(HasUnqualifiedLoc
, BindsToConstIntVarDecl
) {
6297 EXPECT_TRUE(matches(
6299 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6300 hasUnqualifiedLoc(loc(asString("int"))))))));
6303 TEST(HasUnqualifiedLoc
, BindsToVolatileIntVarDecl
) {
6304 EXPECT_TRUE(matches(
6305 "volatile int x = 0;",
6306 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6307 hasUnqualifiedLoc(loc(asString("int"))))))));
6310 TEST(HasUnqualifiedLoc
, BindsToConstVolatileIntVarDecl
) {
6311 EXPECT_TRUE(matches(
6312 "const volatile int x = 0;",
6313 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6314 hasUnqualifiedLoc(loc(asString("int"))))))));
6317 TEST(HasUnqualifiedLoc
, BindsToConstPointerVarDecl
) {
6318 auto matcher
= varDecl(
6320 hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))));
6321 EXPECT_TRUE(matches("int* const x = 0;", matcher
));
6322 EXPECT_TRUE(notMatches("int const x = 0;", matcher
));
6325 TEST(HasUnqualifiedLoc
, BindsToPointerToConstVolatileIntVarDecl
) {
6327 matches("const volatile int* x = 0;",
6328 varDecl(hasName("x"),
6329 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(
6330 hasUnqualifiedLoc(loc(asString("int"))))))))));
6333 TEST(HasUnqualifiedLoc
, BindsToConstIntFunctionDecl
) {
6335 matches("const int f() { return 5; }",
6336 functionDecl(hasName("f"),
6337 hasReturnTypeLoc(qualifiedTypeLoc(
6338 hasUnqualifiedLoc(loc(asString("int"))))))));
6341 TEST(HasUnqualifiedLoc
, FloatBindsToConstFloatVarDecl
) {
6342 EXPECT_TRUE(matches(
6343 "const float x = 0;",
6344 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6345 hasUnqualifiedLoc(loc(asString("float"))))))));
6348 TEST(HasUnqualifiedLoc
, FloatDoesNotBindToIntVarDecl
) {
6349 EXPECT_TRUE(notMatches(
6351 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6352 hasUnqualifiedLoc(loc(asString("float"))))))));
6355 TEST(HasUnqualifiedLoc
, FloatDoesNotBindToConstIntVarDecl
) {
6356 EXPECT_TRUE(notMatches(
6358 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6359 hasUnqualifiedLoc(loc(asString("float"))))))));
6362 TEST(HasReturnTypeLoc
, BindsToIntReturnTypeLoc
) {
6363 EXPECT_TRUE(matches(
6364 "int f() { return 5; }",
6365 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6368 TEST(HasReturnTypeLoc
, BindsToFloatReturnTypeLoc
) {
6369 EXPECT_TRUE(matches(
6370 "float f() { return 5.0; }",
6371 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6374 TEST(HasReturnTypeLoc
, BindsToVoidReturnTypeLoc
) {
6375 EXPECT_TRUE(matches(
6377 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));
6380 TEST(HasReturnTypeLoc
, FloatDoesNotBindToIntReturnTypeLoc
) {
6381 EXPECT_TRUE(notMatches(
6382 "int f() { return 5; }",
6383 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6386 TEST(HasReturnTypeLoc
, IntDoesNotBindToFloatReturnTypeLoc
) {
6387 EXPECT_TRUE(notMatches(
6388 "float f() { return 5.0; }",
6389 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6392 TEST(HasPointeeLoc
, BindsToAnyPointeeTypeLoc
) {
6393 auto matcher
= varDecl(hasName("x"),
6394 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6395 EXPECT_TRUE(matches("int* x;", matcher
));
6396 EXPECT_TRUE(matches("float* x;", matcher
));
6397 EXPECT_TRUE(matches("char* x;", matcher
));
6398 EXPECT_TRUE(matches("void* x;", matcher
));
6401 TEST(HasPointeeLoc
, DoesNotBindToTypeLocWithoutPointee
) {
6402 auto matcher
= varDecl(hasName("x"),
6403 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6404 EXPECT_TRUE(notMatches("int x;", matcher
));
6405 EXPECT_TRUE(notMatches("float x;", matcher
));
6406 EXPECT_TRUE(notMatches("char x;", matcher
));
6409 TEST(HasPointeeLoc
, BindsToTypeLocPointingToInt
) {
6411 matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6414 TEST(HasPointeeLoc
, BindsToTypeLocPointingToIntPointer
) {
6415 EXPECT_TRUE(matches("int** x;",
6416 pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));
6419 TEST(HasPointeeLoc
, BindsToTypeLocPointingToTypeLocPointingToInt
) {
6420 EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
6421 hasPointeeLoc(loc(asString("int"))))))));
6424 TEST(HasPointeeLoc
, BindsToTypeLocPointingToFloat
) {
6425 EXPECT_TRUE(matches("float* x;",
6426 pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6429 TEST(HasPointeeLoc
, IntPointeeDoesNotBindToTypeLocPointingToFloat
) {
6430 EXPECT_TRUE(notMatches("float* x;",
6431 pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6434 TEST(HasPointeeLoc
, FloatPointeeDoesNotBindToTypeLocPointingToInt
) {
6435 EXPECT_TRUE(notMatches(
6436 "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6439 TEST(HasReferentLoc
, BindsToAnyReferentTypeLoc
) {
6440 auto matcher
= varDecl(
6441 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6442 EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher
));
6443 EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher
));
6444 EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher
));
6445 EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher
));
6446 EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher
));
6449 TEST(HasReferentLoc
, DoesNotBindToTypeLocWithoutReferent
) {
6450 auto matcher
= varDecl(
6451 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6452 EXPECT_TRUE(notMatches("int r;", matcher
));
6453 EXPECT_TRUE(notMatches("int r = 3;", matcher
));
6454 EXPECT_TRUE(notMatches("const int r = 3;", matcher
));
6455 EXPECT_TRUE(notMatches("int* r;", matcher
));
6456 EXPECT_TRUE(notMatches("float r;", matcher
));
6457 EXPECT_TRUE(notMatches("char r;", matcher
));
6460 TEST(HasReferentLoc
, BindsToAnyRvalueReference
) {
6461 auto matcher
= varDecl(
6462 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6463 EXPECT_TRUE(matches("int&& r = 3;", matcher
));
6464 EXPECT_TRUE(matches("auto&& r = 3;", matcher
));
6465 EXPECT_TRUE(matches("float&& r = 3.0;", matcher
));
6468 TEST(HasReferentLoc
, BindsToIntReferenceTypeLoc
) {
6469 EXPECT_TRUE(matches("int rr = 3; int& r = rr;",
6470 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6473 TEST(HasReferentLoc
, BindsToIntRvalueReferenceTypeLoc
) {
6474 EXPECT_TRUE(matches("int&& r = 3;",
6475 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6478 TEST(HasReferentLoc
, BindsToFloatReferenceTypeLoc
) {
6480 matches("float rr = 3.0; float& r = rr;",
6481 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6484 TEST(HasReferentLoc
, BindsToParameterWithIntReferenceTypeLoc
) {
6485 EXPECT_TRUE(matches(
6486 "int f(int& r) { return r; }",
6487 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6488 hasReferentLoc(loc(asString("int"))))))));
6491 TEST(HasReferentLoc
, IntReferenceDoesNotBindToFloatReferenceTypeLoc
) {
6493 notMatches("float rr = 3.0; float& r = rr;",
6494 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6497 TEST(HasReferentLoc
, FloatReferenceDoesNotBindToIntReferenceTypeLoc
) {
6499 notMatches("int rr = 3; int& r = rr;",
6500 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6503 TEST(HasReferentLoc
, DoesNotBindToParameterWithoutIntReferenceTypeLoc
) {
6504 EXPECT_TRUE(notMatches(
6505 "int f(int r) { return r; }",
6506 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6507 hasReferentLoc(loc(asString("int"))))))));
6510 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithIntArgument
) {
6511 EXPECT_TRUE(matches(
6512 "template<typename T> class A {}; A<int> a;",
6513 varDecl(hasName("a"),
6514 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6515 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6516 hasTypeLoc(loc(asString("int")))))))))));
6519 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithDoubleArgument
) {
6520 EXPECT_TRUE(matches(
6521 "template<typename T> class A {}; A<double> a;",
6522 varDecl(hasName("a"),
6523 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6524 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6525 hasTypeLoc(loc(asString("double")))))))))));
6528 TEST(HasAnyTemplateArgumentLoc
, BindsToExplicitSpecializationWithIntArgument
) {
6529 EXPECT_TRUE(matches(
6530 "template<typename T> class A {}; template<> class A<int> {};",
6531 classTemplateSpecializationDecl(
6533 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
6536 TEST(HasAnyTemplateArgumentLoc
,
6537 BindsToExplicitSpecializationWithDoubleArgument
) {
6538 EXPECT_TRUE(matches(
6539 "template<typename T> class A {}; template<> class A<double> {};",
6540 classTemplateSpecializationDecl(
6542 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
6545 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithMultipleArguments
) {
6547 template<typename T, typename U> class A {};
6548 template<> class A<double, int> {};
6551 matches(code
, classTemplateSpecializationDecl(
6552 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
6553 loc(asString("double")))))));
6555 EXPECT_TRUE(matches(
6556 code
, classTemplateSpecializationDecl(
6558 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
6561 TEST(HasAnyTemplateArgumentLoc
, DoesNotBindToSpecializationWithIntArgument
) {
6562 EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",
6563 classTemplateSpecializationDecl(
6564 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
6565 loc(asString("double")))))));
6568 TEST(HasAnyTemplateArgumentLoc
,
6569 DoesNotBindToExplicitSpecializationWithIntArgument
) {
6570 EXPECT_TRUE(notMatches(
6571 "template<typename T> class A {}; template<> class A<int> {};",
6572 classTemplateSpecializationDecl(
6574 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
6577 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithIntArgument
) {
6579 matches("template<typename T> class A {}; A<int> a;",
6580 varDecl(hasName("a"),
6581 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6582 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6583 0, hasTypeLoc(loc(asString("int")))))))))));
6586 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithDoubleArgument
) {
6588 matches("template<typename T> class A {}; A<double> a;",
6589 varDecl(hasName("a"),
6590 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6591 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6592 0, hasTypeLoc(loc(asString("double")))))))))));
6595 TEST(HasTemplateArgumentLoc
, DoesNotBindToSpecializationWithIntArgument
) {
6596 EXPECT_TRUE(notMatches(
6597 "template<typename T> class A {}; A<int> a;",
6598 varDecl(hasName("a"),
6599 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6600 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6601 0, hasTypeLoc(loc(asString("double")))))))))));
6604 TEST(HasTemplateArgumentLoc
, BindsToExplicitSpecializationWithIntArgument
) {
6605 EXPECT_TRUE(matches(
6606 "template<typename T> class A {}; template<> class A<int> {};",
6607 classTemplateSpecializationDecl(
6609 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6612 TEST(HasTemplateArgumentLoc
, BindsToExplicitSpecializationWithDoubleArgument
) {
6613 EXPECT_TRUE(matches(
6614 "template<typename T> class A {}; template<> class A<double> {};",
6615 classTemplateSpecializationDecl(
6617 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6620 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithMultipleArguments
) {
6622 template<typename T, typename U> class A {};
6623 template<> class A<double, int> {};
6625 EXPECT_TRUE(matches(
6626 code
, classTemplateSpecializationDecl(
6627 hasName("A"), hasTemplateArgumentLoc(
6628 0, hasTypeLoc(loc(asString("double")))))));
6629 EXPECT_TRUE(matches(
6630 code
, classTemplateSpecializationDecl(
6632 hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));
6635 TEST(HasTemplateArgumentLoc
,
6636 DoesNotBindToExplicitSpecializationWithIntArgument
) {
6637 EXPECT_TRUE(notMatches(
6638 "template<typename T> class A {}; template<> class A<int> {};",
6639 classTemplateSpecializationDecl(
6641 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6644 TEST(HasTemplateArgumentLoc
,
6645 DoesNotBindToSpecializationWithMisplacedArguments
) {
6647 template<typename T, typename U> class A {};
6648 template<> class A<double, int> {};
6650 EXPECT_TRUE(notMatches(
6651 code
, classTemplateSpecializationDecl(
6652 hasName("A"), hasTemplateArgumentLoc(
6653 1, hasTypeLoc(loc(asString("double")))))));
6654 EXPECT_TRUE(notMatches(
6655 code
, classTemplateSpecializationDecl(
6657 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6660 TEST(HasTemplateArgumentLoc
, DoesNotBindWithBadIndex
) {
6662 template<typename T, typename U> class A {};
6663 template<> class A<double, int> {};
6665 EXPECT_TRUE(notMatches(
6666 code
, classTemplateSpecializationDecl(
6667 hasName("A"), hasTemplateArgumentLoc(
6668 -1, hasTypeLoc(loc(asString("double")))))));
6669 EXPECT_TRUE(notMatches(
6670 code
, classTemplateSpecializationDecl(
6671 hasName("A"), hasTemplateArgumentLoc(
6672 100, hasTypeLoc(loc(asString("int")))))));
6675 TEST(HasTemplateArgumentLoc
, BindsToDeclRefExprWithIntArgument
) {
6676 EXPECT_TRUE(matches(R
"(
6677 template<typename T> T f(T t) { return t; }
6678 int g() { int i = f<int>(3); return i; }
6680 declRefExpr(to(functionDecl(hasName("f"))),
6681 hasTemplateArgumentLoc(
6682 0, hasTypeLoc(loc(asString("int")))))));
6685 TEST(HasTemplateArgumentLoc
, BindsToDeclRefExprWithDoubleArgument
) {
6686 EXPECT_TRUE(matches(
6688 template<typename T> T f(T t) { return t; }
6689 double g() { double i = f<double>(3.0); return i; }
6692 to(functionDecl(hasName("f"))),
6693 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6696 TEST(HasTemplateArgumentLoc
, DoesNotBindToDeclRefExprWithDoubleArgument
) {
6697 EXPECT_TRUE(notMatches(
6699 template<typename T> T f(T t) { return t; }
6700 double g() { double i = f<double>(3.0); return i; }
6703 to(functionDecl(hasName("f"))),
6704 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6707 TEST(HasNamedTypeLoc
, BindsToElaboratedObjectDeclaration
) {
6708 EXPECT_TRUE(matches(
6710 template <typename T>
6714 varDecl(hasName("c"),
6715 hasTypeLoc(elaboratedTypeLoc(
6716 hasNamedTypeLoc(templateSpecializationTypeLoc(
6717 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6720 TEST(HasNamedTypeLoc
, DoesNotBindToNonElaboratedObjectDeclaration
) {
6721 EXPECT_TRUE(matches(
6723 template <typename T>
6727 varDecl(hasName("c"),
6728 hasTypeLoc(elaboratedTypeLoc(
6729 hasNamedTypeLoc(templateSpecializationTypeLoc(
6730 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6733 } // namespace ast_matchers
6734 } // namespace clang