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(HasDeclaration
, HasDeclarationOfObjCInterface
) {
287 EXPECT_TRUE(matchesObjC("@interface BaseClass @end void f() {BaseClass* b;}",
288 varDecl(hasType(objcObjectPointerType(
289 pointee(hasDeclaration(objcInterfaceDecl())))))));
292 TEST(HasUnqualifiedDesugaredType
, DesugarsUsing
) {
294 matches("struct A {}; using B = A; B b;",
295 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
297 matches("struct A {}; using B = A; using C = B; C b;",
298 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
301 TEST(HasUnderlyingDecl
, Matches
) {
302 EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }"
303 "template <class T> void g() { using N::f; f(T()); }",
304 unresolvedLookupExpr(hasAnyDeclaration(
305 namedDecl(hasUnderlyingDecl(hasName("::N::f")))))));
307 "namespace N { template <class T> void f(T t); }"
308 "template <class T> void g() { N::f(T()); }",
309 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
310 EXPECT_TRUE(notMatches(
311 "namespace N { template <class T> void f(T t); }"
312 "template <class T> void g() { using N::f; f(T()); }",
313 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
316 TEST(HasType
, TakesQualTypeMatcherAndMatchesExpr
) {
317 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
319 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX
))));
321 notMatches("class X {}; void y(X *x) { x; }",
322 expr(hasType(ClassX
))));
324 matches("class X {}; void y(X *x) { x; }",
325 expr(hasType(pointsTo(ClassX
)))));
328 TEST(HasType
, TakesQualTypeMatcherAndMatchesValueDecl
) {
329 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
331 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX
))));
333 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX
))));
335 matches("class X {}; void y() { X *x; }",
336 varDecl(hasType(pointsTo(ClassX
)))));
339 TEST(HasType
, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier
) {
340 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
341 CXXBaseSpecifierMatcher BaseClassX
= cxxBaseSpecifier(hasType(ClassX
));
342 DeclarationMatcher ClassHasBaseClassX
=
343 cxxRecordDecl(hasDirectBase(BaseClassX
));
344 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX
));
345 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX
));
348 TEST(HasType
, TakesDeclMatcherAndMatchesExpr
) {
349 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
351 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX
))));
353 notMatches("class X {}; void y(X *x) { x; }",
354 expr(hasType(ClassX
))));
357 TEST(HasType
, TakesDeclMatcherAndMatchesValueDecl
) {
358 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
360 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX
))));
362 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX
))));
365 TEST(HasType
, TakesDeclMatcherAndMatchesCXXBaseSpecifier
) {
366 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
367 CXXBaseSpecifierMatcher BaseClassX
= cxxBaseSpecifier(hasType(ClassX
));
368 DeclarationMatcher ClassHasBaseClassX
=
369 cxxRecordDecl(hasDirectBase(BaseClassX
));
370 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX
));
371 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX
));
374 TEST(HasType
, MatchesTypedefDecl
) {
375 EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));
376 EXPECT_TRUE(matches("typedef const int T;",
377 typedefDecl(hasType(asString("const int")))));
378 EXPECT_TRUE(notMatches("typedef const int T;",
379 typedefDecl(hasType(asString("int")))));
380 EXPECT_TRUE(matches("typedef int foo; typedef foo bar;",
381 typedefDecl(hasType(asString("foo")), hasName("bar"))));
384 TEST(HasType
, MatchesTypedefNameDecl
) {
385 EXPECT_TRUE(matches("using X = int;", typedefNameDecl(hasType(asString("int")))));
386 EXPECT_TRUE(matches("using T = const int;",
387 typedefNameDecl(hasType(asString("const int")))));
388 EXPECT_TRUE(notMatches("using T = const int;",
389 typedefNameDecl(hasType(asString("int")))));
390 EXPECT_TRUE(matches("using foo = int; using bar = foo;",
391 typedefNameDecl(hasType(asString("foo")), hasName("bar"))));
394 TEST(HasTypeLoc
, MatchesBlockDecl
) {
395 EXPECT_TRUE(matchesConditionally(
396 "auto x = ^int (int a, int b) { return a + b; };",
397 blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true,
401 TEST(HasTypeLoc
, MatchesCXXBaseSpecifierAndCtorInitializer
) {
402 llvm::StringRef code
= R
"cpp(
404 class Bar : public Foo {
410 code
, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("Foo")))))));
412 matches(code
, cxxCtorInitializer(hasTypeLoc(loc(asString("Foo"))))));
415 TEST(HasTypeLoc
, MatchesCXXFunctionalCastExpr
) {
416 EXPECT_TRUE(matches("auto x = int(3);",
417 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int"))))));
420 TEST(HasTypeLoc
, MatchesCXXNewExpr
) {
421 EXPECT_TRUE(matches("auto* x = new int(3);",
422 cxxNewExpr(hasTypeLoc(loc(asString("int"))))));
423 EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();",
424 cxxNewExpr(hasTypeLoc(loc(asString("Foo"))))));
427 TEST(HasTypeLoc
, MatchesCXXTemporaryObjectExpr
) {
429 matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",
430 cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("Foo"))))));
433 TEST(HasTypeLoc
, MatchesCXXUnresolvedConstructExpr
) {
435 matches("template <typename T> T make() { return T(); }",
436 cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));
439 TEST(HasTypeLoc
, MatchesCompoundLiteralExpr
) {
441 matches("int* x = (int[2]) { 0, 1 };",
442 compoundLiteralExpr(hasTypeLoc(loc(asString("int[2]"))))));
445 TEST(HasTypeLoc
, MatchesDeclaratorDecl
) {
446 EXPECT_TRUE(matches("int x;",
447 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
448 EXPECT_TRUE(matches("int x(3);",
449 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
450 EXPECT_TRUE(matches("struct Foo { Foo(int, int); }; Foo x(1, 2);",
451 varDecl(hasName("x"), hasTypeLoc(loc(asString("Foo"))))));
453 // Make sure we don't crash on implicit constructors.
454 EXPECT_TRUE(notMatches("class X {}; X x;",
455 declaratorDecl(hasTypeLoc(loc(asString("int"))))));
458 TEST(HasTypeLoc
, MatchesExplicitCastExpr
) {
459 EXPECT_TRUE(matches("auto x = (int) 3;",
460 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
461 EXPECT_TRUE(matches("auto x = static_cast<int>(3);",
462 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
465 TEST(HasTypeLoc
, MatchesObjCPropertyDecl
) {
466 EXPECT_TRUE(matchesObjC(R
"objc(
468 @property int enabled;
471 objcPropertyDecl(hasTypeLoc(loc(asString("int"))))));
474 TEST(HasTypeLoc
, MatchesTemplateArgumentLoc
) {
475 EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;",
476 templateArgumentLoc(hasTypeLoc(loc(asString("int"))))));
479 TEST(HasTypeLoc
, MatchesTypedefNameDecl
) {
480 EXPECT_TRUE(matches("typedef int X;",
481 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
482 EXPECT_TRUE(matches("using X = int;",
483 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
486 TEST(Callee
, MatchesDeclarations
) {
487 StatementMatcher CallMethodX
= callExpr(callee(cxxMethodDecl(hasName("x"))));
489 EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX
));
490 EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX
));
492 CallMethodX
= traverse(TK_AsIs
, callExpr(callee(cxxConversionDecl())));
494 matches("struct Y { operator int() const; }; int i = Y();", CallMethodX
));
495 EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",
499 TEST(Callee
, MatchesMemberExpressions
) {
500 EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
501 callExpr(callee(memberExpr()))));
503 notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));
506 TEST(Matcher
, Argument
) {
507 StatementMatcher CallArgumentY
= callExpr(
508 hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
510 EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY
));
512 matches("class X { void x(int) { int y; x(y); } };", CallArgumentY
));
513 EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY
));
515 StatementMatcher WrongIndex
= callExpr(
516 hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
517 EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex
));
520 TEST(Matcher
, AnyArgument
) {
521 auto HasArgumentY
= hasAnyArgument(
522 ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
523 StatementMatcher CallArgumentY
= callExpr(HasArgumentY
);
524 StatementMatcher CtorArgumentY
= cxxConstructExpr(HasArgumentY
);
525 StatementMatcher UnresolvedCtorArgumentY
=
526 cxxUnresolvedConstructExpr(HasArgumentY
);
527 StatementMatcher ObjCCallArgumentY
= objcMessageExpr(HasArgumentY
);
528 EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY
));
529 EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY
));
530 EXPECT_TRUE(matches("struct Y { Y(int, int); };"
531 "void x() { int y; (void)Y(1, y); }",
533 EXPECT_TRUE(matches("struct Y { Y(int, int); };"
534 "void x() { int y; (void)Y(y, 42); }",
536 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",
537 UnresolvedCtorArgumentY
));
538 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",
539 UnresolvedCtorArgumentY
));
540 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
541 "void x(I* i) { int y; [i f:y]; }",
543 EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "
544 "void x(I* i) { int z; [i f:z]; }",
546 EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY
));
547 EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"
548 "void x() { int y; (void)Y(1, 2); }",
550 EXPECT_TRUE(notMatches("template <class Y>"
551 "void x() { int y; (void)Y(1, 2); }",
552 UnresolvedCtorArgumentY
));
554 StatementMatcher ImplicitCastedArgument
=
555 traverse(TK_AsIs
, callExpr(hasAnyArgument(implicitCastExpr())));
556 EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument
));
559 TEST(Matcher
, HasReceiver
) {
560 EXPECT_TRUE(matchesObjC(
561 "@interface NSString @end "
562 "void f(NSString *x) {"
563 "[x containsString];"
565 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
567 EXPECT_FALSE(matchesObjC(
568 "@interface NSString +(NSString *) stringWithFormat; @end "
569 "void f() { [NSString stringWithFormat]; }",
570 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
573 TEST(Matcher
, MatchesMethodsOnLambda
) {
574 StringRef Code
= R
"cpp(
583 auto lPtrDecay = +[] { };
589 Code
, cxxConstructorDecl(
590 hasBody(compoundStmt()),
591 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),
592 isCopyConstructor())));
594 Code
, cxxConstructorDecl(
595 hasBody(compoundStmt()),
596 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),
597 isMoveConstructor())));
599 Code
, cxxDestructorDecl(
600 hasBody(compoundStmt()),
601 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))))));
603 Code
, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt(
604 hasReturnValue(implicitCastExpr()))))),
605 hasAncestor(lambdaExpr(hasAncestor(
606 varDecl(hasName("lPtrDecay"))))))));
609 TEST(Matcher
, MatchesCoroutine
) {
610 FileContentMappings M
;
611 M
.push_back(std::make_pair("/coro_header", R
"cpp(
614 template <class... Args>
618 template <class... Args>
619 using void_t = typename void_t_imp<Args...>::type;
621 template <class T, class = void>
622 struct traits_sfinae_base {};
625 struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
626 using promise_type = typename T::promise_type;
629 template <class Ret, class... Args>
630 struct coroutine_traits : public traits_sfinae_base<Ret> {};
633 bool await_ready() noexcept;
634 template <typename F>
635 void await_suspend(F) noexcept;
636 void await_resume() noexcept;
639 void get_return_object();
640 awaitable initial_suspend();
641 awaitable final_suspend() noexcept;
642 awaitable yield_value(int); // expected-note 2{{candidate}}
643 void return_value(int); // expected-note 2{{here}}
644 void unhandled_exception();
646 template <typename... T>
647 struct std::coroutine_traits<void, T...> { using promise_type = promise; };
649 template <class PromiseType = void>
650 struct coroutine_handle {
651 static coroutine_handle from_address(void *) noexcept;
655 StringRef CoReturnCode
= R
"cpp(
656 #include <coro_header>
657 void check_match_co_return() {
661 EXPECT_TRUE(matchesConditionally(CoReturnCode
,
662 coreturnStmt(isExpansionInMainFile()), true,
663 {"-std=c++20", "-I/"}, M
));
664 StringRef CoAwaitCode
= R
"cpp(
665 #include <coro_header>
666 void check_match_co_await() {
670 EXPECT_TRUE(matchesConditionally(CoAwaitCode
,
671 coawaitExpr(isExpansionInMainFile()), true,
672 {"-std=c++20", "-I/"}, M
));
673 StringRef CoYieldCode
= R
"cpp(
674 #include <coro_header>
675 void check_match_co_yield() {
679 EXPECT_TRUE(matchesConditionally(CoYieldCode
,
680 coyieldExpr(isExpansionInMainFile()), true,
681 {"-std=c++20", "-I/"}, M
));
683 StringRef NonCoroCode
= R
"cpp(
684 #include <coro_header>
685 void non_coro_function() {
689 EXPECT_TRUE(matchesConditionally(CoReturnCode
, coroutineBodyStmt(), true,
690 {"-std=c++20", "-I/"}, M
));
691 EXPECT_TRUE(matchesConditionally(CoAwaitCode
, coroutineBodyStmt(), true,
692 {"-std=c++20", "-I/"}, M
));
693 EXPECT_TRUE(matchesConditionally(CoYieldCode
, coroutineBodyStmt(), true,
694 {"-std=c++20", "-I/"}, M
));
696 EXPECT_FALSE(matchesConditionally(NonCoroCode
, coroutineBodyStmt(), true,
697 {"-std=c++20", "-I/"}, M
));
699 StringRef CoroWithDeclCode
= R
"cpp(
700 #include <coro_header>
706 EXPECT_TRUE(matchesConditionally(
708 coroutineBodyStmt(hasBody(compoundStmt(
709 has(declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))),
710 true, {"-std=c++20", "-I/"}, M
));
712 StringRef CoroWithTryCatchDeclCode
= R
"cpp(
713 #include <coro_header>
719 EXPECT_TRUE(matchesConditionally(
720 CoroWithTryCatchDeclCode
,
721 coroutineBodyStmt(hasBody(compoundStmt(has(cxxTryStmt(has(compoundStmt(has(
722 declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))))),
723 true, {"-std=c++20", "-I/"}, M
));
726 TEST(Matcher
, isClassMessage
) {
727 EXPECT_TRUE(matchesObjC(
728 "@interface NSString +(NSString *) stringWithFormat; @end "
729 "void f() { [NSString stringWithFormat]; }",
730 objcMessageExpr(isClassMessage())));
732 EXPECT_FALSE(matchesObjC(
733 "@interface NSString @end "
734 "void f(NSString *x) {"
735 "[x containsString];"
737 objcMessageExpr(isClassMessage())));
740 TEST(Matcher
, isInstanceMessage
) {
741 EXPECT_TRUE(matchesObjC(
742 "@interface NSString @end "
743 "void f(NSString *x) {"
744 "[x containsString];"
746 objcMessageExpr(isInstanceMessage())));
748 EXPECT_FALSE(matchesObjC(
749 "@interface NSString +(NSString *) stringWithFormat; @end "
750 "void f() { [NSString stringWithFormat]; }",
751 objcMessageExpr(isInstanceMessage())));
755 TEST(Matcher
, isClassMethod
) {
756 EXPECT_TRUE(matchesObjC(
757 "@interface Bar + (void)bar; @end",
758 objcMethodDecl(isClassMethod())));
760 EXPECT_TRUE(matchesObjC(
761 "@interface Bar @end"
762 "@implementation Bar + (void)bar {} @end",
763 objcMethodDecl(isClassMethod())));
765 EXPECT_FALSE(matchesObjC(
766 "@interface Foo - (void)foo; @end",
767 objcMethodDecl(isClassMethod())));
769 EXPECT_FALSE(matchesObjC(
770 "@interface Foo @end "
771 "@implementation Foo - (void)foo {} @end",
772 objcMethodDecl(isClassMethod())));
775 TEST(Matcher
, isInstanceMethod
) {
776 EXPECT_TRUE(matchesObjC(
777 "@interface Foo - (void)foo; @end",
778 objcMethodDecl(isInstanceMethod())));
780 EXPECT_TRUE(matchesObjC(
781 "@interface Foo @end "
782 "@implementation Foo - (void)foo {} @end",
783 objcMethodDecl(isInstanceMethod())));
785 EXPECT_FALSE(matchesObjC(
786 "@interface Bar + (void)bar; @end",
787 objcMethodDecl(isInstanceMethod())));
789 EXPECT_FALSE(matchesObjC(
790 "@interface Bar @end"
791 "@implementation Bar + (void)bar {} @end",
792 objcMethodDecl(isInstanceMethod())));
795 TEST(MatcherCXXMemberCallExpr
, On
) {
796 StringRef Snippet1
= R
"cc(
800 void z(Y y) { y.m(); }
802 StringRef Snippet2
= R
"cc(
806 struct X : public Y {};
807 void z(X x) { x.m(); }
809 auto MatchesY
= cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))));
810 EXPECT_TRUE(matches(Snippet1
, MatchesY
));
811 EXPECT_TRUE(notMatches(Snippet2
, MatchesY
));
813 auto MatchesX
= cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))));
814 EXPECT_TRUE(matches(Snippet2
, MatchesX
));
816 // Parens are ignored.
817 StringRef Snippet3
= R
"cc(
822 void z(Y y) { (g()).m(); }
824 auto MatchesCall
= cxxMemberCallExpr(on(callExpr()));
825 EXPECT_TRUE(matches(Snippet3
, MatchesCall
));
828 TEST(MatcherCXXMemberCallExpr
, OnImplicitObjectArgument
) {
829 StringRef Snippet1
= R
"cc(
833 void z(Y y) { y.m(); }
835 StringRef Snippet2
= R
"cc(
839 struct X : public Y {};
840 void z(X x) { x.m(); }
842 auto MatchesY
= traverse(TK_AsIs
, cxxMemberCallExpr(onImplicitObjectArgument(
843 hasType(cxxRecordDecl(hasName("Y"))))));
844 EXPECT_TRUE(matches(Snippet1
, MatchesY
));
845 EXPECT_TRUE(matches(Snippet2
, MatchesY
));
847 auto MatchesX
= traverse(TK_AsIs
, cxxMemberCallExpr(onImplicitObjectArgument(
848 hasType(cxxRecordDecl(hasName("X"))))));
849 EXPECT_TRUE(notMatches(Snippet2
, MatchesX
));
851 // Parens are not ignored.
852 StringRef Snippet3
= R
"cc(
857 void z(Y y) { (g()).m(); }
859 auto MatchesCall
= traverse(
860 TK_AsIs
, cxxMemberCallExpr(onImplicitObjectArgument(callExpr())));
861 EXPECT_TRUE(notMatches(Snippet3
, MatchesCall
));
864 TEST(Matcher
, HasObjectExpr
) {
865 StringRef Snippet1
= R
"cc(
868 int f(X x) { return x.m; }
871 StringRef Snippet2
= R
"cc(
874 int f(X x) { return m; }
878 memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))));
879 EXPECT_TRUE(matches(Snippet1
, MatchesX
));
880 EXPECT_TRUE(notMatches(Snippet2
, MatchesX
));
882 auto MatchesXPointer
= memberExpr(
883 hasObjectExpression(hasType(pointsTo(cxxRecordDecl(hasName("X"))))));
884 EXPECT_TRUE(notMatches(Snippet1
, MatchesXPointer
));
885 EXPECT_TRUE(matches(Snippet2
, MatchesXPointer
));
888 TEST(ForEachArgumentWithParam
, ReportsNoFalsePositives
) {
889 StatementMatcher ArgumentY
=
890 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
891 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
892 StatementMatcher CallExpr
=
893 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
895 // IntParam does not match.
896 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr
));
897 // ArgumentY does not match.
898 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr
));
901 TEST(ForEachArgumentWithParam
, MatchesCXXMemberCallExpr
) {
902 StatementMatcher ArgumentY
=
903 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
904 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
905 StatementMatcher CallExpr
=
906 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
907 EXPECT_TRUE(matchAndVerifyResultTrue(
909 " const S& operator[](int i) { return *this; }"
915 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", 1)));
917 StatementMatcher CallExpr2
=
918 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
919 EXPECT_TRUE(matchAndVerifyResultTrue(
921 " static void g(int i);"
927 CallExpr2
, std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", 1)));
930 TEST(ForEachArgumentWithParam
, MatchesCallExpr
) {
931 StatementMatcher ArgumentY
=
932 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
933 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
934 StatementMatcher CallExpr
=
935 callExpr(forEachArgumentWithParam(ArgumentY
, IntParam
));
938 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr
,
939 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>(
942 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr
,
943 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>(
946 EXPECT_TRUE(matchAndVerifyResultTrue(
947 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
948 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", 2)));
949 EXPECT_TRUE(matchAndVerifyResultTrue(
950 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
951 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg", 2)));
954 TEST(ForEachArgumentWithParam
, MatchesConstructExpr
) {
955 StatementMatcher ArgumentY
=
956 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
957 DeclarationMatcher IntParam
= parmVarDecl(hasType(isInteger())).bind("param");
958 StatementMatcher ConstructExpr
= traverse(
959 TK_AsIs
, cxxConstructExpr(forEachArgumentWithParam(ArgumentY
, IntParam
)));
961 EXPECT_TRUE(matchAndVerifyResultTrue(
968 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param")));
971 TEST(ForEachArgumentWithParam
, HandlesBoundNodesForNonMatches
) {
972 EXPECT_TRUE(matchAndVerifyResultTrue(
973 "void g(int i, int j) {"
982 forEachDescendant(varDecl().bind("v")),
983 forEachDescendant(callExpr(forEachArgumentWithParam(
984 declRefExpr(to(decl(equalsBoundNode("v")))), parmVarDecl())))),
985 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("v", 4)));
988 TEST_P(ASTMatchersTest
,
989 ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls
) {
990 if (!GetParam().isCXX23OrLater()) {
994 auto DeclRef
= declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");
995 auto SelfParam
= parmVarDecl().bind("param");
996 StatementMatcher CallExpr
=
997 callExpr(forEachArgumentWithParam(DeclRef
, SelfParam
));
1001 int operator()(this const A &self);
1007 auto Args
= GetParam().getCommandLineArgs();
1008 auto Filename
= getFilenameForTesting(GetParam().Language
);
1010 EXPECT_TRUE(matchAndVerifyResultTrue(
1012 std::make_unique
<VerifyIdIsBoundTo
<ParmVarDecl
>>("param", "self"), Args
,
1014 EXPECT_TRUE(matchAndVerifyResultTrue(
1016 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("declOfArg", "obj"), Args
,
1020 TEST(ForEachArgumentWithParamType
, ReportsNoFalsePositives
) {
1021 StatementMatcher ArgumentY
=
1022 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1023 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1024 StatementMatcher CallExpr
=
1025 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1027 // IntParam does not match.
1028 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr
));
1029 // ArgumentY does not match.
1030 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr
));
1033 TEST(ForEachArgumentWithParamType
, MatchesCXXMemberCallExpr
) {
1034 StatementMatcher ArgumentY
=
1035 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1036 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1037 StatementMatcher CallExpr
=
1038 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1039 EXPECT_TRUE(matchAndVerifyResultTrue(
1041 " const S& operator[](int i) { return *this; }"
1047 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 1)));
1049 StatementMatcher CallExpr2
=
1050 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1051 EXPECT_TRUE(matchAndVerifyResultTrue(
1053 " static void g(int i);"
1059 CallExpr2
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 1)));
1062 TEST(ForEachArgumentWithParamType
, MatchesCallExpr
) {
1063 StatementMatcher ArgumentY
=
1064 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1065 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1066 StatementMatcher CallExpr
=
1067 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1069 EXPECT_TRUE(matchAndVerifyResultTrue(
1070 "void f(int i) { int y; f(y); }", CallExpr
,
1071 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1072 EXPECT_TRUE(matchAndVerifyResultTrue(
1073 "void f(int i) { int y; f(y); }", CallExpr
,
1074 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1076 EXPECT_TRUE(matchAndVerifyResultTrue(
1077 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
1078 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 2)));
1079 EXPECT_TRUE(matchAndVerifyResultTrue(
1080 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
1081 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg", 2)));
1084 TEST(ForEachArgumentWithParamType
, MatchesConstructExpr
) {
1085 StatementMatcher ArgumentY
=
1086 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1087 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1088 StatementMatcher ConstructExpr
=
1089 cxxConstructExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1091 EXPECT_TRUE(matchAndVerifyResultTrue(
1097 ConstructExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1098 EXPECT_TRUE(matchAndVerifyResultTrue(
1104 ConstructExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1107 TEST(ForEachArgumentWithParamType
, HandlesKandRFunctions
) {
1108 StatementMatcher ArgumentY
=
1109 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1110 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1111 StatementMatcher CallExpr
=
1112 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1114 EXPECT_TRUE(matchesC("void f();\n"
1115 "void call_it(void) { int x, y; f(x, y); }\n"
1116 "void f(a, b) int a, b; {}\n"
1117 "void call_it2(void) { int x, y; f(x, y); }",
1121 TEST(ForEachArgumentWithParamType
, HandlesBoundNodesForNonMatches
) {
1122 EXPECT_TRUE(matchAndVerifyResultTrue(
1123 "void g(int i, int j) {"
1132 forEachDescendant(varDecl().bind("v")),
1133 forEachDescendant(callExpr(forEachArgumentWithParamType(
1134 declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),
1135 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("v", 4)));
1138 TEST(ForEachArgumentWithParamType
, MatchesFunctionPtrCalls
) {
1139 StatementMatcher ArgumentY
=
1140 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1141 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1142 StatementMatcher CallExpr
=
1143 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1145 EXPECT_TRUE(matchAndVerifyResultTrue(
1147 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1148 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1149 EXPECT_TRUE(matchAndVerifyResultTrue(
1151 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1152 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1155 TEST(ForEachArgumentWithParamType
, MatchesMemberFunctionPtrCalls
) {
1156 StatementMatcher ArgumentY
=
1157 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1158 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1159 StatementMatcher CallExpr
=
1160 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1162 StringRef S
= "struct A {\n"
1163 " int f(int i) { return i + 1; }\n"
1164 " int (A::*x)(int);\n"
1172 EXPECT_TRUE(matchAndVerifyResultTrue(
1173 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1174 EXPECT_TRUE(matchAndVerifyResultTrue(
1175 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1178 TEST(ForEachArgumentWithParamType
, MatchesVariadicFunctionPtrCalls
) {
1179 StatementMatcher ArgumentY
=
1180 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1181 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1182 StatementMatcher CallExpr
=
1183 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1185 StringRef S
= R
"cpp(
1186 void fcntl(int fd, int cmd, ...) {}
1188 template <typename Func>
1194 void g() { f(fcntl); }
1197 EXPECT_TRUE(matchAndVerifyResultTrue(
1198 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1199 EXPECT_TRUE(matchAndVerifyResultTrue(
1200 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1203 TEST_P(ASTMatchersTest
,
1204 ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls
) {
1205 if (!GetParam().isCXX23OrLater()) {
1209 auto DeclRef
= declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");
1210 auto SelfTy
= qualType(asString("const A &")).bind("selfType");
1211 StatementMatcher CallExpr
=
1212 callExpr(forEachArgumentWithParamType(DeclRef
, SelfTy
));
1214 StringRef S
= R
"cpp(
1216 int operator()(this const A &self);
1222 auto Args
= GetParam().getCommandLineArgs();
1223 auto Filename
= getFilenameForTesting(GetParam().Language
);
1225 EXPECT_TRUE(matchAndVerifyResultTrue(
1226 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("selfType"),
1228 EXPECT_TRUE(matchAndVerifyResultTrue(
1230 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("declOfArg", "obj"), Args
,
1234 TEST(QualType
, hasCanonicalType
) {
1235 EXPECT_TRUE(notMatches("typedef int &int_ref;"
1238 varDecl(hasType(qualType(referenceType())))));
1240 matches("typedef int &int_ref;"
1243 varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));
1246 TEST(HasParameter
, CallsInnerMatcher
) {
1247 EXPECT_TRUE(matches("class X { void x(int) {} };",
1248 cxxMethodDecl(hasParameter(0, varDecl()))));
1249 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1250 cxxMethodDecl(hasParameter(0, hasName("x")))));
1251 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1252 objcMethodDecl(hasParameter(0, hasName("x")))));
1253 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1254 blockDecl(hasParameter(0, hasName("p")))));
1257 TEST(HasParameter
, DoesNotMatchIfIndexOutOfBounds
) {
1258 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1259 cxxMethodDecl(hasParameter(42, varDecl()))));
1262 TEST(HasType
, MatchesParameterVariableTypesStrictly
) {
1263 EXPECT_TRUE(matches(
1264 "class X { void x(X x) {} };",
1265 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1266 EXPECT_TRUE(notMatches(
1267 "class X { void x(const X &x) {} };",
1268 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1269 EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
1270 cxxMethodDecl(hasParameter(
1271 0, hasType(pointsTo(recordDecl(hasName("X"))))))));
1272 EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
1273 cxxMethodDecl(hasParameter(
1274 0, hasType(references(recordDecl(hasName("X"))))))));
1277 TEST(HasAnyParameter
, MatchesIndependentlyOfPosition
) {
1278 EXPECT_TRUE(matches(
1279 "class Y {}; class X { void x(X x, Y y) {} };",
1280 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1281 EXPECT_TRUE(matches(
1282 "class Y {}; class X { void x(Y y, X x) {} };",
1283 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1284 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1285 objcMethodDecl(hasAnyParameter(hasName("x")))));
1286 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1287 blockDecl(hasAnyParameter(hasName("p")))));
1290 TEST(Returns
, MatchesReturnTypes
) {
1291 EXPECT_TRUE(matches("class Y { int f() { return 1; } };",
1292 functionDecl(returns(asString("int")))));
1293 EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",
1294 functionDecl(returns(asString("float")))));
1295 EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",
1296 functionDecl(returns(hasDeclaration(
1297 recordDecl(hasName("Y")))))));
1300 TEST(HasAnyParameter
, DoesntMatchIfInnerMatcherDoesntMatch
) {
1301 EXPECT_TRUE(notMatches(
1302 "class Y {}; class X { void x(int) {} };",
1303 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1306 TEST(HasAnyParameter
, DoesNotMatchThisPointer
) {
1307 EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
1308 cxxMethodDecl(hasAnyParameter(
1309 hasType(pointsTo(recordDecl(hasName("X"))))))));
1312 TEST(HasName
, MatchesParameterVariableDeclarations
) {
1313 EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
1314 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1315 EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
1316 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1319 TEST(Matcher
, MatchesTypeTemplateArgument
) {
1320 EXPECT_TRUE(matches(
1321 "template<typename T> struct B {};"
1323 classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
1324 asString("int"))))));
1327 TEST(Matcher
, MatchesTemplateTemplateArgument
) {
1328 EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
1329 "template<typename T> class Y {};"
1331 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1332 refersToTemplate(templateName())))));
1335 TEST(Matcher
, MatchesDeclarationReferenceTemplateArgument
) {
1336 EXPECT_TRUE(matches(
1337 "struct B { int next; };"
1338 "template<int(B::*next_ptr)> struct A {};"
1340 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1341 refersToDeclaration(fieldDecl(hasName("next")))))));
1343 EXPECT_TRUE(notMatches(
1344 "template <typename T> struct A {};"
1346 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1347 refersToDeclaration(decl())))));
1349 EXPECT_TRUE(matches(
1350 "struct B { int next; };"
1351 "template<int(B::*next_ptr)> struct A {};"
1353 templateSpecializationType(hasAnyTemplateArgument(isExpr(
1354 hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));
1356 EXPECT_TRUE(notMatches(
1357 "template <typename T> struct A {};"
1359 templateSpecializationType(hasAnyTemplateArgument(
1360 refersToDeclaration(decl())))));
1364 TEST(Matcher
, MatchesSpecificArgument
) {
1365 EXPECT_TRUE(matches(
1366 "template<typename T, typename U> class A {};"
1368 classTemplateSpecializationDecl(hasTemplateArgument(
1369 1, refersToType(asString("int"))))));
1370 EXPECT_TRUE(notMatches(
1371 "template<typename T, typename U> class A {};"
1373 classTemplateSpecializationDecl(hasTemplateArgument(
1374 1, refersToType(asString("int"))))));
1376 EXPECT_TRUE(matches(
1377 "template<typename T, typename U> class A {};"
1379 templateSpecializationType(hasTemplateArgument(
1380 1, refersToType(asString("int"))))));
1381 EXPECT_TRUE(notMatches(
1382 "template<typename T, typename U> class A {};"
1384 templateSpecializationType(hasTemplateArgument(
1385 1, refersToType(asString("int"))))));
1387 EXPECT_TRUE(matches(
1388 "template<typename T> void f() {};"
1389 "void func() { f<int>(); }",
1390 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1391 EXPECT_TRUE(notMatches(
1392 "template<typename T> void f() {};",
1393 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1396 TEST(TemplateArgument
, Matches
) {
1397 EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
1398 classTemplateSpecializationDecl(
1399 hasAnyTemplateArgument(templateArgument()))));
1400 EXPECT_TRUE(matches(
1401 "template<typename T> struct C {}; C<int> c;",
1402 templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
1404 EXPECT_TRUE(matches(
1405 "template<typename T> void f() {};"
1406 "void func() { f<int>(); }",
1407 functionDecl(hasAnyTemplateArgument(templateArgument()))));
1410 TEST(TemplateTypeParmDecl
, CXXMethodDecl
) {
1411 const char input
[] =
1412 "template<typename T>\n"
1416 "template<typename U>\n"
1417 "void Class<U>::method() {}\n";
1418 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1419 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1422 TEST(TemplateTypeParmDecl
, VarDecl
) {
1423 const char input
[] =
1424 "template<typename T>\n"
1428 "template<typename U>\n"
1429 "U Class<U>::pi = U(3.1415926535897932385);\n";
1430 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1431 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1434 TEST(TemplateTypeParmDecl
, VarTemplatePartialSpecializationDecl
) {
1435 const char input
[] =
1436 "template<typename T>\n"
1438 " template<typename T2> static int field;\n"
1440 "template<typename U>\n"
1441 "template<typename U2>\n"
1442 "int Struct<U>::field<U2*> = 123;\n";
1444 matches(input
, templateTypeParmDecl(hasName("T")), langCxx14OrLater()));
1446 matches(input
, templateTypeParmDecl(hasName("T2")), langCxx14OrLater()));
1448 matches(input
, templateTypeParmDecl(hasName("U")), langCxx14OrLater()));
1450 matches(input
, templateTypeParmDecl(hasName("U2")), langCxx14OrLater()));
1453 TEST(TemplateTypeParmDecl
, ClassTemplatePartialSpecializationDecl
) {
1454 const char input
[] =
1455 "template<typename T>\n"
1457 " template<typename T2> struct Struct;\n"
1459 "template<typename U>\n"
1460 "template<typename U2>\n"
1461 "struct Class<U>::Struct<U2*> {};\n";
1462 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1463 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T2"))));
1464 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1465 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U2"))));
1468 TEST(TemplateTypeParmDecl
, EnumDecl
) {
1469 const char input
[] =
1470 "template<typename T>\n"
1472 " enum class Enum : T;\n"
1474 "template<typename U>\n"
1475 "enum class Struct<U>::Enum : U {\n"
1479 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1480 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1483 TEST(TemplateTypeParmDecl
, RecordDecl
) {
1484 const char input
[] =
1485 "template<typename T>\n"
1489 "template<typename U>\n"
1490 "struct Class<U>::Struct {\n"
1493 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1494 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1497 TEST(RefersToIntegralType
, Matches
) {
1498 EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1499 classTemplateSpecializationDecl(
1500 hasAnyTemplateArgument(refersToIntegralType(
1501 asString("int"))))));
1502 EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",
1503 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1504 refersToIntegralType(asString("int"))))));
1507 TEST(ConstructorDeclaration
, SimpleCase
) {
1508 EXPECT_TRUE(matches("class Foo { Foo(int i); };",
1509 cxxConstructorDecl(ofClass(hasName("Foo")))));
1510 EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
1511 cxxConstructorDecl(ofClass(hasName("Bar")))));
1514 TEST(DestructorDeclaration
, MatchesVirtualDestructor
) {
1515 EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
1516 cxxDestructorDecl(ofClass(hasName("Foo")))));
1519 TEST(DestructorDeclaration
, DoesNotMatchImplicitDestructor
) {
1520 EXPECT_TRUE(notMatches("class Foo {};",
1521 cxxDestructorDecl(ofClass(hasName("Foo")))));
1524 TEST(HasAnyConstructorInitializer
, SimpleCase
) {
1526 notMatches("class Foo { Foo() { } };",
1527 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1529 matches("class Foo {"
1530 " Foo() : foo_() { }"
1533 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1536 TEST(HasAnyConstructorInitializer
, ForField
) {
1537 static const char Code
[] =
1540 " Foo() : foo_(), bar_() { }"
1546 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1547 forField(hasType(recordDecl(hasName("Baz"))))))));
1548 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1549 forField(hasName("foo_"))))));
1550 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1551 forField(hasName("bar_"))))));
1552 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1553 forField(hasType(recordDecl(hasName("Bar"))))))));
1556 TEST(HasAnyConstructorInitializer
, WithInitializer
) {
1557 static const char Code
[] =
1559 " Foo() : foo_(0) { }"
1562 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1563 withInitializer(integerLiteral(equals(0)))))));
1564 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1565 withInitializer(integerLiteral(equals(1)))))));
1568 TEST(HasAnyConstructorInitializer
, IsWritten
) {
1569 static const char Code
[] =
1570 "struct Bar { Bar(){} };"
1572 " Foo() : foo_() { }"
1576 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1577 allOf(forField(hasName("foo_")), isWritten())))));
1578 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1579 allOf(forField(hasName("bar_")), isWritten())))));
1580 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1581 allOf(forField(hasName("bar_")), unless(isWritten()))))));
1584 TEST(HasAnyConstructorInitializer
, IsBaseInitializer
) {
1585 static const char Code
[] =
1589 " D(int i) : I(i) {}"
1594 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(allOf(
1595 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1597 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(allOf(
1598 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1600 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(allOf(
1601 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1603 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(allOf(
1604 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1608 TEST(IfStmt
, ChildTraversalMatchers
) {
1609 EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
1610 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1611 EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
1612 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1613 EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
1614 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1615 EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
1616 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1619 TEST(MatchBinaryOperator
, HasOperatorName
) {
1620 StatementMatcher OperatorOr
= binaryOperator(hasOperatorName("||"));
1622 EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr
));
1623 EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr
));
1626 TEST(MatchBinaryOperator
, HasAnyOperatorName
) {
1627 StatementMatcher Matcher
=
1628 binaryOperator(hasAnyOperatorName("+", "-", "*", "/"));
1630 EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher
));
1631 EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher
));
1632 EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher
));
1633 EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher
));
1634 EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher
));
1635 // Ensure '+= isn't mistaken.
1636 EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher
));
1639 TEST(MatchBinaryOperator
, HasLHSAndHasRHS
) {
1640 StatementMatcher OperatorTrueFalse
=
1641 binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),
1642 hasRHS(cxxBoolLiteral(equals(false))));
1644 EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse
));
1645 EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse
));
1646 EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse
));
1648 StatementMatcher OperatorIntPointer
= arraySubscriptExpr(
1649 hasLHS(hasType(isInteger())),
1650 traverse(TK_AsIs
, hasRHS(hasType(pointsTo(qualType())))));
1651 EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer
));
1652 EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer
));
1654 StringRef Code
= R
"cpp(
1657 bool operator==(const HasOpEqMem& other) const
1666 bool operator==(const HasOpFree& lhs, const HasOpFree& rhs)
1687 auto s1Expr
= declRefExpr(to(varDecl(hasName("s1"))));
1688 auto s2Expr
= declRefExpr(to(varDecl(hasName("s2"))));
1689 EXPECT_TRUE(matches(
1691 traverse(TK_IgnoreUnlessSpelledInSource
,
1692 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1693 hasOperatorName("=="), hasLHS(s1Expr
),
1695 EXPECT_TRUE(matches(
1696 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1697 cxxOperatorCallExpr(
1698 forFunction(functionDecl(hasName("opMem"))),
1699 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr
)))));
1700 EXPECT_TRUE(matches(
1701 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1702 cxxOperatorCallExpr(
1703 forFunction(functionDecl(hasName("opMem"))),
1704 hasOperatorName("=="), hasOperands(s1Expr
, s2Expr
)))));
1705 EXPECT_TRUE(matches(
1706 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1707 cxxOperatorCallExpr(
1708 forFunction(functionDecl(hasName("opMem"))),
1709 hasOperatorName("=="), hasEitherOperand(s2Expr
)))));
1711 EXPECT_TRUE(matches(
1713 traverse(TK_IgnoreUnlessSpelledInSource
,
1714 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1715 hasOperatorName("=="), hasLHS(s1Expr
),
1717 EXPECT_TRUE(matches(
1718 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1719 cxxOperatorCallExpr(
1720 forFunction(functionDecl(hasName("opFree"))),
1721 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr
)))));
1722 EXPECT_TRUE(matches(
1723 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1724 cxxOperatorCallExpr(
1725 forFunction(functionDecl(hasName("opFree"))),
1726 hasOperatorName("=="), hasOperands(s1Expr
, s2Expr
)))));
1727 EXPECT_TRUE(matches(
1728 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1729 cxxOperatorCallExpr(
1730 forFunction(functionDecl(hasName("opFree"))),
1731 hasOperatorName("=="), hasEitherOperand(s2Expr
)))));
1734 TEST(MatchBinaryOperator
, HasEitherOperand
) {
1735 StatementMatcher HasOperand
=
1736 binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));
1738 EXPECT_TRUE(matches("void x() { true || false; }", HasOperand
));
1739 EXPECT_TRUE(matches("void x() { false && true; }", HasOperand
));
1740 EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand
));
1743 TEST(MatchBinaryOperator
, HasOperands
) {
1744 StatementMatcher HasOperands
= binaryOperator(
1745 hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2))));
1746 EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands
));
1747 EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands
));
1748 EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands
));
1749 EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands
));
1750 EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands
));
1751 EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands
));
1754 TEST(MatchBinaryOperator
, HasOperandsEnsureOrdering
) {
1755 StatementMatcher HasOperandsWithBindings
= binaryOperator(hasOperands(
1756 cStyleCastExpr(has(declRefExpr(hasDeclaration(valueDecl().bind("d"))))),
1757 declRefExpr(hasDeclaration(valueDecl(equalsBoundNode("d"))))));
1758 EXPECT_TRUE(matches(
1759 "int a; int b = ((int) a) + a;",
1760 traverse(TK_IgnoreUnlessSpelledInSource
, HasOperandsWithBindings
)));
1761 EXPECT_TRUE(matches(
1762 "int a; int b = a + ((int) a);",
1763 traverse(TK_IgnoreUnlessSpelledInSource
, HasOperandsWithBindings
)));
1766 TEST(Matcher
, BinaryOperatorTypes
) {
1767 // Integration test that verifies the AST provides all binary operators in
1769 // FIXME: Operator ','
1771 matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));
1773 matches("bool b; bool c = (b = true);",
1774 binaryOperator(hasOperatorName("="))));
1776 matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));
1778 matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));
1779 EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));
1781 matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));
1783 matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));
1785 matches("int i = 1; int j = (i <<= 2);",
1786 binaryOperator(hasOperatorName("<<="))));
1787 EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));
1789 matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));
1791 matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));
1793 matches("int i = 1; int j = (i >>= 2);",
1794 binaryOperator(hasOperatorName(">>="))));
1796 matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));
1798 matches("int i = 42; int j = (i ^= 42);",
1799 binaryOperator(hasOperatorName("^="))));
1801 matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));
1803 matches("int i = 42; int j = (i %= 42);",
1804 binaryOperator(hasOperatorName("%="))));
1806 matches("bool b = 42 &23;", binaryOperator(hasOperatorName("&"))));
1808 matches("bool b = true && false;",
1809 binaryOperator(hasOperatorName("&&"))));
1811 matches("bool b = true; bool c = (b &= false);",
1812 binaryOperator(hasOperatorName("&="))));
1814 matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));
1816 matches("bool b = true || false;",
1817 binaryOperator(hasOperatorName("||"))));
1819 matches("bool b = true; bool c = (b |= false);",
1820 binaryOperator(hasOperatorName("|="))));
1822 matches("int i = 42 *23;", binaryOperator(hasOperatorName("*"))));
1824 matches("int i = 42; int j = (i *= 23);",
1825 binaryOperator(hasOperatorName("*="))));
1827 matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));
1829 matches("int i = 42; int j = (i /= 23);",
1830 binaryOperator(hasOperatorName("/="))));
1832 matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));
1834 matches("int i = 42; int j = (i += 23);",
1835 binaryOperator(hasOperatorName("+="))));
1837 matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));
1839 matches("int i = 42; int j = (i -= 23);",
1840 binaryOperator(hasOperatorName("-="))));
1842 matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",
1843 binaryOperator(hasOperatorName("->*"))));
1845 matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",
1846 binaryOperator(hasOperatorName(".*"))));
1848 // Member expressions as operators are not supported in matches.
1850 notMatches("struct A { void x(A *a) { a->x(this); } };",
1851 binaryOperator(hasOperatorName("->"))));
1853 // Initializer assignments are not represented as operator equals.
1855 notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));
1857 // Array indexing is not represented as operator.
1858 EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));
1860 // Overloaded operators do not match at all.
1861 EXPECT_TRUE(notMatches(
1862 "struct A { bool operator&&(const A &a) const { return false; } };"
1863 "void x() { A a, b; a && b; }",
1867 TEST(MatchUnaryOperator
, HasOperatorName
) {
1868 StatementMatcher OperatorNot
= unaryOperator(hasOperatorName("!"));
1870 EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot
));
1871 EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot
));
1874 TEST(MatchUnaryOperator
, HasAnyOperatorName
) {
1875 StatementMatcher Matcher
= unaryOperator(hasAnyOperatorName("-", "*", "++"));
1877 EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher
));
1878 EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher
));
1879 EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher
));
1880 EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher
));
1881 EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher
));
1882 EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher
));
1883 EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher
));
1886 TEST(MatchUnaryOperator
, HasUnaryOperand
) {
1887 StatementMatcher OperatorOnFalse
=
1888 unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));
1890 EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse
));
1891 EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse
));
1893 StringRef Code
= R
"cpp(
1896 bool operator!() const
1901 struct HasOpBangFree
1904 bool operator!(HasOpBangFree const&)
1922 auto s1Expr
= declRefExpr(to(varDecl(hasName("s1"))));
1923 EXPECT_TRUE(matches(
1924 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1925 cxxOperatorCallExpr(
1926 forFunction(functionDecl(hasName("opMem"))),
1927 hasOperatorName("!"), hasUnaryOperand(s1Expr
)))));
1928 EXPECT_TRUE(matches(
1930 traverse(TK_IgnoreUnlessSpelledInSource
,
1931 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1932 hasAnyOperatorName("+", "!"),
1933 hasUnaryOperand(s1Expr
)))));
1935 EXPECT_TRUE(matches(
1936 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1937 cxxOperatorCallExpr(
1938 forFunction(functionDecl(hasName("opFree"))),
1939 hasOperatorName("!"), hasUnaryOperand(s1Expr
)))));
1940 EXPECT_TRUE(matches(
1942 traverse(TK_IgnoreUnlessSpelledInSource
,
1943 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1944 hasAnyOperatorName("+", "!"),
1945 hasUnaryOperand(s1Expr
)))));
1948 struct HasIncOperatorsMem
1950 HasIncOperatorsMem& operator++();
1951 HasIncOperatorsMem operator++(int);
1953 struct HasIncOperatorsFree
1956 HasIncOperatorsFree& operator++(HasIncOperatorsFree&);
1957 HasIncOperatorsFree operator++(HasIncOperatorsFree&, int);
1959 void prefixIncOperatorMem()
1961 HasIncOperatorsMem s1;
1964 void prefixIncOperatorFree()
1966 HasIncOperatorsFree s1;
1969 void postfixIncOperatorMem()
1971 HasIncOperatorsMem s1;
1974 void postfixIncOperatorFree()
1976 HasIncOperatorsFree s1;
1982 HasOpPlusInt& operator+(int);
1984 void plusIntOperator()
1991 EXPECT_TRUE(matches(
1993 traverse(TK_IgnoreUnlessSpelledInSource
,
1994 cxxOperatorCallExpr(
1995 forFunction(functionDecl(hasName("prefixIncOperatorMem"))),
1996 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1998 EXPECT_TRUE(matches(
2000 traverse(TK_IgnoreUnlessSpelledInSource
,
2001 cxxOperatorCallExpr(
2002 forFunction(functionDecl(hasName("prefixIncOperatorFree"))),
2003 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2005 EXPECT_TRUE(matches(
2007 traverse(TK_IgnoreUnlessSpelledInSource
,
2008 cxxOperatorCallExpr(
2009 forFunction(functionDecl(hasName("postfixIncOperatorMem"))),
2010 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2012 EXPECT_TRUE(matches(
2014 traverse(TK_IgnoreUnlessSpelledInSource
,
2015 cxxOperatorCallExpr(
2016 forFunction(functionDecl(hasName("postfixIncOperatorFree"))),
2017 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2019 EXPECT_FALSE(matches(
2020 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2021 cxxOperatorCallExpr(
2022 forFunction(functionDecl(hasName("plusIntOperator"))),
2023 hasOperatorName("+"), hasUnaryOperand(expr())))));
2038 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2039 cxxOperatorCallExpr(hasOperatorName("*"),
2040 hasUnaryOperand(expr())))));
2043 TEST(Matcher
, UnaryOperatorTypes
) {
2044 // Integration test that verifies the AST provides all unary operators in
2046 EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));
2048 matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));
2049 EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));
2051 matches("bool *p; bool b = *p;", 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 matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));
2061 matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));
2063 matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));
2065 // We don't match conversion operators.
2066 EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));
2068 // Function calls are not represented as operator.
2069 EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));
2071 // Overloaded operators do not match at all.
2072 // FIXME: We probably want to add that.
2073 EXPECT_TRUE(notMatches(
2074 "struct A { bool operator!() const { return false; } };"
2075 "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
2078 TEST_P(ASTMatchersTest
, HasInit
) {
2079 if (!GetParam().isCXX11OrLater()) {
2080 // FIXME: Add a test for `hasInit()` that does not depend on C++.
2084 EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));
2085 EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));
2086 EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));
2089 TEST_P(ASTMatchersTest
, HasFoldInit
) {
2090 if (!GetParam().isCXX17OrLater()) {
2094 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2095 "return (0 + ... + args); }",
2096 cxxFoldExpr(hasFoldInit(expr()))));
2097 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2098 "return (args + ... + 0); }",
2099 cxxFoldExpr(hasFoldInit(expr()))));
2100 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2101 "return (... + args); };",
2102 cxxFoldExpr(hasFoldInit(expr()))));
2105 TEST_P(ASTMatchersTest
, HasPattern
) {
2106 if (!GetParam().isCXX17OrLater()) {
2110 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2111 "return (0 + ... + args); }",
2112 cxxFoldExpr(hasPattern(expr()))));
2113 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2114 "return (args + ... + 0); }",
2115 cxxFoldExpr(hasPattern(expr()))));
2116 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2117 "return (... + args); };",
2118 cxxFoldExpr(hasPattern(expr()))));
2121 TEST_P(ASTMatchersTest
, HasLHSAndHasRHS
) {
2122 if (!GetParam().isCXX17OrLater()) {
2126 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2127 "return (0 + ... + args); }",
2128 cxxFoldExpr(hasLHS(expr()))));
2129 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2130 "return (args + ... + 0); }",
2131 cxxFoldExpr(hasLHS(expr()))));
2132 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2133 "return (... + args); };",
2134 cxxFoldExpr(hasLHS(expr()))));
2135 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2136 "return (args + ...); };",
2137 cxxFoldExpr(hasLHS(expr()))));
2139 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2140 "return (0 + ... + args); }",
2141 cxxFoldExpr(hasRHS(expr()))));
2142 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2143 "return (args + ... + 0); }",
2144 cxxFoldExpr(hasRHS(expr()))));
2145 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2146 "return (... + args); };",
2147 cxxFoldExpr(hasRHS(expr()))));
2148 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2149 "return (args + ...); };",
2150 cxxFoldExpr(hasRHS(expr()))));
2153 TEST_P(ASTMatchersTest
, HasEitherOperandAndHasOperands
) {
2154 if (!GetParam().isCXX17OrLater()) {
2158 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2159 "return (0 + ... + args); }",
2160 cxxFoldExpr(hasEitherOperand(integerLiteral()))));
2161 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2162 "return (args + ... + 0); }",
2163 cxxFoldExpr(hasEitherOperand(integerLiteral()))));
2165 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2166 "return (0 + ... + args); }",
2167 cxxFoldExpr(hasEitherOperand(
2168 declRefExpr(to(namedDecl(hasName("args"))))))));
2169 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2170 "return (args + ... + 0); }",
2171 cxxFoldExpr(hasEitherOperand(
2172 declRefExpr(to(namedDecl(hasName("args"))))))));
2173 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2174 "return (... + args); };",
2175 cxxFoldExpr(hasEitherOperand(
2176 declRefExpr(to(namedDecl(hasName("args"))))))));
2177 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2178 "return (args + ...); };",
2179 cxxFoldExpr(hasEitherOperand(
2180 declRefExpr(to(namedDecl(hasName("args"))))))));
2182 EXPECT_TRUE(matches(
2183 "template <typename... Args> auto sum(Args... args) { "
2184 "return (0 + ... + args); }",
2185 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2186 integerLiteral()))));
2187 EXPECT_TRUE(matches(
2188 "template <typename... Args> auto sum(Args... args) { "
2189 "return (args + ... + 0); }",
2190 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2191 integerLiteral()))));
2192 EXPECT_FALSE(matches(
2193 "template <typename... Args> auto sum(Args... args) { "
2194 "return (... + args); };",
2195 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2196 integerLiteral()))));
2197 EXPECT_FALSE(matches(
2198 "template <typename... Args> auto sum(Args... args) { "
2199 "return (args + ...); };",
2200 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2201 integerLiteral()))));
2204 TEST_P(ASTMatchersTest
, Callee
) {
2205 if (!GetParam().isCXX17OrLater()) {
2209 EXPECT_TRUE(matches(
2210 "struct Dummy {}; Dummy operator+(Dummy, Dummy); template "
2211 "<typename... Args> auto sum(Args... args) { return (0 + ... + args); }",
2212 cxxFoldExpr(callee(expr()))));
2213 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2214 "return (0 + ... + args); }",
2215 cxxFoldExpr(callee(expr()))));
2218 TEST(ArraySubscriptMatchers
, ArrayIndex
) {
2219 EXPECT_TRUE(matches(
2220 "int i[2]; void f() { i[1] = 1; }",
2221 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2222 EXPECT_TRUE(matches(
2223 "int i[2]; void f() { 1[i] = 1; }",
2224 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2225 EXPECT_TRUE(notMatches(
2226 "int i[2]; void f() { i[1] = 1; }",
2227 arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));
2230 TEST(ArraySubscriptMatchers
, MatchesArrayBase
) {
2232 matches("int i[2]; void f() { i[1] = 2; }",
2233 traverse(TK_AsIs
, arraySubscriptExpr(hasBase(implicitCastExpr(
2234 hasSourceExpression(declRefExpr())))))));
2237 TEST(Matcher
, OfClass
) {
2238 StatementMatcher Constructor
= cxxConstructExpr(hasDeclaration(cxxMethodDecl(
2239 ofClass(hasName("X")))));
2242 matches("class X { public: X(); }; void x(int) { X x; }", Constructor
));
2244 matches("class X { public: X(); }; void x(int) { X x = X(); }",
2247 notMatches("class Y { public: Y(); }; void x(int) { Y y; }",
2251 TEST(Matcher
, VisitsTemplateInstantiations
) {
2252 EXPECT_TRUE(matches(
2253 "class A { public: void x(); };"
2254 "template <typename T> class B { public: void y() { T t; t.x(); } };"
2255 "void f() { B<A> b; b.y(); }",
2256 callExpr(callee(cxxMethodDecl(hasName("x"))))));
2258 EXPECT_TRUE(matches(
2259 "class A { public: void x(); };"
2262 " template <typename T> class B { public: void y() { T t; t.x(); } };"
2265 " C::B<A> b; b.y();"
2267 recordDecl(hasName("C"), hasDescendant(callExpr(
2268 callee(cxxMethodDecl(hasName("x"))))))));
2271 TEST(Matcher
, HasCondition
) {
2272 StatementMatcher IfStmt
=
2273 ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
2274 EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt
));
2275 EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt
));
2277 StatementMatcher ForStmt
=
2278 forStmt(hasCondition(cxxBoolLiteral(equals(true))));
2279 EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt
));
2280 EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt
));
2282 StatementMatcher WhileStmt
=
2283 whileStmt(hasCondition(cxxBoolLiteral(equals(true))));
2284 EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt
));
2285 EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt
));
2287 StatementMatcher SwitchStmt
=
2288 switchStmt(hasCondition(integerLiteral(equals(42))));
2289 EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt
));
2290 EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt
));
2293 TEST(For
, ForLoopInternals
) {
2294 EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
2295 forStmt(hasCondition(anything()))));
2296 EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
2297 forStmt(hasLoopInit(anything()))));
2300 TEST(For
, ForRangeLoopInternals
) {
2301 EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
2302 cxxForRangeStmt(hasLoopVariable(anything()))));
2303 EXPECT_TRUE(matches(
2304 "void f(){ int a[] {1, 2}; for (int i : a); }",
2305 cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
2308 TEST(For
, NegativeForLoopInternals
) {
2309 EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
2310 forStmt(hasCondition(expr()))));
2311 EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
2312 forStmt(hasLoopInit(anything()))));
2315 TEST(HasBody
, FindsBodyOfForWhileDoLoops
) {
2316 EXPECT_TRUE(matches("void f() { for(;;) {} }",
2317 forStmt(hasBody(compoundStmt()))));
2318 EXPECT_TRUE(notMatches("void f() { for(;;); }",
2319 forStmt(hasBody(compoundStmt()))));
2320 EXPECT_TRUE(matches("void f() { while(true) {} }",
2321 whileStmt(hasBody(compoundStmt()))));
2322 EXPECT_TRUE(matches("void f() { do {} while(true); }",
2323 doStmt(hasBody(compoundStmt()))));
2324 EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
2325 cxxForRangeStmt(hasBody(compoundStmt()))));
2328 TEST(HasBody
, FindsBodyOfFunctions
) {
2329 EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));
2330 EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));
2331 EXPECT_TRUE(matchAndVerifyResultTrue(
2332 "void f(); void f() {}",
2333 functionDecl(hasBody(compoundStmt())).bind("func"),
2334 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("func", 1)));
2335 EXPECT_TRUE(matchAndVerifyResultTrue(
2336 "class C { void f(); }; void C::f() {}",
2337 cxxMethodDecl(hasBody(compoundStmt())).bind("met"),
2338 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("met", 1)));
2339 EXPECT_TRUE(matchAndVerifyResultTrue(
2340 "class C { C(); }; C::C() {}",
2341 cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),
2342 std::make_unique
<VerifyIdIsBoundTo
<CXXConstructorDecl
>>("ctr", 1)));
2343 EXPECT_TRUE(matchAndVerifyResultTrue(
2344 "class C { ~C(); }; C::~C() {}",
2345 cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),
2346 std::make_unique
<VerifyIdIsBoundTo
<CXXDestructorDecl
>>("dtr", 1)));
2349 TEST(HasAnyBody
, FindsAnyBodyOfFunctions
) {
2350 EXPECT_TRUE(matches("void f() {}", functionDecl(hasAnyBody(compoundStmt()))));
2351 EXPECT_TRUE(notMatches("void f();",
2352 functionDecl(hasAnyBody(compoundStmt()))));
2353 EXPECT_TRUE(matchAndVerifyResultTrue(
2354 "void f(); void f() {}",
2355 functionDecl(hasAnyBody(compoundStmt())).bind("func"),
2356 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("func", 2)));
2357 EXPECT_TRUE(matchAndVerifyResultTrue(
2358 "class C { void f(); }; void C::f() {}",
2359 cxxMethodDecl(hasAnyBody(compoundStmt())).bind("met"),
2360 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("met", 2)));
2361 EXPECT_TRUE(matchAndVerifyResultTrue(
2362 "class C { C(); }; C::C() {}",
2363 cxxConstructorDecl(hasAnyBody(compoundStmt())).bind("ctr"),
2364 std::make_unique
<VerifyIdIsBoundTo
<CXXConstructorDecl
>>("ctr", 2)));
2365 EXPECT_TRUE(matchAndVerifyResultTrue(
2366 "class C { ~C(); }; C::~C() {}",
2367 cxxDestructorDecl(hasAnyBody(compoundStmt())).bind("dtr"),
2368 std::make_unique
<VerifyIdIsBoundTo
<CXXDestructorDecl
>>("dtr", 2)));
2371 TEST(HasAnySubstatement
, MatchesForTopLevelCompoundStatement
) {
2372 // The simplest case: every compound statement is in a function
2373 // definition, and the function body itself must be a compound
2375 EXPECT_TRUE(matches("void f() { for (;;); }",
2376 compoundStmt(hasAnySubstatement(forStmt()))));
2379 TEST(HasAnySubstatement
, IsNotRecursive
) {
2380 // It's really "has any immediate substatement".
2381 EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
2382 compoundStmt(hasAnySubstatement(forStmt()))));
2385 TEST(HasAnySubstatement
, MatchesInNestedCompoundStatements
) {
2386 EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
2387 compoundStmt(hasAnySubstatement(forStmt()))));
2390 TEST(HasAnySubstatement
, FindsSubstatementBetweenOthers
) {
2391 EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
2392 compoundStmt(hasAnySubstatement(forStmt()))));
2395 TEST(Member
, MatchesMemberAllocationFunction
) {
2396 // Fails in C++11 mode
2397 EXPECT_TRUE(matchesConditionally(
2398 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2399 "class X { void *operator new(std::size_t); };",
2400 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2402 EXPECT_TRUE(matches("class X { void operator delete(void*); };",
2403 cxxMethodDecl(ofClass(hasName("X")))));
2405 // Fails in C++11 mode
2406 EXPECT_TRUE(matchesConditionally(
2407 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2408 "class X { void operator delete[](void*, std::size_t); };",
2409 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2412 TEST(HasDestinationType
, MatchesSimpleCase
) {
2413 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
2414 cxxStaticCastExpr(hasDestinationType(
2415 pointsTo(TypeMatcher(anything()))))));
2418 TEST(HasImplicitDestinationType
, MatchesSimpleCase
) {
2419 // This test creates an implicit const cast.
2420 EXPECT_TRUE(matches(
2421 "int x; const int i = x;",
2423 implicitCastExpr(hasImplicitDestinationType(isInteger())))));
2424 // This test creates an implicit array-to-pointer cast.
2426 matches("int arr[3]; int *p = arr;",
2427 traverse(TK_AsIs
, implicitCastExpr(hasImplicitDestinationType(
2428 pointsTo(TypeMatcher(anything())))))));
2431 TEST(HasImplicitDestinationType
, DoesNotMatchIncorrectly
) {
2432 // This test creates an implicit cast from int to char.
2433 EXPECT_TRUE(notMatches("char c = 0;",
2434 implicitCastExpr(hasImplicitDestinationType(
2435 unless(anything())))));
2436 // This test creates an implicit array-to-pointer cast.
2437 EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
2438 implicitCastExpr(hasImplicitDestinationType(
2439 unless(anything())))));
2442 TEST(Matcher
, IgnoresElidableConstructors
) {
2444 matches("struct H {};"
2445 "template<typename T> H B(T A);"
2450 cxxOperatorCallExpr(hasArgument(
2451 1, callExpr(hasArgument(
2452 0, ignoringElidableConstructorCall(callExpr()))))),
2453 langCxx11OrLater()));
2455 matches("struct H {};"
2456 "template<typename T> H B(T A);"
2461 cxxOperatorCallExpr(hasArgument(
2462 1, callExpr(hasArgument(0, ignoringElidableConstructorCall(
2463 integerLiteral()))))),
2464 langCxx11OrLater()));
2465 EXPECT_TRUE(matches(
2471 varDecl(hasInitializer(anyOf(
2472 ignoringElidableConstructorCall(callExpr()),
2473 exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())))))),
2474 langCxx11OrLater()));
2477 TEST(Matcher
, IgnoresElidableInReturn
) {
2478 auto matcher
= expr(ignoringElidableConstructorCall(declRefExpr()));
2479 EXPECT_TRUE(matches("struct H {};"
2484 matcher
, langCxx11OrLater()));
2485 EXPECT_TRUE(notMatches("struct H {};"
2489 matcher
, langCxx11OrLater()));
2492 TEST(Matcher
, IgnoreElidableConstructorDoesNotMatchConstructors
) {
2493 EXPECT_TRUE(matches("struct H {};"
2497 varDecl(hasInitializer(
2498 ignoringElidableConstructorCall(cxxConstructExpr()))),
2499 langCxx11OrLater()));
2502 TEST(Matcher
, IgnoresElidableDoesNotPreventMatches
) {
2503 EXPECT_TRUE(matches("void f() {"
2506 expr(ignoringElidableConstructorCall(integerLiteral())),
2507 langCxx11OrLater()));
2510 TEST(Matcher
, IgnoresElidableInVarInit
) {
2512 varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())));
2513 EXPECT_TRUE(matches("struct H {};"
2515 "void f(H D = G()) {"
2518 matcher
, langCxx11OrLater()));
2519 EXPECT_TRUE(matches("struct H {};"
2524 matcher
, langCxx11OrLater()));
2527 TEST(IgnoringImplicit
, MatchesImplicit
) {
2528 EXPECT_TRUE(matches("class C {}; C a = C();",
2529 varDecl(has(ignoringImplicit(cxxConstructExpr())))));
2532 TEST(IgnoringImplicit
, MatchesNestedImplicit
) {
2533 StringRef Code
= R
"(
2540 SomeType(const OtherType&) {}
2541 SomeType& operator=(OtherType const&) { return *this; }
2550 OtherType something()
2557 SomeType i = something();
2560 EXPECT_TRUE(matches(
2563 varDecl(hasName("i"),
2564 hasInitializer(exprWithCleanups(has(cxxConstructExpr(
2565 has(expr(ignoringImplicit(cxxConstructExpr(has(
2566 expr(ignoringImplicit(callExpr())))))))))))))));
2569 TEST(IgnoringImplicit
, DoesNotMatchIncorrectly
) {
2570 EXPECT_TRUE(notMatches("class C {}; C a = C();",
2571 traverse(TK_AsIs
, varDecl(has(cxxConstructExpr())))));
2574 TEST(Traversal
, traverseMatcher
) {
2576 StringRef VarDeclCode
= R
"cpp(
2583 auto Matcher
= varDecl(hasInitializer(floatLiteral()));
2585 EXPECT_TRUE(notMatches(VarDeclCode
, traverse(TK_AsIs
, Matcher
)));
2587 matches(VarDeclCode
, traverse(TK_IgnoreUnlessSpelledInSource
, Matcher
)));
2589 auto ParentMatcher
= floatLiteral(hasParent(varDecl(hasName("i"))));
2591 EXPECT_TRUE(notMatches(VarDeclCode
, traverse(TK_AsIs
, ParentMatcher
)));
2592 EXPECT_TRUE(matches(VarDeclCode
,
2593 traverse(TK_IgnoreUnlessSpelledInSource
, ParentMatcher
)));
2595 EXPECT_TRUE(matches(
2596 VarDeclCode
, decl(traverse(TK_AsIs
, anyOf(cxxRecordDecl(), varDecl())))));
2599 matches(VarDeclCode
,
2600 floatLiteral(traverse(TK_AsIs
, hasParent(implicitCastExpr())))));
2603 matches(VarDeclCode
, floatLiteral(traverse(TK_IgnoreUnlessSpelledInSource
,
2604 hasParent(varDecl())))));
2607 matches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2608 unless(parmVarDecl())))));
2611 notMatches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2612 has(implicitCastExpr())))));
2614 EXPECT_TRUE(matches(VarDeclCode
,
2615 varDecl(traverse(TK_AsIs
, has(implicitCastExpr())))));
2617 EXPECT_TRUE(matches(
2618 VarDeclCode
, traverse(TK_IgnoreUnlessSpelledInSource
,
2619 // The has() below strips away the ImplicitCastExpr
2620 // before the traverse(AsIs) gets to process it.
2621 varDecl(has(traverse(TK_AsIs
, floatLiteral()))))));
2624 matches(VarDeclCode
, functionDecl(traverse(TK_AsIs
, hasName("foo")))));
2626 EXPECT_TRUE(matches(
2628 functionDecl(traverse(TK_IgnoreUnlessSpelledInSource
, hasName("foo")))));
2630 EXPECT_TRUE(matches(
2631 VarDeclCode
, functionDecl(traverse(TK_AsIs
, hasAnyName("foo", "bar")))));
2634 matches(VarDeclCode
, functionDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2635 hasAnyName("foo", "bar")))));
2637 StringRef Code
= R
"cpp(
2648 matches(Code
, callExpr(traverse(TK_IgnoreUnlessSpelledInSource
,
2649 hasArgument(0, floatLiteral())))));
2652 matches(Code
, callExpr(traverse(TK_IgnoreUnlessSpelledInSource
,
2653 hasAnyArgument(floatLiteral())))));
2655 EXPECT_TRUE(matches(
2657 void takesBool(bool){}
2659 template <typename T>
2660 void neverInstantiatedTemplate() {
2664 traverse(TK_IgnoreUnlessSpelledInSource
,
2665 callExpr(unless(callExpr(hasDeclaration(functionDecl())))))));
2668 matches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2669 hasType(builtinType())))));
2672 matches(VarDeclCode
,
2673 functionDecl(hasName("foo"),
2674 traverse(TK_AsIs
, hasDescendant(floatLiteral())))));
2676 EXPECT_TRUE(notMatches(
2677 Code
, traverse(TK_AsIs
, floatLiteral(hasParent(callExpr(
2678 callee(functionDecl(hasName("foo")))))))));
2679 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2680 floatLiteral(hasParent(callExpr(callee(
2681 functionDecl(hasName("foo")))))))));
2689 EXPECT_TRUE(matches(
2690 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2691 varDecl(hasInitializer(integerLiteral(equals(3)))))));
2692 EXPECT_TRUE(matches(
2694 traverse(TK_IgnoreUnlessSpelledInSource
,
2695 integerLiteral(equals(3), hasParent(varDecl(hasName("i")))))));
2698 const char *SomeString{"str
"};
2701 matches(Code
, traverse(TK_AsIs
, stringLiteral(hasParent(implicitCastExpr(
2702 hasParent(initListExpr())))))));
2704 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2705 stringLiteral(hasParent(initListExpr())))));
2710 String(const char*, int = -1) {}
2713 void stringConstruct()
2719 EXPECT_TRUE(matches(
2724 hasName("stringConstruct"),
2725 hasDescendant(varDecl(
2727 hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(
2728 0, ignoringImplicit(cxxConstructExpr(hasArgument(
2729 0, ignoringImplicit(stringLiteral()))))))))))))));
2731 EXPECT_TRUE(matches(
2735 functionDecl(hasName("stringConstruct"),
2736 hasDescendant(cxxOperatorCallExpr(
2737 isAssignmentOperator(),
2738 hasArgument(1, ignoringImplicit(
2739 cxxConstructExpr(hasArgument(
2740 0, ignoringImplicit(stringLiteral())))))
2743 EXPECT_TRUE(matches(
2744 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2745 functionDecl(hasName("stringConstruct"),
2746 hasDescendant(varDecl(
2748 hasInitializer(stringLiteral())))))));
2751 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2752 functionDecl(hasName("stringConstruct"),
2753 hasDescendant(cxxOperatorCallExpr(
2754 isAssignmentOperator(),
2755 hasArgument(1, stringLiteral())))))));
2760 struct C2 { operator C1(); };
2762 void conversionOperator()
2769 EXPECT_TRUE(matches(
2774 hasName("conversionOperator"),
2779 ignoringImplicit(cxxConstructExpr(hasArgument(
2780 0, ignoringImplicit(
2781 cxxMemberCallExpr(onImplicitObjectArgument(
2782 ignoringParenImpCasts(unaryOperator(
2783 hasOperatorName("*")))))))))))
2786 EXPECT_TRUE(matches(
2788 traverse(TK_IgnoreUnlessSpelledInSource
,
2789 functionDecl(hasName("conversionOperator"),
2790 hasDescendant(varDecl(
2791 hasName("c1"), hasInitializer(unaryOperator(
2792 hasOperatorName("*")))))))));
2796 template <unsigned alignment>
2797 void template_test() {
2798 static_assert(alignment, "");
2800 void actual_template_test() {
2805 EXPECT_TRUE(matches(
2808 staticAssertDecl(has(implicitCastExpr(has(
2809 substNonTypeTemplateParmExpr(has(integerLiteral())))))))));
2810 EXPECT_TRUE(matches(
2811 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2812 staticAssertDecl(has(declRefExpr(
2813 to(nonTypeTemplateParmDecl(hasName("alignment"))),
2814 hasType(asString("unsigned int"))))))));
2816 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, staticAssertDecl(hasDescendant(
2817 integerLiteral())))));
2818 EXPECT_FALSE(matches(
2819 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2820 staticAssertDecl(hasDescendant(integerLiteral())))));
2824 struct OneParamCtor {
2825 explicit OneParamCtor(int);
2827 struct TwoParamCtor {
2828 explicit TwoParamCtor(int, int);
2831 void varDeclCtors() {
2833 auto var1 = OneParamCtor(5);
2834 auto var2 = TwoParamCtor(6, 7);
2837 OneParamCtor var3(5);
2838 TwoParamCtor var4(6, 7);
2842 auto var5 = OneParamCtor(i);
2843 auto var6 = TwoParamCtor(i, 7);
2846 OneParamCtor var7(i);
2847 TwoParamCtor var8(i, 7);
2852 EXPECT_TRUE(matches(
2854 traverse(TK_AsIs
, varDecl(hasName("var1"), hasInitializer(hasDescendant(
2855 cxxConstructExpr()))))));
2856 EXPECT_TRUE(matches(
2858 traverse(TK_AsIs
, varDecl(hasName("var2"), hasInitializer(hasDescendant(
2859 cxxConstructExpr()))))));
2860 EXPECT_TRUE(matches(
2861 Code
, traverse(TK_AsIs
, varDecl(hasName("var3"),
2862 hasInitializer(cxxConstructExpr())))));
2863 EXPECT_TRUE(matches(
2864 Code
, traverse(TK_AsIs
, varDecl(hasName("var4"),
2865 hasInitializer(cxxConstructExpr())))));
2866 EXPECT_TRUE(matches(
2868 traverse(TK_AsIs
, varDecl(hasName("var5"), hasInitializer(hasDescendant(
2869 cxxConstructExpr()))))));
2870 EXPECT_TRUE(matches(
2872 traverse(TK_AsIs
, varDecl(hasName("var6"), hasInitializer(hasDescendant(
2873 cxxConstructExpr()))))));
2874 EXPECT_TRUE(matches(
2875 Code
, traverse(TK_AsIs
, varDecl(hasName("var7"),
2876 hasInitializer(cxxConstructExpr())))));
2877 EXPECT_TRUE(matches(
2878 Code
, traverse(TK_AsIs
, varDecl(hasName("var8"),
2879 hasInitializer(cxxConstructExpr())))));
2881 EXPECT_TRUE(matches(
2883 traverse(TK_IgnoreUnlessSpelledInSource
,
2884 varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));
2885 EXPECT_TRUE(matches(
2887 traverse(TK_IgnoreUnlessSpelledInSource
,
2888 varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));
2889 EXPECT_TRUE(matches(
2891 traverse(TK_IgnoreUnlessSpelledInSource
,
2892 varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));
2893 EXPECT_TRUE(matches(
2895 traverse(TK_IgnoreUnlessSpelledInSource
,
2896 varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));
2897 EXPECT_TRUE(matches(
2899 traverse(TK_IgnoreUnlessSpelledInSource
,
2900 varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));
2901 EXPECT_TRUE(matches(
2903 traverse(TK_IgnoreUnlessSpelledInSource
,
2904 varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));
2905 EXPECT_TRUE(matches(
2907 traverse(TK_IgnoreUnlessSpelledInSource
,
2908 varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));
2909 EXPECT_TRUE(matches(
2911 traverse(TK_IgnoreUnlessSpelledInSource
,
2912 varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));
2916 template<typename T>
2917 struct TemplStruct {
2927 template<typename T>
2928 void TemplStruct<T>::outOfLine(T)
2933 template<typename T>
2941 TemplStruct<int> ti;
2942 TemplStruct<double> td;
2943 (void)timesTwo<int>(2);
2944 (void)timesTwo<double>(2);
2947 template class TemplStruct<float>;
2949 extern template class TemplStruct<long>;
2951 template<> class TemplStruct<bool> {
2955 void boolSpecializationMethodOnly() {}
2960 template float timesTwo(float);
2961 template<> bool timesTwo<bool>(bool){
2966 auto M
= cxxRecordDecl(hasName("TemplStruct"),
2967 has(fieldDecl(hasType(asString("int")))));
2968 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2969 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2972 auto M
= cxxRecordDecl(hasName("TemplStruct"),
2973 has(fieldDecl(hasType(asString("double")))));
2974 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2975 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2979 functionDecl(hasName("timesTwo"),
2980 hasParameter(0, parmVarDecl(hasType(asString("int")))));
2981 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2982 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2986 functionDecl(hasName("timesTwo"),
2987 hasParameter(0, parmVarDecl(hasType(asString("double")))));
2988 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2989 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2992 // Match on the integer literal in the explicit instantiation:
2994 functionDecl(hasName("timesTwo"),
2995 hasParameter(0, parmVarDecl(hasType(asString("float")))),
2996 hasDescendant(integerLiteral(equals(2))));
2997 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDef
)));
2998 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDef
)));
3001 functionDecl(hasName("timesTwo"),
3002 hasTemplateArgument(0, refersToType(asString("float"))));
3003 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MTempl
)));
3004 // TODO: If we could match on explicit instantiations of function templates,
3005 // this would be EXPECT_TRUE. See Sema::ActOnExplicitInstantiation.
3007 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MTempl
)));
3010 auto M
= functionDecl(hasName("timesTwo"),
3011 hasParameter(0, parmVarDecl(hasType(booleanType()))));
3012 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3013 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3016 // Match on the field within the explicit instantiation:
3017 auto MRecord
= cxxRecordDecl(hasName("TemplStruct"),
3018 has(fieldDecl(hasType(asString("float")))));
3019 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MRecord
)));
3021 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MRecord
)));
3023 // Match on the explicit template instantiation itself:
3024 auto MTempl
= classTemplateSpecializationDecl(
3025 hasName("TemplStruct"),
3026 hasTemplateArgument(0,
3027 templateArgument(refersToType(asString("float")))));
3028 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MTempl
)));
3030 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MTempl
)));
3033 // The template argument is matchable, but the instantiation is not:
3034 auto M
= classTemplateSpecializationDecl(
3035 hasName("TemplStruct"),
3036 hasTemplateArgument(0,
3037 templateArgument(refersToType(asString("float")))),
3038 has(cxxConstructorDecl(hasName("TemplStruct"))));
3039 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3040 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3043 // The template argument is matchable, but the instantiation is not:
3044 auto M
= classTemplateSpecializationDecl(
3045 hasName("TemplStruct"),
3046 hasTemplateArgument(0,
3047 templateArgument(refersToType(asString("long")))),
3048 has(cxxConstructorDecl(hasName("TemplStruct"))));
3049 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3050 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3053 // Instantiated, out-of-line methods are not matchable.
3055 cxxMethodDecl(hasName("outOfLine"), isDefinition(),
3056 hasParameter(0, parmVarDecl(hasType(asString("float")))));
3057 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3058 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3061 // Explicit specialization is written in source and it matches:
3062 auto M
= classTemplateSpecializationDecl(
3063 hasName("TemplStruct"),
3064 hasTemplateArgument(0, templateArgument(refersToType(booleanType()))),
3065 has(cxxConstructorDecl(hasName("TemplStruct"))),
3066 has(cxxMethodDecl(hasName("boolSpecializationMethodOnly"))));
3067 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3068 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3076 B func1() { return 42; }
3079 auto M
= expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit")));
3080 EXPECT_TRUE(matchAndVerifyResultTrue(
3081 Code
, traverse(TK_AsIs
, M
),
3082 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3083 EXPECT_TRUE(matchAndVerifyResultTrue(
3084 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3085 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3088 auto M
= expr(unless(integerLiteral(equals(24)))).bind("intLit");
3089 EXPECT_TRUE(matchAndVerifyResultTrue(
3090 Code
, traverse(TK_AsIs
, M
),
3091 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 6),
3094 EXPECT_TRUE(matchAndVerifyResultTrue(
3095 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3096 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1),
3101 expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr())));
3102 EXPECT_TRUE(matchAndVerifyResultTrue(
3103 Code
, traverse(TK_AsIs
, M
),
3104 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3105 EXPECT_TRUE(matchAndVerifyResultTrue(
3106 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3107 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3110 auto M
= expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr()));
3111 EXPECT_TRUE(matchAndVerifyResultTrue(
3112 Code
, traverse(TK_AsIs
, M
),
3113 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3114 EXPECT_TRUE(matchAndVerifyResultTrue(
3115 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3116 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3119 auto M
= expr(integerLiteral(equals(42)).bind("intLit"), expr());
3120 EXPECT_TRUE(matchAndVerifyResultTrue(
3121 Code
, traverse(TK_AsIs
, M
),
3122 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3123 EXPECT_TRUE(matchAndVerifyResultTrue(
3124 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3125 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3128 auto M
= expr(optionally(integerLiteral(equals(42)).bind("intLit")));
3129 EXPECT_TRUE(matchAndVerifyResultTrue(
3130 Code
, traverse(TK_AsIs
, M
),
3131 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3132 EXPECT_TRUE(matchAndVerifyResultTrue(
3133 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3134 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
3137 auto M
= expr().bind("allExprs");
3138 EXPECT_TRUE(matchAndVerifyResultTrue(
3139 Code
, traverse(TK_AsIs
, M
),
3140 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("allExprs", 6),
3142 EXPECT_TRUE(matchAndVerifyResultTrue(
3143 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3144 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("allExprs", 1)));
3151 auto &[f, s, t] = arr;
3157 auto M
= bindingDecl(hasName("f"));
3159 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3161 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3162 true, {"-std=c++17"}));
3165 auto M
= bindingDecl(hasName("f"), has(expr()));
3167 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3169 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3170 true, {"-std=c++17"}));
3173 auto M
= integerLiteral(hasAncestor(bindingDecl(hasName("f"))));
3175 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3177 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3178 true, {"-std=c++17"}));
3181 auto M
= declRefExpr(hasAncestor(bindingDecl(hasName("f"))));
3183 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
3185 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3186 true, {"-std=c++17"}));
3190 TEST(Traversal
, traverseNoImplicit
) {
3191 StringRef Code
= R
"cpp(
3194 NonTrivial(const NonTrivial&) {}
3195 NonTrivial& operator=(const NonTrivial&) { return *this; }
3200 struct NoSpecialMethods {
3204 struct ContainsArray {
3206 ContainsArray& operator=(const ContainsArray &other) = default;
3211 NoSpecialMethods nc1;
3212 NoSpecialMethods nc2(nc1);
3220 struct HasCtorInits : NoSpecialMethods, NonTrivial
3224 HasCtorInits() : NoSpecialMethods(), m_i(42) {}
3227 struct CtorInitsNonTrivial : NonTrivial
3231 CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}
3236 auto M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3237 has(cxxRecordDecl(hasName("NoSpecialMethods"))));
3238 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3239 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3241 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3242 has(cxxConstructorDecl(isCopyConstructor())));
3243 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3244 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3246 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3247 has(cxxMethodDecl(isCopyAssignmentOperator())));
3248 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3249 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3251 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3252 has(cxxConstructorDecl(isDefaultConstructor())));
3253 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3254 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3256 M
= cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));
3257 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3258 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3260 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3261 hasMethod(cxxConstructorDecl(isCopyConstructor())));
3262 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3263 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3265 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3266 hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));
3267 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3268 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3270 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3271 hasMethod(cxxConstructorDecl(isDefaultConstructor())));
3272 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3273 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3275 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3276 hasMethod(cxxDestructorDecl()));
3277 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3278 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3281 // Because the copy-assignment operator is not spelled in the
3282 // source (ie, isImplicit()), we don't match it
3284 cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),
3285 callee(cxxMethodDecl(isCopyAssignmentOperator())));
3286 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3287 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3290 // Compiler generates a forStmt to copy the array
3291 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, forStmt())));
3293 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, forStmt())));
3296 // The defaulted method declaration can be matched, but not its
3297 // definition, in IgnoreUnlessSpelledInSource mode
3298 auto MDecl
= cxxMethodDecl(ofClass(cxxRecordDecl(hasName("ContainsArray"))),
3299 isCopyAssignmentOperator(), isDefaulted());
3301 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDecl
)));
3302 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDecl
)));
3304 auto MDef
= cxxMethodDecl(MDecl
, has(compoundStmt()));
3306 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDef
)));
3307 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDef
)));
3309 auto MBody
= cxxMethodDecl(MDecl
, hasBody(compoundStmt()));
3311 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MBody
)));
3313 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MBody
)));
3315 auto MIsDefn
= cxxMethodDecl(MDecl
, isDefinition());
3317 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MIsDefn
)));
3319 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MIsDefn
)));
3321 auto MIsInline
= cxxMethodDecl(MDecl
, isInline());
3323 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, MIsInline
)));
3325 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MIsInline
)));
3327 // The parameter of the defaulted method can still be matched.
3329 cxxMethodDecl(MDecl
, hasParameter(0, parmVarDecl(hasName("other"))));
3331 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MParm
)));
3332 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MParm
)));
3336 cxxConstructorDecl(hasName("HasCtorInits"),
3337 has(cxxCtorInitializer(forField(hasName("m_i")))));
3338 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3339 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3343 cxxConstructorDecl(hasName("HasCtorInits"),
3344 has(cxxCtorInitializer(forField(hasName("m_nt")))));
3345 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3346 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3349 auto M
= cxxConstructorDecl(hasName("HasCtorInits"),
3350 hasAnyConstructorInitializer(cxxCtorInitializer(
3351 forField(hasName("m_nt")))));
3352 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3353 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3357 cxxConstructorDecl(hasName("HasCtorInits"),
3358 forEachConstructorInitializer(
3359 cxxCtorInitializer(forField(hasName("m_nt")))));
3360 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3361 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3364 auto M
= cxxConstructorDecl(
3365 hasName("CtorInitsNonTrivial"),
3366 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(
3367 hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));
3368 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3369 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3372 auto M
= cxxConstructorDecl(
3373 hasName("HasCtorInits"),
3374 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(
3375 cxxConstructorDecl(hasName("NoSpecialMethods"))))))));
3376 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3377 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3380 auto M
= cxxCtorInitializer(forField(hasName("m_nt")));
3381 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3382 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3398 auto M
= cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3399 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3400 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3404 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3405 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3406 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3410 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3411 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3412 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3415 auto M
= cxxForRangeStmt(has(declStmt()));
3416 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3417 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3421 cxxForRangeStmt(hasLoopVariable(varDecl(hasName("i"))),
3422 hasRangeInit(declRefExpr(to(varDecl(hasName("arr"))))));
3423 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3424 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3427 auto M
= cxxForRangeStmt(unless(hasInitStatement(stmt())));
3428 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3429 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3432 auto M
= cxxForRangeStmt(hasBody(stmt()));
3433 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3434 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3437 auto M
= cxxForRangeStmt(hasDescendant(ifStmt()));
3438 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3439 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3442 EXPECT_TRUE(matches(
3443 Code
, traverse(TK_AsIs
, cxxForRangeStmt(has(declStmt(
3444 hasSingleDecl(varDecl(hasName("i")))))))));
3446 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3447 cxxForRangeStmt(has(varDecl(hasName("i")))))));
3450 EXPECT_TRUE(matches(
3451 Code
, traverse(TK_AsIs
, cxxForRangeStmt(has(declStmt(hasSingleDecl(
3452 varDecl(hasInitializer(declRefExpr(
3453 to(varDecl(hasName("arr")))))))))))));
3454 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3455 cxxForRangeStmt(has(declRefExpr(
3456 to(varDecl(hasName("arr")))))))));
3459 auto M
= cxxForRangeStmt(has(compoundStmt()));
3460 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3461 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3464 auto M
= binaryOperator(hasOperatorName("!="));
3465 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3466 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3469 auto M
= unaryOperator(hasOperatorName("++"));
3470 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3471 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3474 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__range"))));
3475 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3476 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3479 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__begin"))));
3480 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3481 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3484 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__end"))));
3485 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3486 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3489 auto M
= ifStmt(hasParent(compoundStmt(hasParent(cxxForRangeStmt()))));
3490 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3491 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3494 auto M
= cxxForRangeStmt(
3495 has(varDecl(hasName("i"), hasParent(cxxForRangeStmt()))));
3496 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3497 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3500 auto M
= cxxForRangeStmt(hasDescendant(varDecl(
3501 hasName("i"), hasParent(declStmt(hasParent(cxxForRangeStmt()))))));
3502 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3503 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3506 auto M
= cxxForRangeStmt(hasRangeInit(declRefExpr(
3507 to(varDecl(hasName("arr"))), hasParent(cxxForRangeStmt()))));
3508 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3509 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3513 auto M
= cxxForRangeStmt(hasRangeInit(declRefExpr(
3514 to(varDecl(hasName("arr"))), hasParent(varDecl(hasParent(declStmt(
3515 hasParent(cxxForRangeStmt()))))))));
3516 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3517 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3525 Range getRange(int);
3529 for (auto i : getRange(42))
3535 auto M
= integerLiteral(equals(42));
3536 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3537 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3540 auto M
= callExpr(hasDescendant(integerLiteral(equals(42))));
3541 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3542 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3545 auto M
= compoundStmt(hasDescendant(integerLiteral(equals(42))));
3546 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3547 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3554 for (auto& a = arr; auto i : a)
3561 auto M
= cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3563 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3565 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3566 true, {"-std=c++20"}));
3570 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3572 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3574 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3575 true, {"-std=c++20"}));
3579 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3581 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3583 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3584 true, {"-std=c++20"}));
3588 cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i"))))));
3590 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3592 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3593 true, {"-std=c++20"}));
3596 auto M
= cxxForRangeStmt(
3597 hasInitStatement(declStmt(hasSingleDecl(varDecl(
3599 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3600 hasLoopVariable(varDecl(hasName("i"))),
3601 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3603 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3605 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3606 true, {"-std=c++20"}));
3609 auto M
= cxxForRangeStmt(
3610 has(declStmt(hasSingleDecl(varDecl(
3612 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3613 hasLoopVariable(varDecl(hasName("i"))),
3614 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3616 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3618 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3619 true, {"-std=c++20"}));
3622 auto M
= cxxForRangeStmt(hasInitStatement(declStmt(
3623 hasSingleDecl(varDecl(hasName("a"))), hasParent(cxxForRangeStmt()))));
3625 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3627 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3628 true, {"-std=c++20"}));
3636 Range getRange(int);
3642 for (auto j = getNum(42); auto i : getRange(j))
3648 auto M
= integerLiteral(equals(42));
3650 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3652 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3653 true, {"-std=c++20"}));
3656 auto M
= compoundStmt(hasDescendant(integerLiteral(equals(42))));
3658 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3660 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3661 true, {"-std=c++20"}));
3665 void hasDefaultArg(int i, int j = 0)
3668 void callDefaultArg()
3673 auto hasDefaultArgCall
= [](auto InnerMatcher
) {
3674 return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),
3678 auto M
= hasDefaultArgCall(has(integerLiteral(equals(42))));
3679 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3680 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3683 auto M
= hasDefaultArgCall(has(cxxDefaultArgExpr()));
3684 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3685 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3688 auto M
= hasDefaultArgCall(argumentCountIs(2));
3689 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3690 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3693 auto M
= hasDefaultArgCall(argumentCountIs(1));
3694 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3695 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3698 auto M
= hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));
3699 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3700 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3703 auto M
= hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));
3704 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3705 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3718 auto M
= cxxDestructorDecl(isDefaulted(),
3719 ofClass(cxxRecordDecl(has(fieldDecl()))));
3720 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3721 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3726 static constexpr bool getTrue() { return true; }
3731 explicit(S::getTrue()) A();
3737 EXPECT_TRUE(matchesConditionally(
3742 hasExplicitSpecifier(expr(ignoringImplicit(
3743 callExpr(has(ignoringImplicit(declRefExpr())))))))),
3744 true, {"-std=c++20"}));
3745 EXPECT_TRUE(matchesConditionally(
3747 traverse(TK_IgnoreUnlessSpelledInSource
,
3750 hasExplicitSpecifier(callExpr(has(declRefExpr()))))),
3751 true, {"-std=c++20"}));
3755 template <typename MatcherT
>
3756 bool matcherTemplateWithBinding(StringRef Code
, const MatcherT
&M
) {
3757 return matchAndVerifyResultTrue(
3758 Code
, M
.bind("matchedStmt"),
3759 std::make_unique
<VerifyIdIsBoundTo
<ReturnStmt
>>("matchedStmt", 1));
3762 TEST(Traversal
, traverseWithBinding
) {
3763 // Some existing matcher code expects to take a matcher as a
3764 // template arg and bind to it. Verify that that works.
3766 llvm::StringRef Code
= R
"cpp(
3772 EXPECT_TRUE(matcherTemplateWithBinding(
3773 Code
, traverse(TK_AsIs
,
3774 returnStmt(has(implicitCastExpr(has(floatLiteral())))))));
3777 TEST(Traversal
, traverseMatcherNesting
) {
3779 StringRef Code
= R
"cpp(
3792 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3793 callExpr(has(callExpr(traverse(
3794 TK_AsIs
, callExpr(has(implicitCastExpr(
3795 has(floatLiteral())))))))))));
3797 EXPECT_TRUE(matches(
3799 traverse(TK_IgnoreUnlessSpelledInSource
,
3800 traverse(TK_AsIs
, implicitCastExpr(has(floatLiteral()))))));
3803 TEST(Traversal
, traverseMatcherThroughImplicit
) {
3804 StringRef Code
= R
"cpp(
3809 void constructImplicit() {
3815 auto Matcher
= traverse(TK_IgnoreUnlessSpelledInSource
, implicitCastExpr());
3817 // Verfiy that it does not segfault
3818 EXPECT_FALSE(matches(Code
, Matcher
));
3821 TEST(Traversal
, traverseMatcherThroughMemoization
) {
3823 StringRef Code
= R
"cpp(
3830 auto Matcher
= varDecl(hasInitializer(floatLiteral()));
3832 // Matchers such as hasDescendant memoize their result regarding AST
3833 // nodes. In the matcher below, the first use of hasDescendant(Matcher)
3834 // fails, and the use of it inside the traverse() matcher should pass
3835 // causing the overall matcher to be a true match.
3836 // This test verifies that the first false result is not re-used, which
3837 // would cause the overall matcher to be incorrectly false.
3839 EXPECT_TRUE(matches(
3841 functionDecl(anyOf(hasDescendant(Matcher
),
3842 traverse(TK_IgnoreUnlessSpelledInSource
,
3843 functionDecl(hasDescendant(Matcher
)))))));
3846 TEST(Traversal
, traverseUnlessSpelledInSource
) {
3848 StringRef Code
= R
"cpp(
3921 [a, b = c](int d) { int e = d; };
3925 [] <typename TemplateType> (TemplateType t, TemplateType u) { int e = t + u; };
3931 auto l = [&] { ++count; };
3939 traverse(TK_IgnoreUnlessSpelledInSource
,
3940 returnStmt(forFunction(functionDecl(hasName("func1"))),
3941 hasReturnValue(integerLiteral(equals(42))))),
3942 langCxx20OrLater()));
3946 traverse(TK_IgnoreUnlessSpelledInSource
,
3947 integerLiteral(equals(42),
3948 hasParent(returnStmt(forFunction(
3949 functionDecl(hasName("func1"))))))),
3950 langCxx20OrLater()));
3952 EXPECT_TRUE(matches(
3954 traverse(TK_IgnoreUnlessSpelledInSource
,
3955 returnStmt(forFunction(functionDecl(hasName("func2"))),
3956 hasReturnValue(cxxTemporaryObjectExpr(
3957 hasArgument(0, integerLiteral(equals(42))))))),
3958 langCxx20OrLater()));
3959 EXPECT_TRUE(matches(
3962 TK_IgnoreUnlessSpelledInSource
,
3963 integerLiteral(equals(42),
3964 hasParent(cxxTemporaryObjectExpr(hasParent(returnStmt(
3965 forFunction(functionDecl(hasName("func2"))))))))),
3966 langCxx20OrLater()));
3970 traverse(TK_IgnoreUnlessSpelledInSource
,
3971 returnStmt(forFunction(functionDecl(hasName("func3"))),
3972 hasReturnValue(cxxConstructExpr(hasArgument(
3973 0, integerLiteral(equals(42))))))),
3974 langCxx20OrLater()));
3976 EXPECT_TRUE(matches(
3979 TK_IgnoreUnlessSpelledInSource
,
3980 integerLiteral(equals(42),
3981 hasParent(cxxConstructExpr(hasParent(returnStmt(
3982 forFunction(functionDecl(hasName("func3"))))))))),
3983 langCxx20OrLater()));
3987 traverse(TK_IgnoreUnlessSpelledInSource
,
3988 returnStmt(forFunction(functionDecl(hasName("func4"))),
3989 hasReturnValue(cxxTemporaryObjectExpr()))),
3990 langCxx20OrLater()));
3994 traverse(TK_IgnoreUnlessSpelledInSource
,
3995 returnStmt(forFunction(functionDecl(hasName("func5"))),
3996 hasReturnValue(cxxTemporaryObjectExpr()))),
3997 langCxx20OrLater()));
4001 traverse(TK_IgnoreUnlessSpelledInSource
,
4002 returnStmt(forFunction(functionDecl(hasName("func6"))),
4003 hasReturnValue(cxxTemporaryObjectExpr()))),
4004 langCxx20OrLater()));
4008 traverse(TK_IgnoreUnlessSpelledInSource
,
4009 returnStmt(forFunction(functionDecl(hasName("func7"))),
4010 hasReturnValue(cxxTemporaryObjectExpr()))),
4011 langCxx20OrLater()));
4015 traverse(TK_IgnoreUnlessSpelledInSource
,
4016 returnStmt(forFunction(functionDecl(hasName("func8"))),
4017 hasReturnValue(cxxFunctionalCastExpr(
4018 hasSourceExpression(initListExpr()))))),
4019 langCxx20OrLater()));
4023 traverse(TK_IgnoreUnlessSpelledInSource
,
4024 returnStmt(forFunction(functionDecl(hasName("func9"))),
4025 hasReturnValue(cxxFunctionalCastExpr(
4026 hasSourceExpression(initListExpr()))))),
4027 langCxx20OrLater()));
4029 EXPECT_TRUE(matches(
4032 TK_IgnoreUnlessSpelledInSource
,
4033 returnStmt(forFunction(functionDecl(hasName("func10"))),
4034 hasReturnValue(declRefExpr(to(varDecl(hasName("a"))))))),
4035 langCxx20OrLater()));
4039 traverse(TK_IgnoreUnlessSpelledInSource
,
4040 declRefExpr(to(varDecl(hasName("a"))),
4041 hasParent(returnStmt(forFunction(
4042 functionDecl(hasName("func10"))))))),
4043 langCxx20OrLater()));
4045 EXPECT_TRUE(matches(
4048 TK_IgnoreUnlessSpelledInSource
,
4049 returnStmt(forFunction(functionDecl(hasName("func11"))),
4050 hasReturnValue(declRefExpr(to(varDecl(hasName("b"))))))),
4051 langCxx20OrLater()));
4055 traverse(TK_IgnoreUnlessSpelledInSource
,
4056 declRefExpr(to(varDecl(hasName("b"))),
4057 hasParent(returnStmt(forFunction(
4058 functionDecl(hasName("func11"))))))),
4059 langCxx20OrLater()));
4061 EXPECT_TRUE(matches(
4064 TK_IgnoreUnlessSpelledInSource
,
4065 returnStmt(forFunction(functionDecl(hasName("func12"))),
4066 hasReturnValue(declRefExpr(to(varDecl(hasName("c"))))))),
4067 langCxx20OrLater()));
4071 traverse(TK_IgnoreUnlessSpelledInSource
,
4072 declRefExpr(to(varDecl(hasName("c"))),
4073 hasParent(returnStmt(forFunction(
4074 functionDecl(hasName("func12"))))))),
4075 langCxx20OrLater()));
4077 EXPECT_TRUE(matches(
4080 TK_IgnoreUnlessSpelledInSource
,
4081 lambdaExpr(forFunction(functionDecl(hasName("func13"))),
4082 has(compoundStmt(hasDescendant(varDecl(hasName("e"))))),
4083 has(declRefExpr(to(varDecl(hasName("a"))))),
4084 has(varDecl(hasName("b"), hasInitializer(declRefExpr(to(
4085 varDecl(hasName("c"))))))),
4086 has(parmVarDecl(hasName("d"))))),
4087 langCxx20OrLater()));
4091 traverse(TK_IgnoreUnlessSpelledInSource
,
4092 declRefExpr(to(varDecl(hasName("a"))),
4093 hasParent(lambdaExpr(forFunction(
4094 functionDecl(hasName("func13"))))))),
4095 langCxx20OrLater()));
4097 EXPECT_TRUE(matches(
4099 traverse(TK_IgnoreUnlessSpelledInSource
,
4100 varDecl(hasName("b"),
4101 hasInitializer(declRefExpr(to(varDecl(hasName("c"))))),
4102 hasParent(lambdaExpr(
4103 forFunction(functionDecl(hasName("func13"))))))),
4104 langCxx20OrLater()));
4106 EXPECT_TRUE(matches(Code
,
4107 traverse(TK_IgnoreUnlessSpelledInSource
,
4108 compoundStmt(hasParent(lambdaExpr(forFunction(
4109 functionDecl(hasName("func13"))))))),
4110 langCxx20OrLater()));
4112 EXPECT_TRUE(matches(
4114 traverse(TK_IgnoreUnlessSpelledInSource
,
4115 templateTypeParmDecl(hasName("TemplateType"),
4116 hasParent(lambdaExpr(forFunction(
4117 functionDecl(hasName("func14"))))))),
4118 langCxx20OrLater()));
4120 EXPECT_TRUE(matches(
4122 traverse(TK_IgnoreUnlessSpelledInSource
,
4123 lambdaExpr(forFunction(functionDecl(hasName("func14"))),
4124 has(templateTypeParmDecl(hasName("TemplateType"))))),
4125 langCxx20OrLater()));
4127 EXPECT_TRUE(matches(
4129 traverse(TK_IgnoreUnlessSpelledInSource
,
4130 functionDecl(hasName("func14"), hasDescendant(floatLiteral()))),
4131 langCxx20OrLater()));
4133 EXPECT_TRUE(matches(
4135 traverse(TK_IgnoreUnlessSpelledInSource
,
4137 hasDescendant(varDecl(hasName("count")).bind("countVar")),
4139 declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))),
4140 langCxx20OrLater()));
4144 int explicit_captured = 0;
4145 int implicit_captured = 0;
4146 auto l = [&, explicit_captured](int i) {
4147 if (i || explicit_captured || implicit_captured) return;
4152 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, ifStmt())));
4154 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, ifStmt())));
4156 auto lambdaExplicitCapture
= declRefExpr(
4157 to(varDecl(hasName("explicit_captured"))), unless(hasAncestor(ifStmt())));
4158 auto lambdaImplicitCapture
= declRefExpr(
4159 to(varDecl(hasName("implicit_captured"))), unless(hasAncestor(ifStmt())));
4161 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, lambdaExplicitCapture
)));
4162 EXPECT_TRUE(matches(
4163 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, lambdaExplicitCapture
)));
4165 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, lambdaImplicitCapture
)));
4166 EXPECT_FALSE(matches(
4167 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, lambdaImplicitCapture
)));
4174 bool operator==(const S& other)
4189 auto M
= unaryOperator(
4190 hasOperatorName("!"),
4191 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="))));
4193 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4195 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4196 true, {"-std=c++20"}));
4199 auto M
= declRefExpr(to(varDecl(hasName("s1"))));
4201 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4203 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4204 true, {"-std=c++20"}));
4207 auto M
= cxxOperatorCallExpr(hasOverloadedOperatorName("=="));
4209 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4211 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4212 true, {"-std=c++20"}));
4215 auto M
= cxxOperatorCallExpr(hasOverloadedOperatorName("!="));
4217 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4219 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4220 true, {"-std=c++20"}));
4222 auto withDescendants
= [](StringRef lName
, StringRef rName
) {
4223 return stmt(hasDescendant(declRefExpr(to(varDecl(hasName(lName
))))),
4224 hasDescendant(declRefExpr(to(varDecl(hasName(rName
))))));
4227 auto M
= cxxRewrittenBinaryOperator(withDescendants("s1", "s2"));
4229 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4231 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4232 true, {"-std=c++20"}));
4235 auto M
= cxxRewrittenBinaryOperator(
4236 has(declRefExpr(to(varDecl(hasName("s1"))))),
4237 has(declRefExpr(to(varDecl(hasName("s2"))))));
4239 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4241 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4242 true, {"-std=c++20"}));
4245 auto M
= cxxRewrittenBinaryOperator(
4246 hasLHS(expr(hasParent(cxxRewrittenBinaryOperator()))),
4247 hasRHS(expr(hasParent(cxxRewrittenBinaryOperator()))));
4249 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4251 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4252 true, {"-std=c++20"}));
4255 EXPECT_TRUE(matchesConditionally(
4258 cxxRewrittenBinaryOperator(
4259 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4260 isComparisonOperator(),
4261 hasLHS(ignoringImplicit(
4262 declRefExpr(to(varDecl(hasName("s1")))))),
4263 hasRHS(ignoringImplicit(
4264 declRefExpr(to(varDecl(hasName("s2")))))),
4265 hasEitherOperand(ignoringImplicit(
4266 declRefExpr(to(varDecl(hasName("s2")))))),
4267 hasOperands(ignoringImplicit(
4268 declRefExpr(to(varDecl(hasName("s1"))))),
4269 ignoringImplicit(declRefExpr(
4270 to(varDecl(hasName("s2")))))))),
4271 true, {"-std=c++20"}));
4272 EXPECT_TRUE(matchesConditionally(
4274 traverse(TK_IgnoreUnlessSpelledInSource
,
4275 cxxRewrittenBinaryOperator(
4276 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4277 isComparisonOperator(),
4278 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4279 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4280 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4281 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4282 declRefExpr(to(varDecl(hasName("s2"))))))),
4283 true, {"-std=c++20"}));
4288 struct strong_ordering {
4290 constexpr operator int() const { return n; }
4291 static const strong_ordering equal, greater, less;
4293 constexpr strong_ordering strong_ordering::equal = {0};
4294 constexpr strong_ordering strong_ordering::greater = {1};
4295 constexpr strong_ordering strong_ordering::less = {-1};
4298 struct HasSpaceshipMem {
4300 constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
4305 HasSpaceshipMem hs1, hs2;
4309 HasSpaceshipMem hs3, hs4;
4313 HasSpaceshipMem hs5, hs6;
4317 HasSpaceshipMem hs7, hs8;
4321 HasSpaceshipMem hs9, hs10;
4325 HasSpaceshipMem hs11, hs12;
4330 auto withArgs
= [](StringRef lName
, StringRef rName
) {
4331 return cxxOperatorCallExpr(
4332 hasArgument(0, declRefExpr(to(varDecl(hasName(lName
))))),
4333 hasArgument(1, declRefExpr(to(varDecl(hasName(rName
))))));
4336 auto M
= ifStmt(hasCondition(cxxOperatorCallExpr(
4337 hasOverloadedOperatorName("=="), withArgs("hs1", "hs2"))));
4339 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4341 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4342 true, {"-std=c++20"}));
4346 unaryOperator(hasOperatorName("!"),
4347 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4348 withArgs("hs3", "hs4"))));
4350 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4352 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4353 true, {"-std=c++20"}));
4357 unaryOperator(hasOperatorName("!"),
4358 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4359 withArgs("hs3", "hs4"))));
4361 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4363 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4364 true, {"-std=c++20"}));
4367 auto M
= binaryOperator(
4368 hasOperatorName("<"),
4369 hasLHS(hasDescendant(cxxOperatorCallExpr(
4370 hasOverloadedOperatorName("<=>"), withArgs("hs5", "hs6")))),
4371 hasRHS(integerLiteral(equals(0))));
4373 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4375 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4376 true, {"-std=c++20"}));
4379 auto M
= cxxRewrittenBinaryOperator(withDescendants("hs3", "hs4"));
4381 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4383 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4384 true, {"-std=c++20"}));
4387 auto M
= declRefExpr(to(varDecl(hasName("hs3"))));
4389 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4391 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4392 true, {"-std=c++20"}));
4395 auto M
= cxxRewrittenBinaryOperator(has(
4396 unaryOperator(hasOperatorName("!"), withDescendants("hs3", "hs4"))));
4398 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4400 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4401 true, {"-std=c++20"}));
4404 auto M
= cxxRewrittenBinaryOperator(
4405 has(declRefExpr(to(varDecl(hasName("hs3"))))),
4406 has(declRefExpr(to(varDecl(hasName("hs4"))))));
4408 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4410 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4411 true, {"-std=c++20"}));
4414 EXPECT_TRUE(matchesConditionally(
4417 cxxRewrittenBinaryOperator(
4418 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4419 isComparisonOperator(),
4420 hasLHS(ignoringImplicit(
4421 declRefExpr(to(varDecl(hasName("hs3")))))),
4422 hasRHS(ignoringImplicit(
4423 declRefExpr(to(varDecl(hasName("hs4")))))),
4424 hasEitherOperand(ignoringImplicit(
4425 declRefExpr(to(varDecl(hasName("hs3")))))),
4426 hasOperands(ignoringImplicit(
4427 declRefExpr(to(varDecl(hasName("hs3"))))),
4428 ignoringImplicit(declRefExpr(
4429 to(varDecl(hasName("hs4")))))))),
4430 true, {"-std=c++20"}));
4431 EXPECT_TRUE(matchesConditionally(
4433 traverse(TK_IgnoreUnlessSpelledInSource
,
4434 cxxRewrittenBinaryOperator(
4435 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4436 isComparisonOperator(),
4437 hasLHS(declRefExpr(to(varDecl(hasName("hs3"))))),
4438 hasRHS(declRefExpr(to(varDecl(hasName("hs4"))))),
4439 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs3"))))),
4440 hasOperands(declRefExpr(to(varDecl(hasName("hs3")))),
4441 declRefExpr(to(varDecl(hasName("hs4"))))))),
4442 true, {"-std=c++20"}));
4445 EXPECT_TRUE(matchesConditionally(
4448 cxxRewrittenBinaryOperator(
4449 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4450 isComparisonOperator(),
4451 hasLHS(ignoringImplicit(
4452 declRefExpr(to(varDecl(hasName("hs5")))))),
4453 hasRHS(ignoringImplicit(
4454 declRefExpr(to(varDecl(hasName("hs6")))))),
4455 hasEitherOperand(ignoringImplicit(
4456 declRefExpr(to(varDecl(hasName("hs5")))))),
4457 hasOperands(ignoringImplicit(
4458 declRefExpr(to(varDecl(hasName("hs5"))))),
4459 ignoringImplicit(declRefExpr(
4460 to(varDecl(hasName("hs6")))))))),
4461 true, {"-std=c++20"}));
4462 EXPECT_TRUE(matchesConditionally(
4464 traverse(TK_IgnoreUnlessSpelledInSource
,
4465 cxxRewrittenBinaryOperator(
4466 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4467 isComparisonOperator(),
4468 hasLHS(declRefExpr(to(varDecl(hasName("hs5"))))),
4469 hasRHS(declRefExpr(to(varDecl(hasName("hs6"))))),
4470 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs5"))))),
4471 hasOperands(declRefExpr(to(varDecl(hasName("hs5")))),
4472 declRefExpr(to(varDecl(hasName("hs6"))))))),
4473 true, {"-std=c++20"}));
4476 EXPECT_TRUE(matchesConditionally(
4479 cxxRewrittenBinaryOperator(
4480 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4481 isComparisonOperator(),
4482 hasLHS(ignoringImplicit(
4483 declRefExpr(to(varDecl(hasName("hs7")))))),
4484 hasRHS(ignoringImplicit(
4485 declRefExpr(to(varDecl(hasName("hs8")))))),
4486 hasEitherOperand(ignoringImplicit(
4487 declRefExpr(to(varDecl(hasName("hs7")))))),
4488 hasOperands(ignoringImplicit(
4489 declRefExpr(to(varDecl(hasName("hs7"))))),
4490 ignoringImplicit(declRefExpr(
4491 to(varDecl(hasName("hs8")))))))),
4492 true, {"-std=c++20"}));
4493 EXPECT_TRUE(matchesConditionally(
4495 traverse(TK_IgnoreUnlessSpelledInSource
,
4496 cxxRewrittenBinaryOperator(
4497 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4498 isComparisonOperator(),
4499 hasLHS(declRefExpr(to(varDecl(hasName("hs7"))))),
4500 hasRHS(declRefExpr(to(varDecl(hasName("hs8"))))),
4501 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs7"))))),
4502 hasOperands(declRefExpr(to(varDecl(hasName("hs7")))),
4503 declRefExpr(to(varDecl(hasName("hs8"))))))),
4504 true, {"-std=c++20"}));
4507 EXPECT_TRUE(matchesConditionally(
4510 cxxRewrittenBinaryOperator(
4511 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4512 isComparisonOperator(),
4513 hasLHS(ignoringImplicit(
4514 declRefExpr(to(varDecl(hasName("hs9")))))),
4515 hasRHS(ignoringImplicit(
4516 declRefExpr(to(varDecl(hasName("hs10")))))),
4517 hasEitherOperand(ignoringImplicit(
4518 declRefExpr(to(varDecl(hasName("hs9")))))),
4519 hasOperands(ignoringImplicit(
4520 declRefExpr(to(varDecl(hasName("hs9"))))),
4521 ignoringImplicit(declRefExpr(
4522 to(varDecl(hasName("hs10")))))))),
4523 true, {"-std=c++20"}));
4524 EXPECT_TRUE(matchesConditionally(
4526 traverse(TK_IgnoreUnlessSpelledInSource
,
4527 cxxRewrittenBinaryOperator(
4528 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4529 isComparisonOperator(),
4530 hasLHS(declRefExpr(to(varDecl(hasName("hs9"))))),
4531 hasRHS(declRefExpr(to(varDecl(hasName("hs10"))))),
4532 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs9"))))),
4533 hasOperands(declRefExpr(to(varDecl(hasName("hs9")))),
4534 declRefExpr(to(varDecl(hasName("hs10"))))))),
4535 true, {"-std=c++20"}));
4538 EXPECT_TRUE(matchesConditionally(
4541 cxxRewrittenBinaryOperator(
4542 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4543 isComparisonOperator(),
4544 hasLHS(ignoringImplicit(
4545 declRefExpr(to(varDecl(hasName("hs11")))))),
4546 hasRHS(ignoringImplicit(
4547 declRefExpr(to(varDecl(hasName("hs12")))))),
4548 hasEitherOperand(ignoringImplicit(
4549 declRefExpr(to(varDecl(hasName("hs11")))))),
4550 hasOperands(ignoringImplicit(
4551 declRefExpr(to(varDecl(hasName("hs11"))))),
4552 ignoringImplicit(declRefExpr(
4553 to(varDecl(hasName("hs12")))))))),
4554 true, {"-std=c++20"}));
4555 EXPECT_TRUE(matchesConditionally(
4558 TK_IgnoreUnlessSpelledInSource
,
4559 cxxRewrittenBinaryOperator(
4560 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4561 isComparisonOperator(),
4562 hasLHS(declRefExpr(to(varDecl(hasName("hs11"))))),
4563 hasRHS(declRefExpr(to(varDecl(hasName("hs12"))))),
4564 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs11"))))),
4565 hasOperands(declRefExpr(to(varDecl(hasName("hs11")))),
4566 declRefExpr(to(varDecl(hasName("hs12"))))))),
4567 true, {"-std=c++20"}));
4575 bool operator==(const S& other) const
4582 bool operator==(const HasOpEqMem&) const { return true; }
4585 struct HasOpEqFree {
4587 bool operator==(const HasOpEqFree&, const HasOpEqFree&) { return true; }
4621 EXPECT_TRUE(matchesConditionally(
4625 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4626 isComparisonOperator(),
4627 hasLHS(ignoringImplicit(
4628 declRefExpr(to(varDecl(hasName("s1")))))),
4629 hasRHS(ignoringImplicit(
4630 declRefExpr(to(varDecl(hasName("s2")))))),
4631 hasEitherOperand(ignoringImplicit(
4632 declRefExpr(to(varDecl(hasName("s2")))))),
4633 hasOperands(ignoringImplicit(
4634 declRefExpr(to(varDecl(hasName("s1"))))),
4635 ignoringImplicit(declRefExpr(
4636 to(varDecl(hasName("s2")))))))),
4637 true, {"-std=c++20"}));
4638 EXPECT_TRUE(matchesConditionally(
4640 traverse(TK_AsIs
, binaryOperation(hasOperatorName("!="),
4641 hasLHS(ignoringImplicit(declRefExpr(
4642 to(varDecl(hasName("i1")))))),
4643 hasRHS(ignoringImplicit(declRefExpr(
4644 to(varDecl(hasName("i2")))))))),
4645 true, {"-std=c++20"}));
4646 EXPECT_TRUE(matchesConditionally(
4648 traverse(TK_AsIs
, binaryOperation(hasOperatorName("=="),
4649 hasLHS(ignoringImplicit(declRefExpr(
4650 to(varDecl(hasName("M1")))))),
4651 hasRHS(ignoringImplicit(declRefExpr(
4652 to(varDecl(hasName("M2")))))))),
4653 true, {"-std=c++20"}));
4654 EXPECT_TRUE(matchesConditionally(
4656 traverse(TK_AsIs
, binaryOperation(hasOperatorName("=="),
4657 hasLHS(ignoringImplicit(declRefExpr(
4658 to(varDecl(hasName("F1")))))),
4659 hasRHS(ignoringImplicit(declRefExpr(
4660 to(varDecl(hasName("F2")))))))),
4661 true, {"-std=c++20"}));
4662 EXPECT_TRUE(matchesConditionally(
4664 traverse(TK_IgnoreUnlessSpelledInSource
,
4666 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4667 isComparisonOperator(),
4668 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4669 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4670 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4671 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4672 declRefExpr(to(varDecl(hasName("s2"))))))),
4673 true, {"-std=c++20"}));
4674 EXPECT_TRUE(matchesConditionally(
4677 TK_IgnoreUnlessSpelledInSource
,
4678 binaryOperation(hasOperatorName("!="),
4679 hasLHS(declRefExpr(to(varDecl(hasName("i1"))))),
4680 hasRHS(declRefExpr(to(varDecl(hasName("i2"))))))),
4681 true, {"-std=c++20"}));
4682 EXPECT_TRUE(matchesConditionally(
4685 TK_IgnoreUnlessSpelledInSource
,
4686 binaryOperation(hasOperatorName("=="),
4687 hasLHS(declRefExpr(to(varDecl(hasName("M1"))))),
4688 hasRHS(declRefExpr(to(varDecl(hasName("M2"))))))),
4689 true, {"-std=c++20"}));
4690 EXPECT_TRUE(matchesConditionally(
4693 TK_IgnoreUnlessSpelledInSource
,
4694 binaryOperation(hasOperatorName("=="),
4695 hasLHS(declRefExpr(to(varDecl(hasName("F1"))))),
4696 hasRHS(declRefExpr(to(varDecl(hasName("F2"))))))),
4697 true, {"-std=c++20"}));
4701 TEST(IgnoringImpCasts
, PathologicalLambda
) {
4703 // Test that deeply nested lambdas are not a performance penalty
4704 StringRef Code
= R
"cpp(
4769 EXPECT_TRUE(matches(Code
, integerLiteral(equals(42))));
4770 EXPECT_TRUE(matches(Code
, functionDecl(hasDescendant(integerLiteral(equals(42))))));
4773 TEST(IgnoringImpCasts
, MatchesImpCasts
) {
4774 // This test checks that ignoringImpCasts matches when implicit casts are
4775 // present and its inner matcher alone does not match.
4776 // Note that this test creates an implicit const cast.
4777 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4778 varDecl(hasInitializer(ignoringImpCasts(
4779 declRefExpr(to(varDecl(hasName("x")))))))));
4780 // This test creates an implict cast from int to char.
4781 EXPECT_TRUE(matches("char x = 0;",
4782 varDecl(hasInitializer(ignoringImpCasts(
4783 integerLiteral(equals(0)))))));
4786 TEST(IgnoringImpCasts
, DoesNotMatchIncorrectly
) {
4787 // These tests verify that ignoringImpCasts does not match if the inner
4788 // matcher does not match.
4789 // Note that the first test creates an implicit const cast.
4790 EXPECT_TRUE(notMatches("int x; const int y = x;",
4791 varDecl(hasInitializer(ignoringImpCasts(
4792 unless(anything()))))));
4793 EXPECT_TRUE(notMatches("int x; int y = x;",
4794 varDecl(hasInitializer(ignoringImpCasts(
4795 unless(anything()))))));
4797 // These tests verify that ignoringImplictCasts does not look through explicit
4798 // casts or parentheses.
4799 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4800 varDecl(hasInitializer(ignoringImpCasts(
4801 integerLiteral())))));
4802 EXPECT_TRUE(notMatches(
4805 varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))))));
4806 EXPECT_TRUE(notMatches("float i = (float)0;",
4807 varDecl(hasInitializer(ignoringImpCasts(
4808 integerLiteral())))));
4809 EXPECT_TRUE(notMatches("float i = float(0);",
4810 varDecl(hasInitializer(ignoringImpCasts(
4811 integerLiteral())))));
4814 TEST(IgnoringImpCasts
, MatchesWithoutImpCasts
) {
4815 // This test verifies that expressions that do not have implicit casts
4816 // still match the inner matcher.
4817 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4818 varDecl(hasInitializer(ignoringImpCasts(
4819 declRefExpr(to(varDecl(hasName("x")))))))));
4822 TEST(IgnoringParenCasts
, MatchesParenCasts
) {
4823 // This test checks that ignoringParenCasts matches when parentheses and/or
4824 // casts are present and its inner matcher alone does not match.
4825 EXPECT_TRUE(matches("int x = (0);",
4826 varDecl(hasInitializer(ignoringParenCasts(
4827 integerLiteral(equals(0)))))));
4828 EXPECT_TRUE(matches("int x = (((((0)))));",
4829 varDecl(hasInitializer(ignoringParenCasts(
4830 integerLiteral(equals(0)))))));
4832 // This test creates an implict cast from int to char in addition to the
4834 EXPECT_TRUE(matches("char x = (0);",
4835 varDecl(hasInitializer(ignoringParenCasts(
4836 integerLiteral(equals(0)))))));
4838 EXPECT_TRUE(matches("char x = (char)0;",
4839 varDecl(hasInitializer(ignoringParenCasts(
4840 integerLiteral(equals(0)))))));
4841 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
4842 varDecl(hasInitializer(ignoringParenCasts(
4843 integerLiteral(equals(0)))))));
4846 TEST(IgnoringParenCasts
, MatchesWithoutParenCasts
) {
4847 // This test verifies that expressions that do not have any casts still match.
4848 EXPECT_TRUE(matches("int x = 0;",
4849 varDecl(hasInitializer(ignoringParenCasts(
4850 integerLiteral(equals(0)))))));
4853 TEST(IgnoringParenCasts
, DoesNotMatchIncorrectly
) {
4854 // These tests verify that ignoringImpCasts does not match if the inner
4855 // matcher does not match.
4856 EXPECT_TRUE(notMatches("int x = ((0));",
4857 varDecl(hasInitializer(ignoringParenCasts(
4858 unless(anything()))))));
4860 // This test creates an implicit cast from int to char in addition to the
4862 EXPECT_TRUE(notMatches("char x = ((0));",
4863 varDecl(hasInitializer(ignoringParenCasts(
4864 unless(anything()))))));
4866 EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
4867 varDecl(hasInitializer(ignoringParenCasts(
4868 unless(anything()))))));
4871 TEST(IgnoringParenAndImpCasts
, MatchesParenImpCasts
) {
4872 // This test checks that ignoringParenAndImpCasts matches when
4873 // parentheses and/or implicit casts are present and its inner matcher alone
4875 // Note that this test creates an implicit const cast.
4876 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4877 varDecl(hasInitializer(ignoringParenImpCasts(
4878 declRefExpr(to(varDecl(hasName("x")))))))));
4879 // This test creates an implicit cast from int to char.
4880 EXPECT_TRUE(matches("const char x = (0);",
4881 varDecl(hasInitializer(ignoringParenImpCasts(
4882 integerLiteral(equals(0)))))));
4885 TEST(IgnoringParenAndImpCasts
, MatchesWithoutParenImpCasts
) {
4886 // This test verifies that expressions that do not have parentheses or
4887 // implicit casts still match.
4888 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4889 varDecl(hasInitializer(ignoringParenImpCasts(
4890 declRefExpr(to(varDecl(hasName("x")))))))));
4891 EXPECT_TRUE(matches("int x = 0;",
4892 varDecl(hasInitializer(ignoringParenImpCasts(
4893 integerLiteral(equals(0)))))));
4896 TEST(IgnoringParenAndImpCasts
, DoesNotMatchIncorrectly
) {
4897 // These tests verify that ignoringParenImpCasts does not match if
4898 // the inner matcher does not match.
4899 // This test creates an implicit cast.
4900 EXPECT_TRUE(notMatches("char c = ((3));",
4901 varDecl(hasInitializer(ignoringParenImpCasts(
4902 unless(anything()))))));
4903 // These tests verify that ignoringParenAndImplictCasts does not look
4904 // through explicit casts.
4905 EXPECT_TRUE(notMatches("float y = (float(0));",
4906 varDecl(hasInitializer(ignoringParenImpCasts(
4907 integerLiteral())))));
4908 EXPECT_TRUE(notMatches("float y = (float)0;",
4909 varDecl(hasInitializer(ignoringParenImpCasts(
4910 integerLiteral())))));
4911 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4912 varDecl(hasInitializer(ignoringParenImpCasts(
4913 integerLiteral())))));
4916 TEST(HasSourceExpression
, MatchesImplicitCasts
) {
4917 EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
4918 "void r() {string a_string; URL url = a_string; }",
4919 traverse(TK_AsIs
, implicitCastExpr(hasSourceExpression(
4920 cxxConstructExpr())))));
4923 TEST(HasSourceExpression
, MatchesExplicitCasts
) {
4925 matches("float x = static_cast<float>(42);",
4926 traverse(TK_AsIs
, explicitCastExpr(hasSourceExpression(
4927 hasDescendant(expr(integerLiteral())))))));
4930 TEST(UsingDeclaration
, MatchesSpecificTarget
) {
4931 EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",
4932 usingDecl(hasAnyUsingShadowDecl(
4933 hasTargetDecl(functionDecl())))));
4934 EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",
4935 usingDecl(hasAnyUsingShadowDecl(
4936 hasTargetDecl(functionDecl())))));
4939 TEST(UsingDeclaration
, ThroughUsingDeclaration
) {
4940 EXPECT_TRUE(matches(
4941 "namespace a { void f(); } using a::f; void g() { f(); }",
4942 declRefExpr(throughUsingDecl(anything()))));
4943 EXPECT_TRUE(notMatches(
4944 "namespace a { void f(); } using a::f; void g() { a::f(); }",
4945 declRefExpr(throughUsingDecl(anything()))));
4948 TEST(SingleDecl
, IsSingleDecl
) {
4949 StatementMatcher SingleDeclStmt
=
4950 declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));
4951 EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt
));
4952 EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt
));
4953 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4957 TEST(DeclStmt
, ContainsDeclaration
) {
4958 DeclarationMatcher MatchesInit
= varDecl(hasInitializer(anything()));
4960 EXPECT_TRUE(matches("void f() {int a = 4;}",
4961 declStmt(containsDeclaration(0, MatchesInit
))));
4962 EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
4963 declStmt(containsDeclaration(0, MatchesInit
),
4964 containsDeclaration(1, MatchesInit
))));
4965 unsigned WrongIndex
= 42;
4966 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4967 declStmt(containsDeclaration(WrongIndex
,
4971 TEST(SwitchCase
, MatchesEachCase
) {
4972 EXPECT_TRUE(notMatches("void x() { switch(42); }",
4973 switchStmt(forEachSwitchCase(caseStmt()))));
4974 EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
4975 switchStmt(forEachSwitchCase(caseStmt()))));
4976 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
4977 switchStmt(forEachSwitchCase(caseStmt()))));
4978 EXPECT_TRUE(notMatches(
4979 "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
4980 ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
4981 EXPECT_TRUE(matches(
4982 "void x() { switch(42) { case 1+1: case 4:; } }",
4983 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4984 constantExpr(has(integerLiteral())))))))));
4985 EXPECT_TRUE(notMatches(
4986 "void x() { switch(42) { case 1+1: case 2+2:; } }",
4987 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4988 constantExpr(has(integerLiteral())))))))));
4989 EXPECT_TRUE(notMatches(
4990 "void x() { switch(42) { case 1 ... 2:; } }",
4991 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4992 constantExpr(has(integerLiteral())))))))));
4993 EXPECT_TRUE(matchAndVerifyResultTrue(
4994 "void x() { switch (42) { case 1: case 2: case 3: default:; } }",
4995 switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
4996 std::make_unique
<VerifyIdIsBoundTo
<CaseStmt
>>("x", 3)));
4999 TEST(Declaration
, HasExplicitSpecifier
) {
5001 EXPECT_TRUE(notMatches("void f();",
5002 functionDecl(hasExplicitSpecifier(constantExpr())),
5003 langCxx20OrLater()));
5005 notMatches("template<bool b> struct S { explicit operator int(); };",
5007 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
5008 langCxx20OrLater()));
5010 notMatches("template<bool b> struct S { explicit(b) operator int(); };",
5012 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
5013 langCxx20OrLater()));
5015 matches("struct S { explicit(true) operator int(); };",
5016 traverse(TK_AsIs
, cxxConversionDecl(hasExplicitSpecifier(
5017 constantExpr(has(cxxBoolLiteral()))))),
5018 langCxx20OrLater()));
5020 matches("struct S { explicit(false) operator int(); };",
5021 traverse(TK_AsIs
, cxxConversionDecl(hasExplicitSpecifier(
5022 constantExpr(has(cxxBoolLiteral()))))),
5023 langCxx20OrLater()));
5025 notMatches("template<bool b> struct S { explicit(b) S(int); };",
5026 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
5027 constantExpr(has(cxxBoolLiteral()))))),
5028 langCxx20OrLater()));
5030 matches("struct S { explicit(true) S(int); };",
5031 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
5032 constantExpr(has(cxxBoolLiteral()))))),
5033 langCxx20OrLater()));
5035 matches("struct S { explicit(false) S(int); };",
5036 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
5037 constantExpr(has(cxxBoolLiteral()))))),
5038 langCxx20OrLater()));
5040 notMatches("template<typename T> struct S { S(int); };"
5041 "template<bool b = true> explicit(b) 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(true) S(int) -> S<int>;",
5048 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
5049 constantExpr(has(cxxBoolLiteral()))))),
5050 langCxx20OrLater()));
5052 matches("template<typename T> struct S { S(int); };"
5053 "explicit(false) S(int) -> S<int>;",
5054 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
5055 constantExpr(has(cxxBoolLiteral()))))),
5056 langCxx20OrLater()));
5059 TEST(ForEachConstructorInitializer
, MatchesInitializers
) {
5060 EXPECT_TRUE(matches(
5061 "struct X { X() : i(42), j(42) {} int i, j; };",
5062 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
5065 TEST(LambdaCapture
, InvalidLambdaCapture
) {
5067 EXPECT_FALSE(matches(
5069 struct A { A()=default; A(A const&)=delete; };
5070 A a; [a]() -> void {}();
5073 traverse(TK_IgnoreUnlessSpelledInSource
,
5074 lambdaExpr(has(lambdaCapture()))),
5075 langCxx11OrLater()));
5078 TEST(ForEachLambdaCapture
, MatchesCaptures
) {
5079 EXPECT_TRUE(matches(
5080 "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
5081 lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));
5082 auto matcher
= lambdaExpr(forEachLambdaCapture(
5083 lambdaCapture(capturesVar(varDecl(hasType(isInteger())))).bind("LC")));
5084 EXPECT_TRUE(matchAndVerifyResultTrue(
5085 "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",
5086 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5087 EXPECT_TRUE(matchAndVerifyResultTrue(
5088 "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "
5090 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5093 TEST(ForEachLambdaCapture
, IgnoreUnlessSpelledInSource
) {
5095 traverse(TK_IgnoreUnlessSpelledInSource
,
5096 lambdaExpr(forEachLambdaCapture(
5097 lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))
5100 notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",
5101 matcher
, langCxx11OrLater()));
5103 notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",
5104 matcher
, langCxx11OrLater()));
5105 EXPECT_TRUE(matchAndVerifyResultTrue(
5110 auto f = [=, &y]() { return x + y + z; };
5113 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
5116 TEST(ForEachLambdaCapture
, MatchImplicitCapturesOnly
) {
5118 lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));
5119 EXPECT_TRUE(matchAndVerifyResultTrue(
5120 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
5121 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5122 EXPECT_TRUE(matchAndVerifyResultTrue(
5123 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
5124 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
5127 TEST(ForEachLambdaCapture
, MatchExplicitCapturesOnly
) {
5128 auto matcher
= lambdaExpr(
5129 forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));
5130 EXPECT_TRUE(matchAndVerifyResultTrue(
5131 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
5132 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
5133 EXPECT_TRUE(matchAndVerifyResultTrue(
5134 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
5135 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
5138 TEST(HasConditionVariableStatement
, DoesNotMatchCondition
) {
5139 EXPECT_TRUE(notMatches(
5140 "void x() { if(true) {} }",
5141 ifStmt(hasConditionVariableStatement(declStmt()))));
5142 EXPECT_TRUE(notMatches(
5143 "void x() { int x; if((x = 42)) {} }",
5144 ifStmt(hasConditionVariableStatement(declStmt()))));
5147 TEST(HasConditionVariableStatement
, MatchesConditionVariables
) {
5148 EXPECT_TRUE(matches(
5149 "void x() { if(int* a = 0) {} }",
5150 ifStmt(hasConditionVariableStatement(declStmt()))));
5153 TEST(ForEach
, BindsOneNode
) {
5154 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
5155 recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),
5156 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("x", 1)));
5159 TEST(ForEach
, BindsMultipleNodes
) {
5160 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",
5161 recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),
5162 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 3)));
5165 TEST(ForEach
, BindsRecursiveCombinations
) {
5166 EXPECT_TRUE(matchAndVerifyResultTrue(
5167 "class C { class D { int x; int y; }; class E { int y; int z; }; };",
5168 recordDecl(hasName("C"),
5169 forEach(recordDecl(forEach(fieldDecl().bind("f"))))),
5170 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 4)));
5173 TEST(ForEach
, DoesNotIgnoreImplicit
) {
5174 StringRef Code
= R
"cpp(
5182 EXPECT_TRUE(matchAndVerifyResultFalse(
5183 Code
, binaryOperator(forEach(declRefExpr().bind("dre"))),
5184 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 0)));
5186 EXPECT_TRUE(matchAndVerifyResultTrue(
5188 binaryOperator(forEach(
5189 implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))),
5190 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
5192 EXPECT_TRUE(matchAndVerifyResultTrue(
5195 forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))),
5196 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
5198 EXPECT_TRUE(matchAndVerifyResultTrue(
5200 traverse(TK_IgnoreUnlessSpelledInSource
,
5201 binaryOperator(forEach(declRefExpr().bind("dre")))),
5202 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
5205 TEST(ForEachDescendant
, BindsOneNode
) {
5206 EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",
5207 recordDecl(hasName("C"),
5208 forEachDescendant(fieldDecl(hasName("x")).bind("x"))),
5209 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("x", 1)));
5212 TEST(ForEachDescendant
, NestedForEachDescendant
) {
5213 DeclarationMatcher m
= recordDecl(
5214 isDefinition(), decl().bind("x"), hasName("C"));
5215 EXPECT_TRUE(matchAndVerifyResultTrue(
5216 "class A { class B { class C {}; }; };",
5217 recordDecl(hasName("A"), anyOf(m
, forEachDescendant(m
))),
5218 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", "C")));
5220 // Check that a partial match of 'm' that binds 'x' in the
5221 // first part of anyOf(m, anything()) will not overwrite the
5222 // binding created by the earlier binding in the hasDescendant.
5223 EXPECT_TRUE(matchAndVerifyResultTrue(
5224 "class A { class B { class C {}; }; };",
5225 recordDecl(hasName("A"), allOf(hasDescendant(m
), anyOf(m
, anything()))),
5226 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", "C")));
5229 TEST(ForEachDescendant
, BindsMultipleNodes
) {
5230 EXPECT_TRUE(matchAndVerifyResultTrue(
5231 "class C { class D { int x; int y; }; "
5232 " class E { class F { int y; int z; }; }; };",
5233 recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),
5234 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 4)));
5237 TEST(ForEachDescendant
, BindsRecursiveCombinations
) {
5238 EXPECT_TRUE(matchAndVerifyResultTrue(
5239 "class C { class D { "
5240 " class E { class F { class G { int y; int z; }; }; }; }; };",
5241 recordDecl(hasName("C"), forEachDescendant(recordDecl(
5242 forEachDescendant(fieldDecl().bind("f"))))),
5243 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 8)));
5246 TEST(ForEachDescendant
, BindsCombinations
) {
5247 EXPECT_TRUE(matchAndVerifyResultTrue(
5248 "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "
5250 compoundStmt(forEachDescendant(ifStmt().bind("if")),
5251 forEachDescendant(whileStmt().bind("while"))),
5252 std::make_unique
<VerifyIdIsBoundTo
<IfStmt
>>("if", 6)));
5255 TEST(ForEachTemplateArgument
, OnFunctionDecl
) {
5256 const std::string Code
= R
"(
5257 template <typename T, typename U> void f(T, U) {}
5263 EXPECT_TRUE(matches(
5264 Code
, functionDecl(forEachTemplateArgument(refersToType(builtinType()))),
5265 langCxx11OrLater()));
5267 functionDecl(forEachTemplateArgument(
5268 templateArgument(refersToType(builtinType().bind("BT")))
5272 EXPECT_TRUE(matchAndVerifyResultTrue(
5274 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("FN", 2)));
5275 EXPECT_TRUE(matchAndVerifyResultTrue(
5277 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgument
>>("TA", 2)));
5278 EXPECT_TRUE(matchAndVerifyResultTrue(
5280 std::make_unique
<VerifyIdIsBoundTo
<BuiltinType
>>("BT", 2)));
5283 TEST(ForEachTemplateArgument
, OnClassTemplateSpecialization
) {
5284 const std::string Code
= R
"(
5285 template <typename T, unsigned N, unsigned M>
5288 static constexpr unsigned R = 2;
5290 Matrix<int, R * 2, R * 4> M;
5292 EXPECT_TRUE(matches(
5293 Code
, templateSpecializationType(forEachTemplateArgument(isExpr(expr()))),
5294 langCxx11OrLater()));
5295 auto matcher
= templateSpecializationType(
5296 forEachTemplateArgument(
5297 templateArgument(isExpr(expr().bind("E"))).bind("TA")))
5300 EXPECT_TRUE(matchAndVerifyResultTrue(
5302 std::make_unique
<VerifyIdIsBoundTo
<TemplateSpecializationType
>>("TST",
5304 EXPECT_TRUE(matchAndVerifyResultTrue(
5306 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgument
>>("TA", 2)));
5307 EXPECT_TRUE(matchAndVerifyResultTrue(
5308 Code
, matcher
, std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("E", 2)));
5311 TEST(Has
, DoesNotDeleteBindings
) {
5312 EXPECT_TRUE(matchAndVerifyResultTrue(
5313 "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),
5314 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5317 TEST(TemplateArgumentLoc
, Matches
) {
5318 EXPECT_TRUE(matchAndVerifyResultTrue(
5320 template <typename A, int B, template <typename> class C> class X {};
5323 template <typename> class C {};
5326 templateArgumentLoc().bind("x"),
5327 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgumentLoc
>>("x", 3)));
5330 TEST(LoopingMatchers
, DoNotOverwritePreviousMatchResultOnFailure
) {
5331 // Those matchers cover all the cases where an inner matcher is called
5332 // and there is not a 1:1 relationship between the match of the outer
5333 // matcher and the match of the inner matcher.
5334 // The pattern to look for is:
5335 // ... return InnerMatcher.matches(...); ...
5336 // In which case no special handling is needed.
5338 // On the other hand, if there are multiple alternative matches
5339 // (for example forEach*) or matches might be discarded (for example has*)
5340 // the implementation must make sure that the discarded matches do not
5341 // affect the bindings.
5342 // When new such matchers are added, add a test here that:
5343 // - matches a simple node, and binds it as the first thing in the matcher:
5344 // recordDecl(decl().bind("x"), hasName("X")))
5345 // - uses the matcher under test afterwards in a way that not the first
5346 // alternative is matched; for anyOf, that means the first branch
5347 // would need to return false; for hasAncestor, it means that not
5348 // the direct parent matches the inner matcher.
5350 EXPECT_TRUE(matchAndVerifyResultTrue(
5351 "class X { int y; };",
5353 recordDecl().bind("x"), hasName("::X"),
5354 anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),
5355 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("x", 1)));
5356 EXPECT_TRUE(matchAndVerifyResultTrue(
5357 "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),
5358 anyOf(unless(anything()), anything())),
5359 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("x", 1)));
5360 EXPECT_TRUE(matchAndVerifyResultTrue(
5361 "template<typename T1, typename T2> class X {}; X<float, int> x;",
5362 classTemplateSpecializationDecl(
5364 hasAnyTemplateArgument(refersToType(asString("int")))),
5365 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5366 EXPECT_TRUE(matchAndVerifyResultTrue(
5367 "class X { void f(); void g(); };",
5368 cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
5369 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5370 EXPECT_TRUE(matchAndVerifyResultTrue(
5371 "class X { X() : a(1), b(2) {} double a; int b; };",
5372 recordDecl(decl().bind("x"),
5373 has(cxxConstructorDecl(
5374 hasAnyConstructorInitializer(forField(hasName("b")))))),
5375 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5376 EXPECT_TRUE(matchAndVerifyResultTrue(
5377 "void x(int, int) { x(0, 42); }",
5378 callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),
5379 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("x", 1)));
5380 EXPECT_TRUE(matchAndVerifyResultTrue(
5381 "void x(int, int y) {}",
5382 functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),
5383 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5384 EXPECT_TRUE(matchAndVerifyResultTrue(
5385 "void x() { return; if (true) {} }",
5386 functionDecl(decl().bind("x"),
5387 has(compoundStmt(hasAnySubstatement(ifStmt())))),
5388 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5389 EXPECT_TRUE(matchAndVerifyResultTrue(
5390 "namespace X { void b(int); void b(); }"
5392 usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(
5393 functionDecl(parameterCountIs(1))))),
5394 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5395 EXPECT_TRUE(matchAndVerifyResultTrue(
5396 "class A{}; class B{}; class C : B, A {};",
5397 cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A")),
5398 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5399 EXPECT_TRUE(matchAndVerifyResultTrue(
5400 "class A{}; typedef A B; typedef A C; typedef A D;"
5402 cxxRecordDecl(decl().bind("x"), isDerivedFrom("C")),
5403 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5404 EXPECT_TRUE(matchAndVerifyResultTrue(
5405 "class A { class B { void f() {} }; };",
5406 functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5407 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5408 EXPECT_TRUE(matchAndVerifyResultTrue(
5409 "template <typename T> struct A { struct B {"
5410 " void f() { if(true) {} }"
5412 "void t() { A<int>::B b; b.f(); }",
5413 ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5414 std::make_unique
<VerifyIdIsBoundTo
<Stmt
>>("x", 2)));
5415 EXPECT_TRUE(matchAndVerifyResultTrue(
5417 recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),
5418 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5419 EXPECT_TRUE(matchAndVerifyResultTrue(
5420 "class A { A() : s(), i(42) {} const char *s; int i; };",
5421 cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),
5422 forEachConstructorInitializer(forField(hasName("i")))),
5423 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5426 TEST(ForEachDescendant
, BindsCorrectNodes
) {
5427 EXPECT_TRUE(matchAndVerifyResultTrue(
5428 "class C { void f(); int i; };",
5429 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5430 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("decl", 1)));
5431 EXPECT_TRUE(matchAndVerifyResultTrue(
5432 "class C { void f() {} int i; };",
5433 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5434 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("decl", 1)));
5437 TEST(FindAll
, BindsNodeOnMatch
) {
5438 EXPECT_TRUE(matchAndVerifyResultTrue(
5440 recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),
5441 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("v", 1)));
5444 TEST(FindAll
, BindsDescendantNodeOnMatch
) {
5445 EXPECT_TRUE(matchAndVerifyResultTrue(
5446 "class A { int a; int b; };",
5447 recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),
5448 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("v", 2)));
5451 TEST(FindAll
, BindsNodeAndDescendantNodesOnOneMatch
) {
5452 EXPECT_TRUE(matchAndVerifyResultTrue(
5453 "class A { int a; int b; };",
5454 recordDecl(hasName("::A"),
5455 findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),
5456 fieldDecl().bind("v"))))),
5457 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("v", 3)));
5459 EXPECT_TRUE(matchAndVerifyResultTrue(
5460 "class A { class B {}; class C {}; };",
5461 recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),
5462 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("v", 3)));
5465 TEST(HasAncenstor
, MatchesDeclarationAncestors
) {
5466 EXPECT_TRUE(matches(
5467 "class A { class B { class C {}; }; };",
5468 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));
5471 TEST(HasAncenstor
, FailsIfNoAncestorMatches
) {
5472 EXPECT_TRUE(notMatches(
5473 "class A { class B { class C {}; }; };",
5474 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));
5477 TEST(HasAncestor
, MatchesDeclarationsThatGetVisitedLater
) {
5478 EXPECT_TRUE(matches(
5479 "class A { class B { void f() { C c; } class C {}; }; };",
5480 varDecl(hasName("c"), hasType(recordDecl(hasName("C"),
5481 hasAncestor(recordDecl(hasName("A"))))))));
5484 TEST(HasAncenstor
, MatchesStatementAncestors
) {
5485 EXPECT_TRUE(matches(
5486 "void f() { if (true) { while (false) { 42; } } }",
5487 integerLiteral(equals(42), hasAncestor(ifStmt()))));
5490 TEST(HasAncestor
, DrillsThroughDifferentHierarchies
) {
5491 EXPECT_TRUE(matches(
5492 "void f() { if (true) { int x = 42; } }",
5493 integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));
5496 TEST(HasAncestor
, BindsRecursiveCombinations
) {
5497 EXPECT_TRUE(matchAndVerifyResultTrue(
5498 "class C { class D { class E { class F { int y; }; }; }; };",
5499 fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),
5500 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("r", 1)));
5503 TEST(HasAncestor
, BindsCombinationsWithHasDescendant
) {
5504 EXPECT_TRUE(matchAndVerifyResultTrue(
5505 "class C { class D { class E { class F { int y; }; }; }; };",
5506 fieldDecl(hasAncestor(
5508 hasDescendant(recordDecl(isDefinition(),
5509 hasAncestor(recordDecl())))
5512 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("d", "E")));
5515 TEST(HasAncestor
, MatchesClosestAncestor
) {
5516 EXPECT_TRUE(matchAndVerifyResultTrue(
5517 "template <typename T> struct C {"
5519 " struct I { void g(T) { int x; } } i; i.g(42);"
5522 "template struct C<int>;",
5523 varDecl(hasName("x"),
5524 hasAncestor(functionDecl(hasParameter(
5525 0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),
5526 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("f", "g", 2)));
5529 TEST(HasAncestor
, MatchesInTemplateInstantiations
) {
5530 EXPECT_TRUE(matches(
5531 "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
5533 fieldDecl(hasType(asString("int")),
5534 hasAncestor(recordDecl(hasName("A"))))));
5537 TEST(HasAncestor
, MatchesInImplicitCode
) {
5538 EXPECT_TRUE(matches(
5539 "struct X {}; struct A { A() {} X x; };",
5541 hasAnyConstructorInitializer(withInitializer(expr(
5542 hasAncestor(recordDecl(hasName("A")))))))));
5545 TEST(HasParent
, MatchesOnlyParent
) {
5546 EXPECT_TRUE(matches(
5547 "void f() { if (true) { int x = 42; } }",
5548 compoundStmt(hasParent(ifStmt()))));
5549 EXPECT_TRUE(notMatches(
5550 "void f() { for (;;) { int x = 42; } }",
5551 compoundStmt(hasParent(ifStmt()))));
5552 EXPECT_TRUE(notMatches(
5553 "void f() { if (true) for (;;) { int x = 42; } }",
5554 compoundStmt(hasParent(ifStmt()))));
5557 TEST(MatcherMemoize
, HasParentDiffersFromHas
) {
5558 // Test introduced after detecting a bug in memoization
5559 constexpr auto code
= "void f() { throw 1; }";
5560 EXPECT_TRUE(notMatches(
5562 cxxThrowExpr(hasParent(expr()))));
5563 EXPECT_TRUE(matches(
5565 cxxThrowExpr(has(expr()))));
5566 EXPECT_TRUE(matches(
5568 cxxThrowExpr(anyOf(hasParent(expr()), has(expr())))));
5571 TEST(MatcherMemoize
, HasDiffersFromHasDescendant
) {
5572 // Test introduced after detecting a bug in memoization
5573 constexpr auto code
= "void f() { throw 1+1; }";
5574 EXPECT_TRUE(notMatches(
5576 cxxThrowExpr(has(integerLiteral()))));
5577 EXPECT_TRUE(matches(
5579 cxxThrowExpr(hasDescendant(integerLiteral()))));
5581 notMatches(code
, cxxThrowExpr(allOf(hasDescendant(integerLiteral()),
5582 has(integerLiteral())))));
5584 TEST(HasAncestor
, MatchesAllAncestors
) {
5585 EXPECT_TRUE(matches(
5586 "template <typename T> struct C { static void f() { 42; } };"
5587 "void t() { C<int>::f(); }",
5591 hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
5592 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
5595 TEST(HasAncestor
, ImplicitArrayCopyCtorDeclRefExpr
) {
5596 EXPECT_TRUE(matches("struct MyClass {\n"
5598 " static MyClass Create() { return MyClass(); }\n"
5600 declRefExpr(to(decl(hasAncestor(decl()))))));
5603 TEST(HasAncestor
, AnonymousUnionMemberExpr
) {
5604 EXPECT_TRUE(matches("int F() {\n"
5605 " union { int i; };\n"
5608 memberExpr(member(hasAncestor(decl())))));
5609 EXPECT_TRUE(matches("void f() {\n"
5611 " struct { int a; int b; };\n"
5615 memberExpr(member(hasAncestor(decl())))));
5616 EXPECT_TRUE(matches("void f() {\n"
5618 " struct { int a; int b; };\n"
5622 declRefExpr(to(decl(hasAncestor(decl()))))));
5624 TEST(HasAncestor
, NonParmDependentTemplateParmVarDeclRefExpr
) {
5625 EXPECT_TRUE(matches("struct PartitionAllocator {\n"
5626 " template<typename T>\n"
5627 " static int quantizedSize(int count) {\n"
5630 " void f() { quantizedSize<int>(10); }\n"
5632 declRefExpr(to(decl(hasAncestor(decl()))))));
5635 TEST(HasAncestor
, AddressOfExplicitSpecializationFunction
) {
5636 EXPECT_TRUE(matches("template <class T> void f();\n"
5637 "template <> void f<int>();\n"
5638 "void (*get_f())() { return f<int>; }\n",
5639 declRefExpr(to(decl(hasAncestor(decl()))))));
5642 TEST(HasParent
, MatchesAllParents
) {
5643 EXPECT_TRUE(matches(
5644 "template <typename T> struct C { static void f() { 42; } };"
5645 "void t() { C<int>::f(); }",
5648 hasParent(compoundStmt(hasParent(functionDecl(
5649 hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));
5651 matches("template <typename T> struct C { static void f() { 42; } };"
5652 "void t() { C<int>::f(); }",
5655 hasParent(compoundStmt(hasParent(functionDecl(hasParent(
5656 cxxRecordDecl(unless(isTemplateInstantiation()))))))))));
5657 EXPECT_TRUE(matches(
5658 "template <typename T> struct C { static void f() { 42; } };"
5659 "void t() { C<int>::f(); }",
5660 integerLiteral(equals(42),
5661 hasParent(compoundStmt(
5662 allOf(hasParent(functionDecl(hasParent(
5663 cxxRecordDecl(isTemplateInstantiation())))),
5664 hasParent(functionDecl(hasParent(cxxRecordDecl(
5665 unless(isTemplateInstantiation())))))))))));
5667 notMatches("template <typename T> struct C { static void f() {} };"
5668 "void t() { C<int>::f(); }",
5669 compoundStmt(hasParent(recordDecl()))));
5672 TEST(HasParent
, NoDuplicateParents
) {
5673 class HasDuplicateParents
: public BoundNodesCallback
{
5675 bool run(const BoundNodes
*Nodes
, ASTContext
*Context
) override
{
5676 const Stmt
*Node
= Nodes
->getNodeAs
<Stmt
>("node");
5677 std::set
<const void *> Parents
;
5678 for (const auto &Parent
: Context
->getParents(*Node
)) {
5679 if (!Parents
.insert(Parent
.getMemoizationData()).second
) {
5686 EXPECT_FALSE(matchAndVerifyResultTrue(
5687 "template <typename T> int Foo() { return 1 + 2; }\n"
5688 "int x = Foo<int>() + Foo<unsigned>();",
5689 stmt().bind("node"), std::make_unique
<HasDuplicateParents
>()));
5692 TEST(HasAnyBase
, BindsInnerBoundNodes
) {
5693 EXPECT_TRUE(matchAndVerifyResultTrue(
5694 "struct Inner {}; struct Proxy : Inner {}; struct Main : public "
5696 cxxRecordDecl(hasName("Main"),
5697 hasAnyBase(cxxBaseSpecifier(hasType(
5698 cxxRecordDecl(hasName("Inner")).bind("base-class")))))
5700 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("base-class",
5704 TEST(TypeMatching
, PointeeTypes
) {
5705 EXPECT_TRUE(matches("int b; int &a = b;",
5706 referenceType(pointee(builtinType()))));
5707 EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));
5709 EXPECT_TRUE(matches("int *a;",
5710 loc(pointerType(pointee(builtinType())))));
5712 EXPECT_TRUE(matches(
5714 pointerType(pointee(isConstQualified(), builtinType()))));
5715 EXPECT_TRUE(notMatches(
5717 pointerType(pointee(isConstQualified(), builtinType()))));
5720 TEST(ElaboratedTypeNarrowing
, hasQualifier
) {
5721 EXPECT_TRUE(matches(
5728 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5729 EXPECT_TRUE(notMatches(
5734 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5735 EXPECT_TRUE(notMatches(
5738 elaboratedType(hasQualifier(nestedNameSpecifier()))));
5741 TEST(ElaboratedTypeNarrowing
, namesType
) {
5742 EXPECT_TRUE(matches(
5749 elaboratedType(elaboratedType(namesType(recordType(
5750 hasDeclaration(namedDecl(hasName("D")))))))));
5751 EXPECT_TRUE(notMatches(
5756 elaboratedType(elaboratedType(namesType(typedefType())))));
5759 TEST(NNS
, BindsNestedNameSpecifiers
) {
5760 EXPECT_TRUE(matchAndVerifyResultTrue(
5761 "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
5762 nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
5763 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>(
5764 "nns", "ns::struct E::")));
5767 TEST(NNS
, BindsNestedNameSpecifierLocs
) {
5768 EXPECT_TRUE(matchAndVerifyResultTrue(
5769 "namespace ns { struct B {}; } ns::B b;",
5770 loc(nestedNameSpecifier()).bind("loc"),
5771 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("loc", 1)));
5774 TEST(NNS
, DescendantsOfNestedNameSpecifiers
) {
5775 StringRef Fragment
=
5776 "namespace a { struct A { struct B { struct C {}; }; }; };"
5777 "void f() { a::A::B::C c; }";
5778 EXPECT_TRUE(matches(
5780 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5781 hasDescendant(nestedNameSpecifier(
5782 specifiesNamespace(hasName("a")))))));
5783 EXPECT_TRUE(notMatches(
5785 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5786 has(nestedNameSpecifier(
5787 specifiesNamespace(hasName("a")))))));
5788 EXPECT_TRUE(matches(
5790 nestedNameSpecifier(specifiesType(asString("struct a::A")),
5791 has(nestedNameSpecifier(
5792 specifiesNamespace(hasName("a")))))));
5794 // Not really useful because a NestedNameSpecifier can af at most one child,
5795 // but to complete the interface.
5796 EXPECT_TRUE(matchAndVerifyResultTrue(
5798 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5799 forEach(nestedNameSpecifier().bind("x"))),
5800 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>("x", 1)));
5803 TEST(NNS
, NestedNameSpecifiersAsDescendants
) {
5804 StringRef Fragment
=
5805 "namespace a { struct A { struct B { struct C {}; }; }; };"
5806 "void f() { a::A::B::C c; }";
5807 EXPECT_TRUE(matches(
5809 decl(hasDescendant(nestedNameSpecifier(specifiesType(
5810 asString("struct a::A")))))));
5811 EXPECT_TRUE(matchAndVerifyResultTrue(
5813 functionDecl(hasName("f"),
5814 forEachDescendant(nestedNameSpecifier().bind("x"))),
5815 // Nested names: a, a::A and a::A::B.
5816 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>("x", 3)));
5819 TEST(NNSLoc
, DescendantsOfNestedNameSpecifierLocs
) {
5820 StringRef Fragment
=
5821 "namespace a { struct A { struct B { struct C {}; }; }; };"
5822 "void f() { a::A::B::C c; }";
5823 EXPECT_TRUE(matches(
5825 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5826 hasDescendant(loc(nestedNameSpecifier(
5827 specifiesNamespace(hasName("a"))))))));
5828 EXPECT_TRUE(notMatches(
5830 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5831 has(loc(nestedNameSpecifier(
5832 specifiesNamespace(hasName("a"))))))));
5833 EXPECT_TRUE(matches(
5835 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
5836 has(loc(nestedNameSpecifier(
5837 specifiesNamespace(hasName("a"))))))));
5839 EXPECT_TRUE(matchAndVerifyResultTrue(
5841 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5842 forEach(nestedNameSpecifierLoc().bind("x"))),
5843 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("x", 1)));
5846 TEST(NNSLoc
, NestedNameSpecifierLocsAsDescendants
) {
5847 StringRef Fragment
=
5848 "namespace a { struct A { struct B { struct C {}; }; }; };"
5849 "void f() { a::A::B::C c; }";
5850 EXPECT_TRUE(matches(
5852 decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
5853 asString("struct a::A"))))))));
5854 EXPECT_TRUE(matchAndVerifyResultTrue(
5856 functionDecl(hasName("f"),
5857 forEachDescendant(nestedNameSpecifierLoc().bind("x"))),
5858 // Nested names: a, a::A and a::A::B.
5859 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("x", 3)));
5862 TEST(Attr
, AttrsAsDescendants
) {
5863 StringRef Fragment
= "namespace a { struct [[clang::warn_unused_result]] "
5864 "F{}; [[noreturn]] void foo(); }";
5865 EXPECT_TRUE(matches(Fragment
, namespaceDecl(hasDescendant(attr()))));
5866 EXPECT_TRUE(matchAndVerifyResultTrue(
5868 namespaceDecl(hasName("a"),
5869 forEachDescendant(attr(unless(isImplicit())).bind("x"))),
5870 std::make_unique
<VerifyIdIsBoundTo
<Attr
>>("x", 2)));
5873 TEST(Attr
, ParentsOfAttrs
) {
5874 StringRef Fragment
=
5875 "namespace a { struct [[clang::warn_unused_result]] F{}; }";
5876 EXPECT_TRUE(matches(Fragment
, attr(hasAncestor(namespaceDecl()))));
5879 template <typename T
> class VerifyMatchOnNode
: public BoundNodesCallback
{
5881 VerifyMatchOnNode(StringRef Id
, const internal::Matcher
<T
> &InnerMatcher
,
5883 : Id(Id
), InnerMatcher(InnerMatcher
), InnerId(InnerId
) {}
5885 bool run(const BoundNodes
*Nodes
, ASTContext
*Context
) override
{
5886 const T
*Node
= Nodes
->getNodeAs
<T
>(Id
);
5887 return selectFirst
<T
>(InnerId
, match(InnerMatcher
, *Node
, *Context
)) !=
5893 internal::Matcher
<T
> InnerMatcher
;
5894 std::string InnerId
;
5897 TEST(MatchFinder
, CanMatchDeclarationsRecursively
) {
5898 EXPECT_TRUE(matchAndVerifyResultTrue(
5899 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5900 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5901 "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),
5903 EXPECT_TRUE(matchAndVerifyResultFalse(
5904 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5905 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5906 "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),
5910 TEST(MatchFinder
, CanMatchStatementsRecursively
) {
5911 EXPECT_TRUE(matchAndVerifyResultTrue(
5912 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5913 std::make_unique
<VerifyMatchOnNode
<Stmt
>>(
5914 "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));
5915 EXPECT_TRUE(matchAndVerifyResultFalse(
5916 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5917 std::make_unique
<VerifyMatchOnNode
<Stmt
>>(
5918 "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));
5921 TEST(MatchFinder
, CanMatchSingleNodesRecursively
) {
5922 EXPECT_TRUE(matchAndVerifyResultTrue(
5923 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5924 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5925 "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));
5926 EXPECT_TRUE(matchAndVerifyResultFalse(
5927 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5928 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5929 "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));
5932 TEST(StatementMatcher
, HasReturnValue
) {
5933 StatementMatcher RetVal
= returnStmt(hasReturnValue(binaryOperator()));
5934 EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal
));
5935 EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal
));
5936 EXPECT_FALSE(matches("void F() { return; }", RetVal
));
5939 TEST(StatementMatcher
, ForFunction
) {
5940 StringRef CppString1
= "struct PosVec {"
5941 " PosVec& operator=(const PosVec&) {"
5942 " auto x = [] { return 1; };"
5946 StringRef CppString2
= "void F() {"
5956 returnStmt(forFunction(hasName("operator=")),
5957 has(unaryOperator(hasOperatorName("*"))))));
5961 returnStmt(forFunction(hasName("operator=")),
5962 has(integerLiteral()))));
5966 returnStmt(forFunction(hasName("operator()")),
5967 has(integerLiteral()))));
5968 EXPECT_TRUE(matches(CppString2
, returnStmt(forFunction(hasName("F2")))));
5969 EXPECT_TRUE(notMatches(CppString2
, returnStmt(forFunction(hasName("F")))));
5972 TEST(StatementMatcher
, ForCallable
) {
5973 // These tests are copied over from the forFunction() test above.
5974 StringRef CppString1
= "struct PosVec {"
5975 " PosVec& operator=(const PosVec&) {"
5976 " auto x = [] { return 1; };"
5980 StringRef CppString2
= "void F() {"
5991 returnStmt(forCallable(functionDecl(hasName("operator="))),
5992 has(unaryOperator(hasOperatorName("*"))))));
5996 returnStmt(forCallable(functionDecl(hasName("operator="))),
5997 has(integerLiteral()))));
6001 returnStmt(forCallable(functionDecl(hasName("operator()"))),
6002 has(integerLiteral()))));
6003 EXPECT_TRUE(matches(CppString2
,
6004 returnStmt(forCallable(functionDecl(hasName("F2"))))));
6005 EXPECT_TRUE(notMatches(CppString2
,
6006 returnStmt(forCallable(functionDecl(hasName("F"))))));
6008 StringRef CodeWithDeepCallExpr
= R
"cpp(
6018 auto ForCallableFirst
=
6019 callExpr(forCallable(functionDecl(hasName("Function"))),
6020 callee(functionDecl(hasName("Other")).bind("callee")))
6022 auto ForCallableSecond
=
6023 callExpr(callee(functionDecl(hasName("Other")).bind("callee")),
6024 forCallable(functionDecl(hasName("Function"))))
6026 EXPECT_TRUE(matchAndVerifyResultTrue(
6027 CodeWithDeepCallExpr
, ForCallableFirst
,
6028 std::make_unique
<VerifyIdIsBoundTo
<CallExpr
>>("call")));
6029 EXPECT_TRUE(matchAndVerifyResultTrue(
6030 CodeWithDeepCallExpr
, ForCallableFirst
,
6031 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("callee")));
6032 EXPECT_TRUE(matchAndVerifyResultTrue(
6033 CodeWithDeepCallExpr
, ForCallableSecond
,
6034 std::make_unique
<VerifyIdIsBoundTo
<CallExpr
>>("call")));
6035 EXPECT_TRUE(matchAndVerifyResultTrue(
6036 CodeWithDeepCallExpr
, ForCallableSecond
,
6037 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("callee")));
6039 // These tests are specific to forCallable().
6040 StringRef ObjCString1
= "@interface I"
6045 " void (^block)() = ^{ 0x2b | ~0x2b; };"
6052 binaryOperator(forCallable(blockDecl()))));
6057 binaryOperator(forCallable(objcMethodDecl()))));
6059 StringRef ObjCString2
= "@interface I"
6065 " void (^block)() = ^{};"
6072 binaryOperator(forCallable(objcMethodDecl()))));
6077 binaryOperator(forCallable(blockDecl()))));
6081 class ForCallablePreservesBindingWithMultipleParentsTestCallback
6082 : public BoundNodesCallback
{
6084 bool run(const BoundNodes
*BoundNodes
, ASTContext
*Context
) override
{
6085 FunctionDecl
const *FunDecl
=
6086 BoundNodes
->getNodeAs
<FunctionDecl
>("funDecl");
6087 // Validate test assumptions. This would be expressed as ASSERT_* in
6090 EXPECT_TRUE(false && "Incorrect test setup");
6093 auto const *FunDef
= FunDecl
->getDefinition();
6094 if (!FunDef
|| !FunDef
->getBody() ||
6095 FunDef
->getNameAsString() != "Function") {
6096 EXPECT_TRUE(false && "Incorrect test setup");
6100 ExpectCorrectResult(
6102 callExpr(callee(cxxMethodDecl().bind("callee"))).bind("call"), //
6105 ExpectCorrectResult("ForCallable first",
6106 callExpr(forCallable(equalsNode(FunDecl
)),
6107 callee(cxxMethodDecl().bind("callee")))
6111 ExpectCorrectResult("ForCallable second",
6112 callExpr(callee(cxxMethodDecl().bind("callee")),
6113 forCallable(equalsNode(FunDecl
)))
6117 // This value does not really matter: the EXPECT_* will set the exit code.
6122 void ExpectCorrectResult(StringRef LogInfo
,
6123 ArrayRef
<BoundNodes
> Results
) const {
6124 EXPECT_EQ(Results
.size(), 1u) << LogInfo
;
6125 if (Results
.empty())
6127 auto const &R
= Results
.front();
6128 EXPECT_TRUE(R
.getNodeAs
<CallExpr
>("call")) << LogInfo
;
6129 EXPECT_TRUE(R
.getNodeAs
<CXXMethodDecl
>("callee")) << LogInfo
;
6132 template <typename MatcherT
>
6133 void ExpectCorrectResult(StringRef LogInfo
, MatcherT Matcher
,
6134 FunctionDecl
const *FunDef
) const {
6135 auto &Context
= FunDef
->getASTContext();
6136 auto const &Results
= match(findAll(Matcher
), *FunDef
->getBody(), Context
);
6137 ExpectCorrectResult(LogInfo
, Results
);
6142 TEST(StatementMatcher
, ForCallablePreservesBindingWithMultipleParents
) {
6143 // Tests in this file are fairly simple and therefore can rely on matches,
6144 // matchAndVerifyResultTrue, etc. This test, however, needs a FunctionDecl* in
6145 // order to call equalsNode in order to reproduce the observed issue (bindings
6146 // being removed despite forCallable matching the node).
6148 // Because of this and because the machinery to compile the code into an
6149 // ASTUnit is not exposed outside matchAndVerifyResultConditionally, it is
6150 // cheaper to have a custom BoundNodesCallback for the purpose of this test.
6151 StringRef codeWithTemplateFunction
= R
"cpp(
6154 template <typename T>
6155 void Function(T t); // Declaration
6158 void Instantiate(Klass k) {
6162 template <typename T>
6163 void Klass::Function(T t) { // Definition
6164 // Compound statement has two parents: the declaration and the definition.
6168 EXPECT_TRUE(matchAndVerifyResultTrue(
6169 codeWithTemplateFunction
,
6170 callExpr(callee(functionDecl(hasName("Function")).bind("funDecl"))),
6172 ForCallablePreservesBindingWithMultipleParentsTestCallback
>()));
6175 TEST(Matcher
, ForEachOverriden
) {
6176 const auto ForEachOverriddenInClass
= [](const char *ClassName
) {
6177 return cxxMethodDecl(ofClass(hasName(ClassName
)), isVirtual(),
6178 forEachOverridden(cxxMethodDecl().bind("overridden")))
6181 static const char Code1
[] = "class A { virtual void f(); };"
6182 "class B : public A { void f(); };"
6183 "class C : public B { void f(); };";
6184 // C::f overrides A::f.
6185 EXPECT_TRUE(matchAndVerifyResultTrue(
6186 Code1
, ForEachOverriddenInClass("C"),
6187 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 1)));
6188 EXPECT_TRUE(matchAndVerifyResultTrue(
6189 Code1
, ForEachOverriddenInClass("C"),
6190 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
6192 // B::f overrides A::f.
6193 EXPECT_TRUE(matchAndVerifyResultTrue(
6194 Code1
, ForEachOverriddenInClass("B"),
6195 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 1)));
6196 EXPECT_TRUE(matchAndVerifyResultTrue(
6197 Code1
, ForEachOverriddenInClass("B"),
6198 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
6200 // A::f overrides nothing.
6201 EXPECT_TRUE(notMatches(Code1
, ForEachOverriddenInClass("A")));
6203 static const char Code2
[] =
6204 "class A1 { virtual void f(); };"
6205 "class A2 { virtual void f(); };"
6206 "class B : public A1, public A2 { void f(); };";
6207 // B::f overrides A1::f and A2::f. This produces two matches.
6208 EXPECT_TRUE(matchAndVerifyResultTrue(
6209 Code2
, ForEachOverriddenInClass("B"),
6210 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 2)));
6211 EXPECT_TRUE(matchAndVerifyResultTrue(
6212 Code2
, ForEachOverriddenInClass("B"),
6213 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
6215 // A1::f overrides nothing.
6216 EXPECT_TRUE(notMatches(Code2
, ForEachOverriddenInClass("A1")));
6219 TEST(Matcher
, HasAnyDeclaration
) {
6220 StringRef Fragment
= "void foo(int p1);"
6221 "void foo(int *p2);"
6223 "template <typename T> void baz(T t) { foo(t); }";
6226 matches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6227 hasParameter(0, parmVarDecl(hasName("p1"))))))));
6229 matches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6230 hasParameter(0, parmVarDecl(hasName("p2"))))))));
6232 notMatches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6233 hasParameter(0, parmVarDecl(hasName("p3"))))))));
6234 EXPECT_TRUE(notMatches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(
6235 functionDecl(hasName("bar"))))));
6238 TEST(SubstTemplateTypeParmType
, HasReplacementType
) {
6239 StringRef Fragment
= "template<typename T>"
6243 EXPECT_TRUE(matches(Fragment
, substTemplateTypeParmType(hasReplacementType(
6244 qualType(asString("int"))))));
6245 EXPECT_TRUE(notMatches(Fragment
, substTemplateTypeParmType(hasReplacementType(
6246 qualType(asString("double"))))));
6248 notMatches("template<int N>"
6250 "double j = F<5>();",
6251 substTemplateTypeParmType(hasReplacementType(qualType()))));
6254 TEST(ClassTemplateSpecializationDecl
, HasSpecializedTemplate
) {
6255 auto Matcher
= classTemplateSpecializationDecl(
6256 hasSpecializedTemplate(classTemplateDecl()));
6258 matches("template<typename T> class A {}; typedef A<int> B;", Matcher
));
6259 EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher
));
6262 TEST(CXXNewExpr
, Array
) {
6263 StatementMatcher NewArray
= cxxNewExpr(isArray());
6265 EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray
));
6266 EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray
));
6268 StatementMatcher NewArraySize10
=
6269 cxxNewExpr(hasArraySize(integerLiteral(equals(10))));
6271 matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10
));
6273 notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10
));
6276 TEST(CXXNewExpr
, PlacementArgs
) {
6277 StatementMatcher IsPlacementNew
= cxxNewExpr(hasAnyPlacementArg(anything()));
6279 EXPECT_TRUE(matches(R
"(
6280 void* operator new(decltype(sizeof(void*)), void*);
6281 int *foo(void* Storage) {
6282 return new (Storage) int;
6286 EXPECT_TRUE(matches(R
"(
6287 void* operator new(decltype(sizeof(void*)), void*, unsigned);
6288 int *foo(void* Storage) {
6289 return new (Storage, 16) int;
6291 cxxNewExpr(hasPlacementArg(
6292 1, ignoringImpCasts(integerLiteral(equals(16)))))));
6294 EXPECT_TRUE(notMatches(R
"(
6295 void* operator new(decltype(sizeof(void*)), void*);
6296 int *foo(void* Storage) {
6302 TEST(HasUnqualifiedLoc
, BindsToConstIntVarDecl
) {
6303 EXPECT_TRUE(matches(
6305 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6306 hasUnqualifiedLoc(loc(asString("int"))))))));
6309 TEST(HasUnqualifiedLoc
, BindsToVolatileIntVarDecl
) {
6310 EXPECT_TRUE(matches(
6311 "volatile int x = 0;",
6312 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6313 hasUnqualifiedLoc(loc(asString("int"))))))));
6316 TEST(HasUnqualifiedLoc
, BindsToConstVolatileIntVarDecl
) {
6317 EXPECT_TRUE(matches(
6318 "const volatile int x = 0;",
6319 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6320 hasUnqualifiedLoc(loc(asString("int"))))))));
6323 TEST(HasUnqualifiedLoc
, BindsToConstPointerVarDecl
) {
6324 auto matcher
= varDecl(
6326 hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))));
6327 EXPECT_TRUE(matches("int* const x = 0;", matcher
));
6328 EXPECT_TRUE(notMatches("int const x = 0;", matcher
));
6331 TEST(HasUnqualifiedLoc
, BindsToPointerToConstVolatileIntVarDecl
) {
6333 matches("const volatile int* x = 0;",
6334 varDecl(hasName("x"),
6335 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(
6336 hasUnqualifiedLoc(loc(asString("int"))))))))));
6339 TEST(HasUnqualifiedLoc
, BindsToConstIntFunctionDecl
) {
6341 matches("const int f() { return 5; }",
6342 functionDecl(hasName("f"),
6343 hasReturnTypeLoc(qualifiedTypeLoc(
6344 hasUnqualifiedLoc(loc(asString("int"))))))));
6347 TEST(HasUnqualifiedLoc
, FloatBindsToConstFloatVarDecl
) {
6348 EXPECT_TRUE(matches(
6349 "const float x = 0;",
6350 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6351 hasUnqualifiedLoc(loc(asString("float"))))))));
6354 TEST(HasUnqualifiedLoc
, FloatDoesNotBindToIntVarDecl
) {
6355 EXPECT_TRUE(notMatches(
6357 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6358 hasUnqualifiedLoc(loc(asString("float"))))))));
6361 TEST(HasUnqualifiedLoc
, FloatDoesNotBindToConstIntVarDecl
) {
6362 EXPECT_TRUE(notMatches(
6364 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6365 hasUnqualifiedLoc(loc(asString("float"))))))));
6368 TEST(HasReturnTypeLoc
, BindsToIntReturnTypeLoc
) {
6369 EXPECT_TRUE(matches(
6370 "int f() { return 5; }",
6371 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6374 TEST(HasReturnTypeLoc
, BindsToFloatReturnTypeLoc
) {
6375 EXPECT_TRUE(matches(
6376 "float f() { return 5.0; }",
6377 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6380 TEST(HasReturnTypeLoc
, BindsToVoidReturnTypeLoc
) {
6381 EXPECT_TRUE(matches(
6383 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));
6386 TEST(HasReturnTypeLoc
, FloatDoesNotBindToIntReturnTypeLoc
) {
6387 EXPECT_TRUE(notMatches(
6388 "int f() { return 5; }",
6389 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6392 TEST(HasReturnTypeLoc
, IntDoesNotBindToFloatReturnTypeLoc
) {
6393 EXPECT_TRUE(notMatches(
6394 "float f() { return 5.0; }",
6395 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6398 TEST(HasPointeeLoc
, BindsToAnyPointeeTypeLoc
) {
6399 auto matcher
= varDecl(hasName("x"),
6400 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6401 EXPECT_TRUE(matches("int* x;", matcher
));
6402 EXPECT_TRUE(matches("float* x;", matcher
));
6403 EXPECT_TRUE(matches("char* x;", matcher
));
6404 EXPECT_TRUE(matches("void* x;", matcher
));
6407 TEST(HasPointeeLoc
, DoesNotBindToTypeLocWithoutPointee
) {
6408 auto matcher
= varDecl(hasName("x"),
6409 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6410 EXPECT_TRUE(notMatches("int x;", matcher
));
6411 EXPECT_TRUE(notMatches("float x;", matcher
));
6412 EXPECT_TRUE(notMatches("char x;", matcher
));
6415 TEST(HasPointeeLoc
, BindsToTypeLocPointingToInt
) {
6417 matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6420 TEST(HasPointeeLoc
, BindsToTypeLocPointingToIntPointer
) {
6421 EXPECT_TRUE(matches("int** x;",
6422 pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));
6425 TEST(HasPointeeLoc
, BindsToTypeLocPointingToTypeLocPointingToInt
) {
6426 EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
6427 hasPointeeLoc(loc(asString("int"))))))));
6430 TEST(HasPointeeLoc
, BindsToTypeLocPointingToFloat
) {
6431 EXPECT_TRUE(matches("float* x;",
6432 pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6435 TEST(HasPointeeLoc
, IntPointeeDoesNotBindToTypeLocPointingToFloat
) {
6436 EXPECT_TRUE(notMatches("float* x;",
6437 pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6440 TEST(HasPointeeLoc
, FloatPointeeDoesNotBindToTypeLocPointingToInt
) {
6441 EXPECT_TRUE(notMatches(
6442 "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6445 TEST(HasReferentLoc
, BindsToAnyReferentTypeLoc
) {
6446 auto matcher
= varDecl(
6447 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6448 EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher
));
6449 EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher
));
6450 EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher
));
6451 EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher
));
6452 EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher
));
6455 TEST(HasReferentLoc
, DoesNotBindToTypeLocWithoutReferent
) {
6456 auto matcher
= varDecl(
6457 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6458 EXPECT_TRUE(notMatches("int r;", matcher
));
6459 EXPECT_TRUE(notMatches("int r = 3;", matcher
));
6460 EXPECT_TRUE(notMatches("const int r = 3;", matcher
));
6461 EXPECT_TRUE(notMatches("int* r;", matcher
));
6462 EXPECT_TRUE(notMatches("float r;", matcher
));
6463 EXPECT_TRUE(notMatches("char r;", matcher
));
6466 TEST(HasReferentLoc
, BindsToAnyRvalueReference
) {
6467 auto matcher
= varDecl(
6468 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6469 EXPECT_TRUE(matches("int&& r = 3;", matcher
));
6470 EXPECT_TRUE(matches("auto&& r = 3;", matcher
));
6471 EXPECT_TRUE(matches("float&& r = 3.0;", matcher
));
6474 TEST(HasReferentLoc
, BindsToIntReferenceTypeLoc
) {
6475 EXPECT_TRUE(matches("int rr = 3; int& r = rr;",
6476 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6479 TEST(HasReferentLoc
, BindsToIntRvalueReferenceTypeLoc
) {
6480 EXPECT_TRUE(matches("int&& r = 3;",
6481 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6484 TEST(HasReferentLoc
, BindsToFloatReferenceTypeLoc
) {
6486 matches("float rr = 3.0; float& r = rr;",
6487 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6490 TEST(HasReferentLoc
, BindsToParameterWithIntReferenceTypeLoc
) {
6491 EXPECT_TRUE(matches(
6492 "int f(int& r) { return r; }",
6493 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6494 hasReferentLoc(loc(asString("int"))))))));
6497 TEST(HasReferentLoc
, IntReferenceDoesNotBindToFloatReferenceTypeLoc
) {
6499 notMatches("float rr = 3.0; float& r = rr;",
6500 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6503 TEST(HasReferentLoc
, FloatReferenceDoesNotBindToIntReferenceTypeLoc
) {
6505 notMatches("int rr = 3; int& r = rr;",
6506 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6509 TEST(HasReferentLoc
, DoesNotBindToParameterWithoutIntReferenceTypeLoc
) {
6510 EXPECT_TRUE(notMatches(
6511 "int f(int r) { return r; }",
6512 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6513 hasReferentLoc(loc(asString("int"))))))));
6516 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithIntArgument
) {
6517 EXPECT_TRUE(matches(
6518 "template<typename T> class A {}; A<int> a;",
6519 varDecl(hasName("a"),
6520 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6521 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6522 hasTypeLoc(loc(asString("int")))))))))));
6525 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithDoubleArgument
) {
6526 EXPECT_TRUE(matches(
6527 "template<typename T> class A {}; A<double> a;",
6528 varDecl(hasName("a"),
6529 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6530 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6531 hasTypeLoc(loc(asString("double")))))))))));
6534 TEST(HasAnyTemplateArgumentLoc
, BindsToExplicitSpecializationWithIntArgument
) {
6535 EXPECT_TRUE(matches(
6536 "template<typename T> class A {}; template<> class A<int> {};",
6537 classTemplateSpecializationDecl(
6539 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
6542 TEST(HasAnyTemplateArgumentLoc
,
6543 BindsToExplicitSpecializationWithDoubleArgument
) {
6544 EXPECT_TRUE(matches(
6545 "template<typename T> class A {}; template<> class A<double> {};",
6546 classTemplateSpecializationDecl(
6548 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
6551 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithMultipleArguments
) {
6553 template<typename T, typename U> class A {};
6554 template<> class A<double, int> {};
6557 matches(code
, classTemplateSpecializationDecl(
6558 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
6559 loc(asString("double")))))));
6561 EXPECT_TRUE(matches(
6562 code
, classTemplateSpecializationDecl(
6564 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
6567 TEST(HasAnyTemplateArgumentLoc
, DoesNotBindToSpecializationWithIntArgument
) {
6568 EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",
6569 classTemplateSpecializationDecl(
6570 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
6571 loc(asString("double")))))));
6574 TEST(HasAnyTemplateArgumentLoc
,
6575 DoesNotBindToExplicitSpecializationWithIntArgument
) {
6576 EXPECT_TRUE(notMatches(
6577 "template<typename T> class A {}; template<> class A<int> {};",
6578 classTemplateSpecializationDecl(
6580 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
6583 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithIntArgument
) {
6585 matches("template<typename T> class A {}; A<int> a;",
6586 varDecl(hasName("a"),
6587 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6588 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6589 0, hasTypeLoc(loc(asString("int")))))))))));
6592 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithDoubleArgument
) {
6594 matches("template<typename T> class A {}; A<double> a;",
6595 varDecl(hasName("a"),
6596 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6597 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6598 0, hasTypeLoc(loc(asString("double")))))))))));
6601 TEST(HasTemplateArgumentLoc
, DoesNotBindToSpecializationWithIntArgument
) {
6602 EXPECT_TRUE(notMatches(
6603 "template<typename T> class A {}; A<int> a;",
6604 varDecl(hasName("a"),
6605 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6606 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6607 0, hasTypeLoc(loc(asString("double")))))))))));
6610 TEST(HasTemplateArgumentLoc
, BindsToExplicitSpecializationWithIntArgument
) {
6611 EXPECT_TRUE(matches(
6612 "template<typename T> class A {}; template<> class A<int> {};",
6613 classTemplateSpecializationDecl(
6615 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6618 TEST(HasTemplateArgumentLoc
, BindsToExplicitSpecializationWithDoubleArgument
) {
6619 EXPECT_TRUE(matches(
6620 "template<typename T> class A {}; template<> class A<double> {};",
6621 classTemplateSpecializationDecl(
6623 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6626 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithMultipleArguments
) {
6628 template<typename T, typename U> class A {};
6629 template<> class A<double, int> {};
6631 EXPECT_TRUE(matches(
6632 code
, classTemplateSpecializationDecl(
6633 hasName("A"), hasTemplateArgumentLoc(
6634 0, hasTypeLoc(loc(asString("double")))))));
6635 EXPECT_TRUE(matches(
6636 code
, classTemplateSpecializationDecl(
6638 hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));
6641 TEST(HasTemplateArgumentLoc
,
6642 DoesNotBindToExplicitSpecializationWithIntArgument
) {
6643 EXPECT_TRUE(notMatches(
6644 "template<typename T> class A {}; template<> class A<int> {};",
6645 classTemplateSpecializationDecl(
6647 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6650 TEST(HasTemplateArgumentLoc
,
6651 DoesNotBindToSpecializationWithMisplacedArguments
) {
6653 template<typename T, typename U> class A {};
6654 template<> class A<double, int> {};
6656 EXPECT_TRUE(notMatches(
6657 code
, classTemplateSpecializationDecl(
6658 hasName("A"), hasTemplateArgumentLoc(
6659 1, hasTypeLoc(loc(asString("double")))))));
6660 EXPECT_TRUE(notMatches(
6661 code
, classTemplateSpecializationDecl(
6663 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6666 TEST(HasTemplateArgumentLoc
, DoesNotBindWithBadIndex
) {
6668 template<typename T, typename U> class A {};
6669 template<> class A<double, int> {};
6671 EXPECT_TRUE(notMatches(
6672 code
, classTemplateSpecializationDecl(
6673 hasName("A"), hasTemplateArgumentLoc(
6674 -1, hasTypeLoc(loc(asString("double")))))));
6675 EXPECT_TRUE(notMatches(
6676 code
, classTemplateSpecializationDecl(
6677 hasName("A"), hasTemplateArgumentLoc(
6678 100, hasTypeLoc(loc(asString("int")))))));
6681 TEST(HasTemplateArgumentLoc
, BindsToDeclRefExprWithIntArgument
) {
6682 EXPECT_TRUE(matches(R
"(
6683 template<typename T> T f(T t) { return t; }
6684 int g() { int i = f<int>(3); return i; }
6686 declRefExpr(to(functionDecl(hasName("f"))),
6687 hasTemplateArgumentLoc(
6688 0, hasTypeLoc(loc(asString("int")))))));
6691 TEST(HasTemplateArgumentLoc
, BindsToDeclRefExprWithDoubleArgument
) {
6692 EXPECT_TRUE(matches(
6694 template<typename T> T f(T t) { return t; }
6695 double g() { double i = f<double>(3.0); return i; }
6698 to(functionDecl(hasName("f"))),
6699 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6702 TEST(HasTemplateArgumentLoc
, DoesNotBindToDeclRefExprWithDoubleArgument
) {
6703 EXPECT_TRUE(notMatches(
6705 template<typename T> T f(T t) { return t; }
6706 double g() { double i = f<double>(3.0); return i; }
6709 to(functionDecl(hasName("f"))),
6710 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6713 TEST(HasNamedTypeLoc
, BindsToElaboratedObjectDeclaration
) {
6714 EXPECT_TRUE(matches(
6716 template <typename T>
6720 varDecl(hasName("c"),
6721 hasTypeLoc(elaboratedTypeLoc(
6722 hasNamedTypeLoc(templateSpecializationTypeLoc(
6723 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6726 TEST(HasNamedTypeLoc
, DoesNotBindToNonElaboratedObjectDeclaration
) {
6727 EXPECT_TRUE(matches(
6729 template <typename T>
6733 varDecl(hasName("c"),
6734 hasTypeLoc(elaboratedTypeLoc(
6735 hasNamedTypeLoc(templateSpecializationTypeLoc(
6736 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6739 } // namespace ast_matchers
6740 } // namespace clang