1 //= unittests/ASTMatchers/ASTMatchersTraversalTest.cpp - matchers unit tests =//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "ASTMatchersTest.h"
10 #include "clang/AST/Attrs.inc"
11 #include "clang/AST/DeclCXX.h"
12 #include "clang/AST/PrettyPrinter.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/ASTMatchers/ASTMatchers.h"
15 #include "clang/Tooling/Tooling.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/TargetParser/Host.h"
18 #include "llvm/TargetParser/Triple.h"
19 #include "gtest/gtest.h"
22 namespace ast_matchers
{
24 TEST(DeclarationMatcher
, hasMethod
) {
25 EXPECT_TRUE(matches("class A { void func(); };",
26 cxxRecordDecl(hasMethod(hasName("func")))));
27 EXPECT_TRUE(notMatches("class A { void func(); };",
28 cxxRecordDecl(hasMethod(isPublic()))));
31 TEST(DeclarationMatcher
, ClassDerivedFromDependentTemplateSpecialization
) {
33 "template <typename T> struct A {"
34 " template <typename T2> struct F {};"
36 "template <typename T> struct B : A<T>::template F<T> {};"
38 cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
41 TEST(DeclarationMatcher
, hasDeclContext
) {
48 recordDecl(hasDeclContext(namespaceDecl(hasName("M"))))));
49 EXPECT_TRUE(notMatches(
55 recordDecl(hasDeclContext(namespaceDecl(hasName("N"))))));
57 EXPECT_TRUE(matches("namespace {"
62 recordDecl(hasDeclContext(namespaceDecl(
63 hasName("M"), hasDeclContext(namespaceDecl()))))));
65 EXPECT_TRUE(matches("class D{};", decl(hasDeclContext(decl()))));
68 TEST(HasDescendant
, MatchesDescendantTypes
) {
69 EXPECT_TRUE(matches("void f() { int i = 3; }",
70 decl(hasDescendant(loc(builtinType())))));
71 EXPECT_TRUE(matches("void f() { int i = 3; }",
72 stmt(hasDescendant(builtinType()))));
74 EXPECT_TRUE(matches("void f() { int i = 3; }",
75 stmt(hasDescendant(loc(builtinType())))));
76 EXPECT_TRUE(matches("void f() { int i = 3; }",
77 stmt(hasDescendant(qualType(builtinType())))));
79 EXPECT_TRUE(notMatches("void f() { float f = 2.0f; }",
80 stmt(hasDescendant(isInteger()))));
82 EXPECT_TRUE(matchAndVerifyResultTrue(
83 "void f() { int a; float c; int d; int e; }",
84 functionDecl(forEachDescendant(
85 varDecl(hasDescendant(isInteger())).bind("x"))),
86 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 3)));
89 TEST(HasDescendant
, MatchesDescendantsOfTypes
) {
90 EXPECT_TRUE(matches("void f() { int*** i; }",
91 qualType(hasDescendant(builtinType()))));
92 EXPECT_TRUE(matches("void f() { int*** i; }",
93 qualType(hasDescendant(
94 pointerType(pointee(builtinType()))))));
95 EXPECT_TRUE(matches("void f() { int*** i; }",
96 typeLoc(hasDescendant(loc(builtinType())))));
98 EXPECT_TRUE(matchAndVerifyResultTrue(
99 "void f() { int*** i; }",
100 qualType(asString("int ***"), forEachDescendant(pointerType().bind("x"))),
101 std::make_unique
<VerifyIdIsBoundTo
<Type
>>("x", 2)));
105 TEST(Has
, MatchesChildrenOfTypes
) {
106 EXPECT_TRUE(matches("int i;",
107 varDecl(hasName("i"), has(isInteger()))));
108 EXPECT_TRUE(notMatches("int** i;",
109 varDecl(hasName("i"), has(isInteger()))));
110 EXPECT_TRUE(matchAndVerifyResultTrue(
111 "int (*f)(float, int);",
112 qualType(functionType(), forEach(qualType(isInteger()).bind("x"))),
113 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("x", 2)));
116 TEST(Has
, MatchesChildTypes
) {
119 varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));
120 EXPECT_TRUE(notMatches(
122 varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));
125 TEST(StatementMatcher
, Has
) {
126 StatementMatcher HasVariableI
=
127 expr(hasType(pointsTo(recordDecl(hasName("X")))),
128 has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i")))))));
131 "class X; X *x(int); void c() { int i; x(i); }", HasVariableI
));
132 EXPECT_TRUE(notMatches(
133 "class X; X *x(int); void c() { int i; x(42); }", HasVariableI
));
136 TEST(StatementMatcher
, HasDescendant
) {
137 StatementMatcher HasDescendantVariableI
=
138 expr(hasType(pointsTo(recordDecl(hasName("X")))),
139 hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));
142 "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",
143 HasDescendantVariableI
));
144 EXPECT_TRUE(notMatches(
145 "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",
146 HasDescendantVariableI
));
149 TEST(TypeMatcher
, MatchesClassType
) {
150 TypeMatcher TypeA
= hasDeclaration(recordDecl(hasName("A")));
152 EXPECT_TRUE(matches("class A { public: A *a; };", TypeA
));
153 EXPECT_TRUE(notMatches("class A {};", TypeA
));
155 TypeMatcher TypeDerivedFromA
=
156 hasDeclaration(cxxRecordDecl(isDerivedFrom("A")));
158 EXPECT_TRUE(matches("class A {}; class B : public A { public: B *b; };",
160 EXPECT_TRUE(notMatches("class A {};", TypeA
));
162 TypeMatcher TypeAHasClassB
= hasDeclaration(
163 recordDecl(hasName("A"), has(recordDecl(hasName("B")))));
166 matches("class A { public: A *a; class B {}; };", TypeAHasClassB
));
168 EXPECT_TRUE(matchesC("struct S {}; void f(void) { struct S s; }",
169 varDecl(hasType(namedDecl(hasName("S"))))));
172 TEST(TypeMatcher
, MatchesDeclTypes
) {
173 // TypedefType -> TypedefNameDecl
174 EXPECT_TRUE(matches("typedef int I; void f(I i);",
175 parmVarDecl(hasType(namedDecl(hasName("I"))))));
176 // ObjCObjectPointerType
177 EXPECT_TRUE(matchesObjC("@interface Foo @end void f(Foo *f);",
178 parmVarDecl(hasType(objcObjectPointerType()))));
179 // ObjCObjectPointerType -> ObjCInterfaceType -> ObjCInterfaceDecl
180 EXPECT_TRUE(matchesObjC(
181 "@interface Foo @end void f(Foo *f);",
182 parmVarDecl(hasType(pointsTo(objcInterfaceDecl(hasName("Foo")))))));
183 // TemplateTypeParmType
184 EXPECT_TRUE(matches("template <typename T> void f(T t);",
185 parmVarDecl(hasType(templateTypeParmType()))));
186 // TemplateTypeParmType -> TemplateTypeParmDecl
187 EXPECT_TRUE(matches("template <typename T> void f(T t);",
188 parmVarDecl(hasType(namedDecl(hasName("T"))))));
189 // InjectedClassNameType
190 EXPECT_TRUE(matches("template <typename T> struct S {"
193 parmVarDecl(hasType(elaboratedType(
194 namesType(injectedClassNameType()))))));
195 EXPECT_TRUE(notMatches("template <typename T> struct S {"
198 parmVarDecl(hasType(elaboratedType(
199 namesType(injectedClassNameType()))))));
200 // InjectedClassNameType -> CXXRecordDecl
201 EXPECT_TRUE(matches("template <typename T> struct S {"
204 parmVarDecl(hasType(namedDecl(hasName("S"))))));
206 static const char Using
[] = "template <typename T>"
211 "template <typename T>"
212 "struct S : private Base<T> {"
213 " using typename Base<T>::Foo;"
216 // UnresolvedUsingTypenameDecl
217 EXPECT_TRUE(matches(Using
, unresolvedUsingTypenameDecl(hasName("Foo"))));
218 // UnresolvedUsingTypenameType -> UnresolvedUsingTypenameDecl
219 EXPECT_TRUE(matches(Using
, parmVarDecl(hasType(namedDecl(hasName("Foo"))))));
222 TEST(HasDeclaration
, HasDeclarationOfEnumType
) {
223 EXPECT_TRUE(matches("enum X {}; void y(X *x) { x; }",
224 expr(hasType(pointsTo(
225 qualType(hasDeclaration(enumDecl(hasName("X")))))))));
228 TEST(HasDeclaration
, HasGetDeclTraitTest
) {
229 static_assert(internal::has_getDecl
<TypedefType
>::value
,
230 "Expected TypedefType to have a getDecl.");
231 static_assert(internal::has_getDecl
<RecordType
>::value
,
232 "Expected RecordType to have a getDecl.");
233 static_assert(!internal::has_getDecl
<TemplateSpecializationType
>::value
,
234 "Expected TemplateSpecializationType to *not* have a getDecl.");
237 TEST(HasDeclaration
, ElaboratedType
) {
239 "namespace n { template <typename T> struct X {}; }"
240 "void f(n::X<int>);",
241 parmVarDecl(hasType(qualType(hasDeclaration(cxxRecordDecl()))))));
243 "namespace n { template <typename T> struct X {}; }"
244 "void f(n::X<int>);",
245 parmVarDecl(hasType(elaboratedType(hasDeclaration(cxxRecordDecl()))))));
248 TEST(HasDeclaration
, HasDeclarationOfTypeWithDecl
) {
250 "typedef int X; X a;",
251 varDecl(hasName("a"), hasType(elaboratedType(namesType(
252 typedefType(hasDeclaration(decl()))))))));
254 // FIXME: Add tests for other types with getDecl() (e.g. RecordType)
257 TEST(HasDeclaration
, HasDeclarationOfTemplateSpecializationType
) {
259 "template <typename T> class A {}; A<int> a;",
260 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
261 hasDeclaration(namedDecl(hasName("A"))))))))));
263 "template <typename T> class A {};"
264 "template <typename T> class B { A<T> a; };",
265 fieldDecl(hasType(elaboratedType(namesType(templateSpecializationType(
266 hasDeclaration(namedDecl(hasName("A"))))))))));
268 "template <typename T> class A {}; A<int> a;",
269 varDecl(hasType(elaboratedType(namesType(
270 templateSpecializationType(hasDeclaration(cxxRecordDecl()))))))));
273 TEST(HasDeclaration
, HasDeclarationOfCXXNewExpr
) {
275 matches("int *A = new int();",
276 cxxNewExpr(hasDeclaration(functionDecl(parameterCountIs(1))))));
279 TEST(HasDeclaration
, HasDeclarationOfTypeAlias
) {
281 "template <typename T> using C = T; C<int> c;",
282 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
283 hasDeclaration(typeAliasTemplateDecl()))))))));
286 TEST(HasUnqualifiedDesugaredType
, DesugarsUsing
) {
288 matches("struct A {}; using B = A; B b;",
289 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
291 matches("struct A {}; using B = A; using C = B; C b;",
292 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
295 TEST(HasUnderlyingDecl
, Matches
) {
296 EXPECT_TRUE(matches("namespace N { template <class T> void f(T t); }"
297 "template <class T> void g() { using N::f; f(T()); }",
298 unresolvedLookupExpr(hasAnyDeclaration(
299 namedDecl(hasUnderlyingDecl(hasName("::N::f")))))));
301 "namespace N { template <class T> void f(T t); }"
302 "template <class T> void g() { N::f(T()); }",
303 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
304 EXPECT_TRUE(notMatches(
305 "namespace N { template <class T> void f(T t); }"
306 "template <class T> void g() { using N::f; f(T()); }",
307 unresolvedLookupExpr(hasAnyDeclaration(namedDecl(hasName("::N::f"))))));
310 TEST(HasType
, TakesQualTypeMatcherAndMatchesExpr
) {
311 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
313 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX
))));
315 notMatches("class X {}; void y(X *x) { x; }",
316 expr(hasType(ClassX
))));
318 matches("class X {}; void y(X *x) { x; }",
319 expr(hasType(pointsTo(ClassX
)))));
322 TEST(HasType
, TakesQualTypeMatcherAndMatchesValueDecl
) {
323 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
325 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX
))));
327 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX
))));
329 matches("class X {}; void y() { X *x; }",
330 varDecl(hasType(pointsTo(ClassX
)))));
333 TEST(HasType
, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier
) {
334 TypeMatcher ClassX
= hasDeclaration(recordDecl(hasName("X")));
335 CXXBaseSpecifierMatcher BaseClassX
= cxxBaseSpecifier(hasType(ClassX
));
336 DeclarationMatcher ClassHasBaseClassX
=
337 cxxRecordDecl(hasDirectBase(BaseClassX
));
338 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX
));
339 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX
));
342 TEST(HasType
, TakesDeclMatcherAndMatchesExpr
) {
343 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
345 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX
))));
347 notMatches("class X {}; void y(X *x) { x; }",
348 expr(hasType(ClassX
))));
351 TEST(HasType
, TakesDeclMatcherAndMatchesValueDecl
) {
352 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
354 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX
))));
356 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX
))));
359 TEST(HasType
, TakesDeclMatcherAndMatchesCXXBaseSpecifier
) {
360 DeclarationMatcher ClassX
= recordDecl(hasName("X"));
361 CXXBaseSpecifierMatcher BaseClassX
= cxxBaseSpecifier(hasType(ClassX
));
362 DeclarationMatcher ClassHasBaseClassX
=
363 cxxRecordDecl(hasDirectBase(BaseClassX
));
364 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX
));
365 EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX
));
368 TEST(HasType
, MatchesTypedefDecl
) {
369 EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));
370 EXPECT_TRUE(matches("typedef const int T;",
371 typedefDecl(hasType(asString("const int")))));
372 EXPECT_TRUE(notMatches("typedef const int T;",
373 typedefDecl(hasType(asString("int")))));
374 EXPECT_TRUE(matches("typedef int foo; typedef foo bar;",
375 typedefDecl(hasType(asString("foo")), hasName("bar"))));
378 TEST(HasType
, MatchesTypedefNameDecl
) {
379 EXPECT_TRUE(matches("using X = int;", typedefNameDecl(hasType(asString("int")))));
380 EXPECT_TRUE(matches("using T = const int;",
381 typedefNameDecl(hasType(asString("const int")))));
382 EXPECT_TRUE(notMatches("using T = const int;",
383 typedefNameDecl(hasType(asString("int")))));
384 EXPECT_TRUE(matches("using foo = int; using bar = foo;",
385 typedefNameDecl(hasType(asString("foo")), hasName("bar"))));
388 TEST(HasTypeLoc
, MatchesBlockDecl
) {
389 EXPECT_TRUE(matchesConditionally(
390 "auto x = ^int (int a, int b) { return a + b; };",
391 blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true,
395 TEST(HasTypeLoc
, MatchesCXXBaseSpecifierAndCtorInitializer
) {
396 llvm::StringRef code
= R
"cpp(
398 class Bar : public Foo {
404 code
, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("Foo")))))));
406 matches(code
, cxxCtorInitializer(hasTypeLoc(loc(asString("Foo"))))));
409 TEST(HasTypeLoc
, MatchesCXXFunctionalCastExpr
) {
410 EXPECT_TRUE(matches("auto x = int(3);",
411 cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int"))))));
414 TEST(HasTypeLoc
, MatchesCXXNewExpr
) {
415 EXPECT_TRUE(matches("auto* x = new int(3);",
416 cxxNewExpr(hasTypeLoc(loc(asString("int"))))));
417 EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();",
418 cxxNewExpr(hasTypeLoc(loc(asString("Foo"))))));
421 TEST(HasTypeLoc
, MatchesCXXTemporaryObjectExpr
) {
423 matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",
424 cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("Foo"))))));
427 TEST(HasTypeLoc
, MatchesCXXUnresolvedConstructExpr
) {
429 matches("template <typename T> T make() { return T(); }",
430 cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));
433 TEST(HasTypeLoc
, MatchesClassTemplateSpecializationDecl
) {
435 "template <typename T> class Foo; template <> class Foo<int> {};",
436 classTemplateSpecializationDecl(hasTypeLoc(loc(asString("Foo<int>"))))));
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()),
663 true, {"-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()),
672 true, {"-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()),
681 true, {"-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(ForEachArgumentWithParamType
, ReportsNoFalsePositives
) {
989 StatementMatcher ArgumentY
=
990 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
991 TypeMatcher IntType
= qualType(isInteger()).bind("type");
992 StatementMatcher CallExpr
=
993 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
995 // IntParam does not match.
996 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr
));
997 // ArgumentY does not match.
998 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr
));
1001 TEST(ForEachArgumentWithParamType
, MatchesCXXMemberCallExpr
) {
1002 StatementMatcher ArgumentY
=
1003 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1004 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1005 StatementMatcher CallExpr
=
1006 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1007 EXPECT_TRUE(matchAndVerifyResultTrue(
1009 " const S& operator[](int i) { return *this; }"
1015 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 1)));
1017 StatementMatcher CallExpr2
=
1018 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1019 EXPECT_TRUE(matchAndVerifyResultTrue(
1021 " static void g(int i);"
1027 CallExpr2
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 1)));
1030 TEST(ForEachArgumentWithParamType
, MatchesCallExpr
) {
1031 StatementMatcher ArgumentY
=
1032 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1033 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1034 StatementMatcher CallExpr
=
1035 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1037 EXPECT_TRUE(matchAndVerifyResultTrue(
1038 "void f(int i) { int y; f(y); }", CallExpr
,
1039 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1040 EXPECT_TRUE(matchAndVerifyResultTrue(
1041 "void f(int i) { int y; f(y); }", CallExpr
,
1042 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1044 EXPECT_TRUE(matchAndVerifyResultTrue(
1045 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
1046 std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type", 2)));
1047 EXPECT_TRUE(matchAndVerifyResultTrue(
1048 "void f(int i, int j) { int y; f(y, y); }", CallExpr
,
1049 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg", 2)));
1052 TEST(ForEachArgumentWithParamType
, MatchesConstructExpr
) {
1053 StatementMatcher ArgumentY
=
1054 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1055 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1056 StatementMatcher ConstructExpr
=
1057 cxxConstructExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1059 EXPECT_TRUE(matchAndVerifyResultTrue(
1065 ConstructExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1066 EXPECT_TRUE(matchAndVerifyResultTrue(
1072 ConstructExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1075 TEST(ForEachArgumentWithParamType
, HandlesKandRFunctions
) {
1076 StatementMatcher ArgumentY
=
1077 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1078 TypeMatcher IntType
= qualType(isInteger()).bind("type");
1079 StatementMatcher CallExpr
=
1080 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1082 EXPECT_TRUE(matchesC("void f();\n"
1083 "void call_it(void) { int x, y; f(x, y); }\n"
1084 "void f(a, b) int a, b; {}\n"
1085 "void call_it2(void) { int x, y; f(x, y); }",
1089 TEST(ForEachArgumentWithParamType
, HandlesBoundNodesForNonMatches
) {
1090 EXPECT_TRUE(matchAndVerifyResultTrue(
1091 "void g(int i, int j) {"
1100 forEachDescendant(varDecl().bind("v")),
1101 forEachDescendant(callExpr(forEachArgumentWithParamType(
1102 declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),
1103 std::make_unique
<VerifyIdIsBoundTo
<VarDecl
>>("v", 4)));
1106 TEST(ForEachArgumentWithParamType
, MatchesFunctionPtrCalls
) {
1107 StatementMatcher ArgumentY
=
1108 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1109 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1110 StatementMatcher CallExpr
=
1111 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1113 EXPECT_TRUE(matchAndVerifyResultTrue(
1115 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1116 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1117 EXPECT_TRUE(matchAndVerifyResultTrue(
1119 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1120 CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1123 TEST(ForEachArgumentWithParamType
, MatchesMemberFunctionPtrCalls
) {
1124 StatementMatcher ArgumentY
=
1125 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1126 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1127 StatementMatcher CallExpr
=
1128 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1130 StringRef S
= "struct A {\n"
1131 " int f(int i) { return i + 1; }\n"
1132 " int (A::*x)(int);\n"
1140 EXPECT_TRUE(matchAndVerifyResultTrue(
1141 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1142 EXPECT_TRUE(matchAndVerifyResultTrue(
1143 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1146 TEST(ForEachArgumentWithParamType
, MatchesVariadicFunctionPtrCalls
) {
1147 StatementMatcher ArgumentY
=
1148 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1149 TypeMatcher IntType
= qualType(builtinType()).bind("type");
1150 StatementMatcher CallExpr
=
1151 callExpr(forEachArgumentWithParamType(ArgumentY
, IntType
));
1153 StringRef S
= R
"cpp(
1154 void fcntl(int fd, int cmd, ...) {}
1156 template <typename Func>
1162 void g() { f(fcntl); }
1165 EXPECT_TRUE(matchAndVerifyResultTrue(
1166 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<QualType
>>("type")));
1167 EXPECT_TRUE(matchAndVerifyResultTrue(
1168 S
, CallExpr
, std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("arg")));
1171 TEST(QualType
, hasCanonicalType
) {
1172 EXPECT_TRUE(notMatches("typedef int &int_ref;"
1175 varDecl(hasType(qualType(referenceType())))));
1177 matches("typedef int &int_ref;"
1180 varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));
1183 TEST(HasParameter
, CallsInnerMatcher
) {
1184 EXPECT_TRUE(matches("class X { void x(int) {} };",
1185 cxxMethodDecl(hasParameter(0, varDecl()))));
1186 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1187 cxxMethodDecl(hasParameter(0, hasName("x")))));
1188 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1189 objcMethodDecl(hasParameter(0, hasName("x")))));
1190 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1191 blockDecl(hasParameter(0, hasName("p")))));
1194 TEST(HasParameter
, DoesNotMatchIfIndexOutOfBounds
) {
1195 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1196 cxxMethodDecl(hasParameter(42, varDecl()))));
1199 TEST(HasType
, MatchesParameterVariableTypesStrictly
) {
1200 EXPECT_TRUE(matches(
1201 "class X { void x(X x) {} };",
1202 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1203 EXPECT_TRUE(notMatches(
1204 "class X { void x(const X &x) {} };",
1205 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1206 EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
1207 cxxMethodDecl(hasParameter(
1208 0, hasType(pointsTo(recordDecl(hasName("X"))))))));
1209 EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
1210 cxxMethodDecl(hasParameter(
1211 0, hasType(references(recordDecl(hasName("X"))))))));
1214 TEST(HasAnyParameter
, MatchesIndependentlyOfPosition
) {
1215 EXPECT_TRUE(matches(
1216 "class Y {}; class X { void x(X x, Y y) {} };",
1217 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1218 EXPECT_TRUE(matches(
1219 "class Y {}; class X { void x(Y y, X x) {} };",
1220 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1221 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1222 objcMethodDecl(hasAnyParameter(hasName("x")))));
1223 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1224 blockDecl(hasAnyParameter(hasName("p")))));
1227 TEST(Returns
, MatchesReturnTypes
) {
1228 EXPECT_TRUE(matches("class Y { int f() { return 1; } };",
1229 functionDecl(returns(asString("int")))));
1230 EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",
1231 functionDecl(returns(asString("float")))));
1232 EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",
1233 functionDecl(returns(hasDeclaration(
1234 recordDecl(hasName("Y")))))));
1237 TEST(HasAnyParameter
, DoesntMatchIfInnerMatcherDoesntMatch
) {
1238 EXPECT_TRUE(notMatches(
1239 "class Y {}; class X { void x(int) {} };",
1240 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1243 TEST(HasAnyParameter
, DoesNotMatchThisPointer
) {
1244 EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
1245 cxxMethodDecl(hasAnyParameter(
1246 hasType(pointsTo(recordDecl(hasName("X"))))))));
1249 TEST(HasName
, MatchesParameterVariableDeclarations
) {
1250 EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
1251 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1252 EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
1253 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1256 TEST(Matcher
, MatchesTypeTemplateArgument
) {
1257 EXPECT_TRUE(matches(
1258 "template<typename T> struct B {};"
1260 classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
1261 asString("int"))))));
1264 TEST(Matcher
, MatchesTemplateTemplateArgument
) {
1265 EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
1266 "template<typename T> class Y {};"
1268 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1269 refersToTemplate(templateName())))));
1272 TEST(Matcher
, MatchesDeclarationReferenceTemplateArgument
) {
1273 EXPECT_TRUE(matches(
1274 "struct B { int next; };"
1275 "template<int(B::*next_ptr)> struct A {};"
1277 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1278 refersToDeclaration(fieldDecl(hasName("next")))))));
1280 EXPECT_TRUE(notMatches(
1281 "template <typename T> struct A {};"
1283 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1284 refersToDeclaration(decl())))));
1286 EXPECT_TRUE(matches(
1287 "struct B { int next; };"
1288 "template<int(B::*next_ptr)> struct A {};"
1290 templateSpecializationType(hasAnyTemplateArgument(isExpr(
1291 hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));
1293 EXPECT_TRUE(notMatches(
1294 "template <typename T> struct A {};"
1296 templateSpecializationType(hasAnyTemplateArgument(
1297 refersToDeclaration(decl())))));
1301 TEST(Matcher
, MatchesSpecificArgument
) {
1302 EXPECT_TRUE(matches(
1303 "template<typename T, typename U> class A {};"
1305 classTemplateSpecializationDecl(hasTemplateArgument(
1306 1, refersToType(asString("int"))))));
1307 EXPECT_TRUE(notMatches(
1308 "template<typename T, typename U> class A {};"
1310 classTemplateSpecializationDecl(hasTemplateArgument(
1311 1, refersToType(asString("int"))))));
1313 EXPECT_TRUE(matches(
1314 "template<typename T, typename U> class A {};"
1316 templateSpecializationType(hasTemplateArgument(
1317 1, refersToType(asString("int"))))));
1318 EXPECT_TRUE(notMatches(
1319 "template<typename T, typename U> class A {};"
1321 templateSpecializationType(hasTemplateArgument(
1322 1, refersToType(asString("int"))))));
1324 EXPECT_TRUE(matches(
1325 "template<typename T> void f() {};"
1326 "void func() { f<int>(); }",
1327 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1328 EXPECT_TRUE(notMatches(
1329 "template<typename T> void f() {};",
1330 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1333 TEST(TemplateArgument
, Matches
) {
1334 EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
1335 classTemplateSpecializationDecl(
1336 hasAnyTemplateArgument(templateArgument()))));
1337 EXPECT_TRUE(matches(
1338 "template<typename T> struct C {}; C<int> c;",
1339 templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
1341 EXPECT_TRUE(matches(
1342 "template<typename T> void f() {};"
1343 "void func() { f<int>(); }",
1344 functionDecl(hasAnyTemplateArgument(templateArgument()))));
1347 TEST(TemplateTypeParmDecl
, CXXMethodDecl
) {
1348 const char input
[] =
1349 "template<typename T>\n"
1353 "template<typename U>\n"
1354 "void Class<U>::method() {}\n";
1355 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1356 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1359 TEST(TemplateTypeParmDecl
, VarDecl
) {
1360 const char input
[] =
1361 "template<typename T>\n"
1365 "template<typename U>\n"
1366 "U Class<U>::pi = U(3.1415926535897932385);\n";
1367 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1368 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1371 TEST(TemplateTypeParmDecl
, VarTemplatePartialSpecializationDecl
) {
1372 const char input
[] =
1373 "template<typename T>\n"
1375 " template<typename T2> static int field;\n"
1377 "template<typename U>\n"
1378 "template<typename U2>\n"
1379 "int Struct<U>::field<U2*> = 123;\n";
1381 matches(input
, templateTypeParmDecl(hasName("T")), langCxx14OrLater()));
1383 matches(input
, templateTypeParmDecl(hasName("T2")), langCxx14OrLater()));
1385 matches(input
, templateTypeParmDecl(hasName("U")), langCxx14OrLater()));
1387 matches(input
, templateTypeParmDecl(hasName("U2")), langCxx14OrLater()));
1390 TEST(TemplateTypeParmDecl
, ClassTemplatePartialSpecializationDecl
) {
1391 const char input
[] =
1392 "template<typename T>\n"
1394 " template<typename T2> struct Struct;\n"
1396 "template<typename U>\n"
1397 "template<typename U2>\n"
1398 "struct Class<U>::Struct<U2*> {};\n";
1399 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1400 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T2"))));
1401 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1402 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U2"))));
1405 TEST(TemplateTypeParmDecl
, EnumDecl
) {
1406 const char input
[] =
1407 "template<typename T>\n"
1409 " enum class Enum : T;\n"
1411 "template<typename U>\n"
1412 "enum class Struct<U>::Enum : U {\n"
1416 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1417 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1420 TEST(TemplateTypeParmDecl
, RecordDecl
) {
1421 const char input
[] =
1422 "template<typename T>\n"
1426 "template<typename U>\n"
1427 "struct Class<U>::Struct {\n"
1430 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("T"))));
1431 EXPECT_TRUE(matches(input
, templateTypeParmDecl(hasName("U"))));
1434 TEST(RefersToIntegralType
, Matches
) {
1435 EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1436 classTemplateSpecializationDecl(
1437 hasAnyTemplateArgument(refersToIntegralType(
1438 asString("int"))))));
1439 EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",
1440 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1441 refersToIntegralType(asString("int"))))));
1444 TEST(ConstructorDeclaration
, SimpleCase
) {
1445 EXPECT_TRUE(matches("class Foo { Foo(int i); };",
1446 cxxConstructorDecl(ofClass(hasName("Foo")))));
1447 EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
1448 cxxConstructorDecl(ofClass(hasName("Bar")))));
1451 TEST(DestructorDeclaration
, MatchesVirtualDestructor
) {
1452 EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
1453 cxxDestructorDecl(ofClass(hasName("Foo")))));
1456 TEST(DestructorDeclaration
, DoesNotMatchImplicitDestructor
) {
1457 EXPECT_TRUE(notMatches("class Foo {};",
1458 cxxDestructorDecl(ofClass(hasName("Foo")))));
1461 TEST(HasAnyConstructorInitializer
, SimpleCase
) {
1463 notMatches("class Foo { Foo() { } };",
1464 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1466 matches("class Foo {"
1467 " Foo() : foo_() { }"
1470 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1473 TEST(HasAnyConstructorInitializer
, ForField
) {
1474 static const char Code
[] =
1477 " Foo() : foo_(), bar_() { }"
1483 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1484 forField(hasType(recordDecl(hasName("Baz"))))))));
1485 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1486 forField(hasName("foo_"))))));
1487 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1488 forField(hasName("bar_"))))));
1489 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1490 forField(hasType(recordDecl(hasName("Bar"))))))));
1493 TEST(HasAnyConstructorInitializer
, WithInitializer
) {
1494 static const char Code
[] =
1496 " Foo() : foo_(0) { }"
1499 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1500 withInitializer(integerLiteral(equals(0)))))));
1501 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1502 withInitializer(integerLiteral(equals(1)))))));
1505 TEST(HasAnyConstructorInitializer
, IsWritten
) {
1506 static const char Code
[] =
1507 "struct Bar { Bar(){} };"
1509 " Foo() : foo_() { }"
1513 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1514 allOf(forField(hasName("foo_")), isWritten())))));
1515 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1516 allOf(forField(hasName("bar_")), isWritten())))));
1517 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(hasAnyConstructorInitializer(
1518 allOf(forField(hasName("bar_")), unless(isWritten()))))));
1521 TEST(HasAnyConstructorInitializer
, IsBaseInitializer
) {
1522 static const char Code
[] =
1526 " D(int i) : I(i) {}"
1531 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(allOf(
1532 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1534 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(allOf(
1535 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1537 EXPECT_TRUE(matches(Code
, cxxConstructorDecl(allOf(
1538 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1540 EXPECT_TRUE(notMatches(Code
, cxxConstructorDecl(allOf(
1541 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1545 TEST(IfStmt
, ChildTraversalMatchers
) {
1546 EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
1547 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1548 EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
1549 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1550 EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
1551 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1552 EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
1553 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1556 TEST(MatchBinaryOperator
, HasOperatorName
) {
1557 StatementMatcher OperatorOr
= binaryOperator(hasOperatorName("||"));
1559 EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr
));
1560 EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr
));
1563 TEST(MatchBinaryOperator
, HasAnyOperatorName
) {
1564 StatementMatcher Matcher
=
1565 binaryOperator(hasAnyOperatorName("+", "-", "*", "/"));
1567 EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher
));
1568 EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher
));
1569 EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher
));
1570 EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher
));
1571 EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher
));
1572 // Ensure '+= isn't mistaken.
1573 EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher
));
1576 TEST(MatchBinaryOperator
, HasLHSAndHasRHS
) {
1577 StatementMatcher OperatorTrueFalse
=
1578 binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),
1579 hasRHS(cxxBoolLiteral(equals(false))));
1581 EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse
));
1582 EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse
));
1583 EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse
));
1585 StatementMatcher OperatorIntPointer
= arraySubscriptExpr(
1586 hasLHS(hasType(isInteger())),
1587 traverse(TK_AsIs
, hasRHS(hasType(pointsTo(qualType())))));
1588 EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer
));
1589 EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer
));
1591 StringRef Code
= R
"cpp(
1594 bool operator==(const HasOpEqMem& other) const
1603 bool operator==(const HasOpFree& lhs, const HasOpFree& rhs)
1624 auto s1Expr
= declRefExpr(to(varDecl(hasName("s1"))));
1625 auto s2Expr
= declRefExpr(to(varDecl(hasName("s2"))));
1626 EXPECT_TRUE(matches(
1628 traverse(TK_IgnoreUnlessSpelledInSource
,
1629 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1630 hasOperatorName("=="), hasLHS(s1Expr
),
1632 EXPECT_TRUE(matches(
1633 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1634 cxxOperatorCallExpr(
1635 forFunction(functionDecl(hasName("opMem"))),
1636 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr
)))));
1637 EXPECT_TRUE(matches(
1638 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1639 cxxOperatorCallExpr(
1640 forFunction(functionDecl(hasName("opMem"))),
1641 hasOperatorName("=="), hasOperands(s1Expr
, s2Expr
)))));
1642 EXPECT_TRUE(matches(
1643 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1644 cxxOperatorCallExpr(
1645 forFunction(functionDecl(hasName("opMem"))),
1646 hasOperatorName("=="), hasEitherOperand(s2Expr
)))));
1648 EXPECT_TRUE(matches(
1650 traverse(TK_IgnoreUnlessSpelledInSource
,
1651 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1652 hasOperatorName("=="), hasLHS(s1Expr
),
1654 EXPECT_TRUE(matches(
1655 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1656 cxxOperatorCallExpr(
1657 forFunction(functionDecl(hasName("opFree"))),
1658 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr
)))));
1659 EXPECT_TRUE(matches(
1660 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1661 cxxOperatorCallExpr(
1662 forFunction(functionDecl(hasName("opFree"))),
1663 hasOperatorName("=="), hasOperands(s1Expr
, s2Expr
)))));
1664 EXPECT_TRUE(matches(
1665 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1666 cxxOperatorCallExpr(
1667 forFunction(functionDecl(hasName("opFree"))),
1668 hasOperatorName("=="), hasEitherOperand(s2Expr
)))));
1671 TEST(MatchBinaryOperator
, HasEitherOperand
) {
1672 StatementMatcher HasOperand
=
1673 binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));
1675 EXPECT_TRUE(matches("void x() { true || false; }", HasOperand
));
1676 EXPECT_TRUE(matches("void x() { false && true; }", HasOperand
));
1677 EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand
));
1680 TEST(MatchBinaryOperator
, HasOperands
) {
1681 StatementMatcher HasOperands
= binaryOperator(
1682 hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2))));
1683 EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands
));
1684 EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands
));
1685 EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands
));
1686 EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands
));
1687 EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands
));
1688 EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands
));
1691 TEST(Matcher
, BinaryOperatorTypes
) {
1692 // Integration test that verifies the AST provides all binary operators in
1694 // FIXME: Operator ','
1696 matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));
1698 matches("bool b; bool c = (b = true);",
1699 binaryOperator(hasOperatorName("="))));
1701 matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));
1703 matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));
1704 EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));
1706 matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));
1708 matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));
1710 matches("int i = 1; int j = (i <<= 2);",
1711 binaryOperator(hasOperatorName("<<="))));
1712 EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));
1714 matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));
1716 matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));
1718 matches("int i = 1; int j = (i >>= 2);",
1719 binaryOperator(hasOperatorName(">>="))));
1721 matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));
1723 matches("int i = 42; int j = (i ^= 42);",
1724 binaryOperator(hasOperatorName("^="))));
1726 matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));
1728 matches("int i = 42; int j = (i %= 42);",
1729 binaryOperator(hasOperatorName("%="))));
1731 matches("bool b = 42 &23;", binaryOperator(hasOperatorName("&"))));
1733 matches("bool b = true && false;",
1734 binaryOperator(hasOperatorName("&&"))));
1736 matches("bool b = true; bool c = (b &= false);",
1737 binaryOperator(hasOperatorName("&="))));
1739 matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));
1741 matches("bool b = true || false;",
1742 binaryOperator(hasOperatorName("||"))));
1744 matches("bool b = true; bool c = (b |= false);",
1745 binaryOperator(hasOperatorName("|="))));
1747 matches("int i = 42 *23;", binaryOperator(hasOperatorName("*"))));
1749 matches("int i = 42; int j = (i *= 23);",
1750 binaryOperator(hasOperatorName("*="))));
1752 matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));
1754 matches("int i = 42; int j = (i /= 23);",
1755 binaryOperator(hasOperatorName("/="))));
1757 matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));
1759 matches("int i = 42; int j = (i += 23);",
1760 binaryOperator(hasOperatorName("+="))));
1762 matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));
1764 matches("int i = 42; int j = (i -= 23);",
1765 binaryOperator(hasOperatorName("-="))));
1767 matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",
1768 binaryOperator(hasOperatorName("->*"))));
1770 matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",
1771 binaryOperator(hasOperatorName(".*"))));
1773 // Member expressions as operators are not supported in matches.
1775 notMatches("struct A { void x(A *a) { a->x(this); } };",
1776 binaryOperator(hasOperatorName("->"))));
1778 // Initializer assignments are not represented as operator equals.
1780 notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));
1782 // Array indexing is not represented as operator.
1783 EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));
1785 // Overloaded operators do not match at all.
1786 EXPECT_TRUE(notMatches(
1787 "struct A { bool operator&&(const A &a) const { return false; } };"
1788 "void x() { A a, b; a && b; }",
1792 TEST(MatchUnaryOperator
, HasOperatorName
) {
1793 StatementMatcher OperatorNot
= unaryOperator(hasOperatorName("!"));
1795 EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot
));
1796 EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot
));
1799 TEST(MatchUnaryOperator
, HasAnyOperatorName
) {
1800 StatementMatcher Matcher
= unaryOperator(hasAnyOperatorName("-", "*", "++"));
1802 EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher
));
1803 EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher
));
1804 EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher
));
1805 EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher
));
1806 EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher
));
1807 EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher
));
1808 EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher
));
1811 TEST(MatchUnaryOperator
, HasUnaryOperand
) {
1812 StatementMatcher OperatorOnFalse
=
1813 unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));
1815 EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse
));
1816 EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse
));
1818 StringRef Code
= R
"cpp(
1821 bool operator!() const
1826 struct HasOpBangFree
1829 bool operator!(HasOpBangFree const&)
1847 auto s1Expr
= declRefExpr(to(varDecl(hasName("s1"))));
1848 EXPECT_TRUE(matches(
1849 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1850 cxxOperatorCallExpr(
1851 forFunction(functionDecl(hasName("opMem"))),
1852 hasOperatorName("!"), hasUnaryOperand(s1Expr
)))));
1853 EXPECT_TRUE(matches(
1855 traverse(TK_IgnoreUnlessSpelledInSource
,
1856 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1857 hasAnyOperatorName("+", "!"),
1858 hasUnaryOperand(s1Expr
)))));
1860 EXPECT_TRUE(matches(
1861 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1862 cxxOperatorCallExpr(
1863 forFunction(functionDecl(hasName("opFree"))),
1864 hasOperatorName("!"), hasUnaryOperand(s1Expr
)))));
1865 EXPECT_TRUE(matches(
1867 traverse(TK_IgnoreUnlessSpelledInSource
,
1868 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1869 hasAnyOperatorName("+", "!"),
1870 hasUnaryOperand(s1Expr
)))));
1873 struct HasIncOperatorsMem
1875 HasIncOperatorsMem& operator++();
1876 HasIncOperatorsMem operator++(int);
1878 struct HasIncOperatorsFree
1881 HasIncOperatorsFree& operator++(HasIncOperatorsFree&);
1882 HasIncOperatorsFree operator++(HasIncOperatorsFree&, int);
1884 void prefixIncOperatorMem()
1886 HasIncOperatorsMem s1;
1889 void prefixIncOperatorFree()
1891 HasIncOperatorsFree s1;
1894 void postfixIncOperatorMem()
1896 HasIncOperatorsMem s1;
1899 void postfixIncOperatorFree()
1901 HasIncOperatorsFree s1;
1907 HasOpPlusInt& operator+(int);
1909 void plusIntOperator()
1916 EXPECT_TRUE(matches(
1918 traverse(TK_IgnoreUnlessSpelledInSource
,
1919 cxxOperatorCallExpr(
1920 forFunction(functionDecl(hasName("prefixIncOperatorMem"))),
1921 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1923 EXPECT_TRUE(matches(
1925 traverse(TK_IgnoreUnlessSpelledInSource
,
1926 cxxOperatorCallExpr(
1927 forFunction(functionDecl(hasName("prefixIncOperatorFree"))),
1928 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1930 EXPECT_TRUE(matches(
1932 traverse(TK_IgnoreUnlessSpelledInSource
,
1933 cxxOperatorCallExpr(
1934 forFunction(functionDecl(hasName("postfixIncOperatorMem"))),
1935 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1937 EXPECT_TRUE(matches(
1939 traverse(TK_IgnoreUnlessSpelledInSource
,
1940 cxxOperatorCallExpr(
1941 forFunction(functionDecl(hasName("postfixIncOperatorFree"))),
1942 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1944 EXPECT_FALSE(matches(
1945 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1946 cxxOperatorCallExpr(
1947 forFunction(functionDecl(hasName("plusIntOperator"))),
1948 hasOperatorName("+"), hasUnaryOperand(expr())))));
1963 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
1964 cxxOperatorCallExpr(hasOperatorName("*"),
1965 hasUnaryOperand(expr())))));
1968 TEST(Matcher
, UnaryOperatorTypes
) {
1969 // Integration test that verifies the AST provides all unary operators in
1971 EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));
1973 matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));
1974 EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));
1976 matches("bool *p; bool b = *p;", unaryOperator(hasOperatorName("*"))));
1978 matches("int i; int j = +i;", unaryOperator(hasOperatorName("+"))));
1980 matches("int i; int j = -i;", unaryOperator(hasOperatorName("-"))));
1982 matches("int i; int j = ++i;", unaryOperator(hasOperatorName("++"))));
1984 matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));
1986 matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));
1988 matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));
1990 // We don't match conversion operators.
1991 EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));
1993 // Function calls are not represented as operator.
1994 EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));
1996 // Overloaded operators do not match at all.
1997 // FIXME: We probably want to add that.
1998 EXPECT_TRUE(notMatches(
1999 "struct A { bool operator!() const { return false; } };"
2000 "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
2003 TEST(ArraySubscriptMatchers
, ArrayIndex
) {
2004 EXPECT_TRUE(matches(
2005 "int i[2]; void f() { i[1] = 1; }",
2006 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2007 EXPECT_TRUE(matches(
2008 "int i[2]; void f() { 1[i] = 1; }",
2009 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2010 EXPECT_TRUE(notMatches(
2011 "int i[2]; void f() { i[1] = 1; }",
2012 arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));
2015 TEST(ArraySubscriptMatchers
, MatchesArrayBase
) {
2017 matches("int i[2]; void f() { i[1] = 2; }",
2018 traverse(TK_AsIs
, arraySubscriptExpr(hasBase(implicitCastExpr(
2019 hasSourceExpression(declRefExpr())))))));
2022 TEST(Matcher
, OfClass
) {
2023 StatementMatcher Constructor
= cxxConstructExpr(hasDeclaration(cxxMethodDecl(
2024 ofClass(hasName("X")))));
2027 matches("class X { public: X(); }; void x(int) { X x; }", Constructor
));
2029 matches("class X { public: X(); }; void x(int) { X x = X(); }",
2032 notMatches("class Y { public: Y(); }; void x(int) { Y y; }",
2036 TEST(Matcher
, VisitsTemplateInstantiations
) {
2037 EXPECT_TRUE(matches(
2038 "class A { public: void x(); };"
2039 "template <typename T> class B { public: void y() { T t; t.x(); } };"
2040 "void f() { B<A> b; b.y(); }",
2041 callExpr(callee(cxxMethodDecl(hasName("x"))))));
2043 EXPECT_TRUE(matches(
2044 "class A { public: void x(); };"
2047 " template <typename T> class B { public: void y() { T t; t.x(); } };"
2050 " C::B<A> b; b.y();"
2052 recordDecl(hasName("C"), hasDescendant(callExpr(
2053 callee(cxxMethodDecl(hasName("x"))))))));
2056 TEST(Matcher
, HasCondition
) {
2057 StatementMatcher IfStmt
=
2058 ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
2059 EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt
));
2060 EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt
));
2062 StatementMatcher ForStmt
=
2063 forStmt(hasCondition(cxxBoolLiteral(equals(true))));
2064 EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt
));
2065 EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt
));
2067 StatementMatcher WhileStmt
=
2068 whileStmt(hasCondition(cxxBoolLiteral(equals(true))));
2069 EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt
));
2070 EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt
));
2072 StatementMatcher SwitchStmt
=
2073 switchStmt(hasCondition(integerLiteral(equals(42))));
2074 EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt
));
2075 EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt
));
2078 TEST(For
, ForLoopInternals
) {
2079 EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
2080 forStmt(hasCondition(anything()))));
2081 EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
2082 forStmt(hasLoopInit(anything()))));
2085 TEST(For
, ForRangeLoopInternals
) {
2086 EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
2087 cxxForRangeStmt(hasLoopVariable(anything()))));
2088 EXPECT_TRUE(matches(
2089 "void f(){ int a[] {1, 2}; for (int i : a); }",
2090 cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
2093 TEST(For
, NegativeForLoopInternals
) {
2094 EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
2095 forStmt(hasCondition(expr()))));
2096 EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
2097 forStmt(hasLoopInit(anything()))));
2100 TEST(HasBody
, FindsBodyOfForWhileDoLoops
) {
2101 EXPECT_TRUE(matches("void f() { for(;;) {} }",
2102 forStmt(hasBody(compoundStmt()))));
2103 EXPECT_TRUE(notMatches("void f() { for(;;); }",
2104 forStmt(hasBody(compoundStmt()))));
2105 EXPECT_TRUE(matches("void f() { while(true) {} }",
2106 whileStmt(hasBody(compoundStmt()))));
2107 EXPECT_TRUE(matches("void f() { do {} while(true); }",
2108 doStmt(hasBody(compoundStmt()))));
2109 EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
2110 cxxForRangeStmt(hasBody(compoundStmt()))));
2113 TEST(HasBody
, FindsBodyOfFunctions
) {
2114 EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));
2115 EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));
2116 EXPECT_TRUE(matchAndVerifyResultTrue(
2117 "void f(); void f() {}",
2118 functionDecl(hasBody(compoundStmt())).bind("func"),
2119 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("func", 1)));
2120 EXPECT_TRUE(matchAndVerifyResultTrue(
2121 "class C { void f(); }; void C::f() {}",
2122 cxxMethodDecl(hasBody(compoundStmt())).bind("met"),
2123 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("met", 1)));
2124 EXPECT_TRUE(matchAndVerifyResultTrue(
2125 "class C { C(); }; C::C() {}",
2126 cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),
2127 std::make_unique
<VerifyIdIsBoundTo
<CXXConstructorDecl
>>("ctr", 1)));
2128 EXPECT_TRUE(matchAndVerifyResultTrue(
2129 "class C { ~C(); }; C::~C() {}",
2130 cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),
2131 std::make_unique
<VerifyIdIsBoundTo
<CXXDestructorDecl
>>("dtr", 1)));
2134 TEST(HasAnyBody
, FindsAnyBodyOfFunctions
) {
2135 EXPECT_TRUE(matches("void f() {}", functionDecl(hasAnyBody(compoundStmt()))));
2136 EXPECT_TRUE(notMatches("void f();",
2137 functionDecl(hasAnyBody(compoundStmt()))));
2138 EXPECT_TRUE(matchAndVerifyResultTrue(
2139 "void f(); void f() {}",
2140 functionDecl(hasAnyBody(compoundStmt())).bind("func"),
2141 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("func", 2)));
2142 EXPECT_TRUE(matchAndVerifyResultTrue(
2143 "class C { void f(); }; void C::f() {}",
2144 cxxMethodDecl(hasAnyBody(compoundStmt())).bind("met"),
2145 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("met", 2)));
2146 EXPECT_TRUE(matchAndVerifyResultTrue(
2147 "class C { C(); }; C::C() {}",
2148 cxxConstructorDecl(hasAnyBody(compoundStmt())).bind("ctr"),
2149 std::make_unique
<VerifyIdIsBoundTo
<CXXConstructorDecl
>>("ctr", 2)));
2150 EXPECT_TRUE(matchAndVerifyResultTrue(
2151 "class C { ~C(); }; C::~C() {}",
2152 cxxDestructorDecl(hasAnyBody(compoundStmt())).bind("dtr"),
2153 std::make_unique
<VerifyIdIsBoundTo
<CXXDestructorDecl
>>("dtr", 2)));
2156 TEST(HasAnySubstatement
, MatchesForTopLevelCompoundStatement
) {
2157 // The simplest case: every compound statement is in a function
2158 // definition, and the function body itself must be a compound
2160 EXPECT_TRUE(matches("void f() { for (;;); }",
2161 compoundStmt(hasAnySubstatement(forStmt()))));
2164 TEST(HasAnySubstatement
, IsNotRecursive
) {
2165 // It's really "has any immediate substatement".
2166 EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
2167 compoundStmt(hasAnySubstatement(forStmt()))));
2170 TEST(HasAnySubstatement
, MatchesInNestedCompoundStatements
) {
2171 EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
2172 compoundStmt(hasAnySubstatement(forStmt()))));
2175 TEST(HasAnySubstatement
, FindsSubstatementBetweenOthers
) {
2176 EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
2177 compoundStmt(hasAnySubstatement(forStmt()))));
2180 TEST(Member
, MatchesMemberAllocationFunction
) {
2181 // Fails in C++11 mode
2182 EXPECT_TRUE(matchesConditionally(
2183 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2184 "class X { void *operator new(std::size_t); };",
2185 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2187 EXPECT_TRUE(matches("class X { void operator delete(void*); };",
2188 cxxMethodDecl(ofClass(hasName("X")))));
2190 // Fails in C++11 mode
2191 EXPECT_TRUE(matchesConditionally(
2192 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2193 "class X { void operator delete[](void*, std::size_t); };",
2194 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2197 TEST(HasDestinationType
, MatchesSimpleCase
) {
2198 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
2199 cxxStaticCastExpr(hasDestinationType(
2200 pointsTo(TypeMatcher(anything()))))));
2203 TEST(HasImplicitDestinationType
, MatchesSimpleCase
) {
2204 // This test creates an implicit const cast.
2205 EXPECT_TRUE(matches(
2206 "int x; const int i = x;",
2208 implicitCastExpr(hasImplicitDestinationType(isInteger())))));
2209 // This test creates an implicit array-to-pointer cast.
2211 matches("int arr[3]; int *p = arr;",
2212 traverse(TK_AsIs
, implicitCastExpr(hasImplicitDestinationType(
2213 pointsTo(TypeMatcher(anything())))))));
2216 TEST(HasImplicitDestinationType
, DoesNotMatchIncorrectly
) {
2217 // This test creates an implicit cast from int to char.
2218 EXPECT_TRUE(notMatches("char c = 0;",
2219 implicitCastExpr(hasImplicitDestinationType(
2220 unless(anything())))));
2221 // This test creates an implicit array-to-pointer cast.
2222 EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
2223 implicitCastExpr(hasImplicitDestinationType(
2224 unless(anything())))));
2227 TEST(Matcher
, IgnoresElidableConstructors
) {
2229 matches("struct H {};"
2230 "template<typename T> H B(T A);"
2235 cxxOperatorCallExpr(hasArgument(
2236 1, callExpr(hasArgument(
2237 0, ignoringElidableConstructorCall(callExpr()))))),
2238 langCxx11OrLater()));
2240 matches("struct H {};"
2241 "template<typename T> H B(T A);"
2246 cxxOperatorCallExpr(hasArgument(
2247 1, callExpr(hasArgument(0, ignoringElidableConstructorCall(
2248 integerLiteral()))))),
2249 langCxx11OrLater()));
2250 EXPECT_TRUE(matches(
2256 varDecl(hasInitializer(anyOf(
2257 ignoringElidableConstructorCall(callExpr()),
2258 exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())))))),
2259 langCxx11OrLater()));
2262 TEST(Matcher
, IgnoresElidableInReturn
) {
2263 auto matcher
= expr(ignoringElidableConstructorCall(declRefExpr()));
2264 EXPECT_TRUE(matches("struct H {};"
2269 matcher
, langCxx11OrLater()));
2270 EXPECT_TRUE(notMatches("struct H {};"
2274 matcher
, langCxx11OrLater()));
2277 TEST(Matcher
, IgnoreElidableConstructorDoesNotMatchConstructors
) {
2278 EXPECT_TRUE(matches("struct H {};"
2282 varDecl(hasInitializer(
2283 ignoringElidableConstructorCall(cxxConstructExpr()))),
2284 langCxx11OrLater()));
2287 TEST(Matcher
, IgnoresElidableDoesNotPreventMatches
) {
2288 EXPECT_TRUE(matches("void f() {"
2291 expr(ignoringElidableConstructorCall(integerLiteral())),
2292 langCxx11OrLater()));
2295 TEST(Matcher
, IgnoresElidableInVarInit
) {
2297 varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())));
2298 EXPECT_TRUE(matches("struct H {};"
2300 "void f(H D = G()) {"
2303 matcher
, langCxx11OrLater()));
2304 EXPECT_TRUE(matches("struct H {};"
2309 matcher
, langCxx11OrLater()));
2312 TEST(IgnoringImplicit
, MatchesImplicit
) {
2313 EXPECT_TRUE(matches("class C {}; C a = C();",
2314 varDecl(has(ignoringImplicit(cxxConstructExpr())))));
2317 TEST(IgnoringImplicit
, MatchesNestedImplicit
) {
2318 StringRef Code
= R
"(
2325 SomeType(const OtherType&) {}
2326 SomeType& operator=(OtherType const&) { return *this; }
2335 OtherType something()
2342 SomeType i = something();
2345 EXPECT_TRUE(matches(
2348 varDecl(hasName("i"),
2349 hasInitializer(exprWithCleanups(has(cxxConstructExpr(
2350 has(expr(ignoringImplicit(cxxConstructExpr(has(
2351 expr(ignoringImplicit(callExpr())))))))))))))));
2354 TEST(IgnoringImplicit
, DoesNotMatchIncorrectly
) {
2355 EXPECT_TRUE(notMatches("class C {}; C a = C();",
2356 traverse(TK_AsIs
, varDecl(has(cxxConstructExpr())))));
2359 TEST(Traversal
, traverseMatcher
) {
2361 StringRef VarDeclCode
= R
"cpp(
2368 auto Matcher
= varDecl(hasInitializer(floatLiteral()));
2370 EXPECT_TRUE(notMatches(VarDeclCode
, traverse(TK_AsIs
, Matcher
)));
2372 matches(VarDeclCode
, traverse(TK_IgnoreUnlessSpelledInSource
, Matcher
)));
2374 auto ParentMatcher
= floatLiteral(hasParent(varDecl(hasName("i"))));
2376 EXPECT_TRUE(notMatches(VarDeclCode
, traverse(TK_AsIs
, ParentMatcher
)));
2377 EXPECT_TRUE(matches(VarDeclCode
,
2378 traverse(TK_IgnoreUnlessSpelledInSource
, ParentMatcher
)));
2380 EXPECT_TRUE(matches(
2381 VarDeclCode
, decl(traverse(TK_AsIs
, anyOf(cxxRecordDecl(), varDecl())))));
2384 matches(VarDeclCode
,
2385 floatLiteral(traverse(TK_AsIs
, hasParent(implicitCastExpr())))));
2388 matches(VarDeclCode
, floatLiteral(traverse(TK_IgnoreUnlessSpelledInSource
,
2389 hasParent(varDecl())))));
2392 matches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2393 unless(parmVarDecl())))));
2396 notMatches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2397 has(implicitCastExpr())))));
2399 EXPECT_TRUE(matches(VarDeclCode
,
2400 varDecl(traverse(TK_AsIs
, has(implicitCastExpr())))));
2402 EXPECT_TRUE(matches(
2403 VarDeclCode
, traverse(TK_IgnoreUnlessSpelledInSource
,
2404 // The has() below strips away the ImplicitCastExpr
2405 // before the traverse(AsIs) gets to process it.
2406 varDecl(has(traverse(TK_AsIs
, floatLiteral()))))));
2409 matches(VarDeclCode
, functionDecl(traverse(TK_AsIs
, hasName("foo")))));
2411 EXPECT_TRUE(matches(
2413 functionDecl(traverse(TK_IgnoreUnlessSpelledInSource
, hasName("foo")))));
2415 EXPECT_TRUE(matches(
2416 VarDeclCode
, functionDecl(traverse(TK_AsIs
, hasAnyName("foo", "bar")))));
2419 matches(VarDeclCode
, functionDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2420 hasAnyName("foo", "bar")))));
2422 StringRef Code
= R
"cpp(
2433 matches(Code
, callExpr(traverse(TK_IgnoreUnlessSpelledInSource
,
2434 hasArgument(0, floatLiteral())))));
2437 matches(Code
, callExpr(traverse(TK_IgnoreUnlessSpelledInSource
,
2438 hasAnyArgument(floatLiteral())))));
2440 EXPECT_TRUE(matches(
2442 void takesBool(bool){}
2444 template <typename T>
2445 void neverInstantiatedTemplate() {
2449 traverse(TK_IgnoreUnlessSpelledInSource
,
2450 callExpr(unless(callExpr(hasDeclaration(functionDecl())))))));
2453 matches(VarDeclCode
, varDecl(traverse(TK_IgnoreUnlessSpelledInSource
,
2454 hasType(builtinType())))));
2457 matches(VarDeclCode
,
2458 functionDecl(hasName("foo"),
2459 traverse(TK_AsIs
, hasDescendant(floatLiteral())))));
2461 EXPECT_TRUE(notMatches(
2462 Code
, traverse(TK_AsIs
, floatLiteral(hasParent(callExpr(
2463 callee(functionDecl(hasName("foo")))))))));
2464 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2465 floatLiteral(hasParent(callExpr(callee(
2466 functionDecl(hasName("foo")))))))));
2474 EXPECT_TRUE(matches(
2475 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2476 varDecl(hasInitializer(integerLiteral(equals(3)))))));
2477 EXPECT_TRUE(matches(
2479 traverse(TK_IgnoreUnlessSpelledInSource
,
2480 integerLiteral(equals(3), hasParent(varDecl(hasName("i")))))));
2483 const char *SomeString{"str
"};
2486 matches(Code
, traverse(TK_AsIs
, stringLiteral(hasParent(implicitCastExpr(
2487 hasParent(initListExpr())))))));
2489 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2490 stringLiteral(hasParent(initListExpr())))));
2495 String(const char*, int = -1) {}
2498 void stringConstruct()
2504 EXPECT_TRUE(matches(
2509 hasName("stringConstruct"),
2510 hasDescendant(varDecl(
2512 hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(
2513 0, ignoringImplicit(cxxConstructExpr(hasArgument(
2514 0, ignoringImplicit(stringLiteral()))))))))))))));
2516 EXPECT_TRUE(matches(
2520 functionDecl(hasName("stringConstruct"),
2521 hasDescendant(cxxOperatorCallExpr(
2522 isAssignmentOperator(),
2523 hasArgument(1, ignoringImplicit(
2524 cxxConstructExpr(hasArgument(
2525 0, ignoringImplicit(stringLiteral())))))
2528 EXPECT_TRUE(matches(
2529 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2530 functionDecl(hasName("stringConstruct"),
2531 hasDescendant(varDecl(
2533 hasInitializer(stringLiteral())))))));
2536 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2537 functionDecl(hasName("stringConstruct"),
2538 hasDescendant(cxxOperatorCallExpr(
2539 isAssignmentOperator(),
2540 hasArgument(1, stringLiteral())))))));
2545 struct C2 { operator C1(); };
2547 void conversionOperator()
2554 EXPECT_TRUE(matches(
2559 hasName("conversionOperator"),
2564 ignoringImplicit(cxxConstructExpr(hasArgument(
2565 0, ignoringImplicit(
2566 cxxMemberCallExpr(onImplicitObjectArgument(
2567 ignoringParenImpCasts(unaryOperator(
2568 hasOperatorName("*")))))))))))
2571 EXPECT_TRUE(matches(
2573 traverse(TK_IgnoreUnlessSpelledInSource
,
2574 functionDecl(hasName("conversionOperator"),
2575 hasDescendant(varDecl(
2576 hasName("c1"), hasInitializer(unaryOperator(
2577 hasOperatorName("*")))))))));
2581 template <unsigned alignment>
2582 void template_test() {
2583 static_assert(alignment, "");
2585 void actual_template_test() {
2590 EXPECT_TRUE(matches(
2593 staticAssertDecl(has(implicitCastExpr(has(
2594 substNonTypeTemplateParmExpr(has(integerLiteral())))))))));
2595 EXPECT_TRUE(matches(
2596 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2597 staticAssertDecl(has(declRefExpr(
2598 to(nonTypeTemplateParmDecl(hasName("alignment"))),
2599 hasType(asString("unsigned int"))))))));
2601 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, staticAssertDecl(hasDescendant(
2602 integerLiteral())))));
2603 EXPECT_FALSE(matches(
2604 Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
2605 staticAssertDecl(hasDescendant(integerLiteral())))));
2609 struct OneParamCtor {
2610 explicit OneParamCtor(int);
2612 struct TwoParamCtor {
2613 explicit TwoParamCtor(int, int);
2616 void varDeclCtors() {
2618 auto var1 = OneParamCtor(5);
2619 auto var2 = TwoParamCtor(6, 7);
2622 OneParamCtor var3(5);
2623 TwoParamCtor var4(6, 7);
2627 auto var5 = OneParamCtor(i);
2628 auto var6 = TwoParamCtor(i, 7);
2631 OneParamCtor var7(i);
2632 TwoParamCtor var8(i, 7);
2637 EXPECT_TRUE(matches(
2639 traverse(TK_AsIs
, varDecl(hasName("var1"), hasInitializer(hasDescendant(
2640 cxxConstructExpr()))))));
2641 EXPECT_TRUE(matches(
2643 traverse(TK_AsIs
, varDecl(hasName("var2"), hasInitializer(hasDescendant(
2644 cxxConstructExpr()))))));
2645 EXPECT_TRUE(matches(
2646 Code
, traverse(TK_AsIs
, varDecl(hasName("var3"),
2647 hasInitializer(cxxConstructExpr())))));
2648 EXPECT_TRUE(matches(
2649 Code
, traverse(TK_AsIs
, varDecl(hasName("var4"),
2650 hasInitializer(cxxConstructExpr())))));
2651 EXPECT_TRUE(matches(
2653 traverse(TK_AsIs
, varDecl(hasName("var5"), hasInitializer(hasDescendant(
2654 cxxConstructExpr()))))));
2655 EXPECT_TRUE(matches(
2657 traverse(TK_AsIs
, varDecl(hasName("var6"), hasInitializer(hasDescendant(
2658 cxxConstructExpr()))))));
2659 EXPECT_TRUE(matches(
2660 Code
, traverse(TK_AsIs
, varDecl(hasName("var7"),
2661 hasInitializer(cxxConstructExpr())))));
2662 EXPECT_TRUE(matches(
2663 Code
, traverse(TK_AsIs
, varDecl(hasName("var8"),
2664 hasInitializer(cxxConstructExpr())))));
2666 EXPECT_TRUE(matches(
2668 traverse(TK_IgnoreUnlessSpelledInSource
,
2669 varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));
2670 EXPECT_TRUE(matches(
2672 traverse(TK_IgnoreUnlessSpelledInSource
,
2673 varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));
2674 EXPECT_TRUE(matches(
2676 traverse(TK_IgnoreUnlessSpelledInSource
,
2677 varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));
2678 EXPECT_TRUE(matches(
2680 traverse(TK_IgnoreUnlessSpelledInSource
,
2681 varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));
2682 EXPECT_TRUE(matches(
2684 traverse(TK_IgnoreUnlessSpelledInSource
,
2685 varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));
2686 EXPECT_TRUE(matches(
2688 traverse(TK_IgnoreUnlessSpelledInSource
,
2689 varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));
2690 EXPECT_TRUE(matches(
2692 traverse(TK_IgnoreUnlessSpelledInSource
,
2693 varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));
2694 EXPECT_TRUE(matches(
2696 traverse(TK_IgnoreUnlessSpelledInSource
,
2697 varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));
2701 template<typename T>
2702 struct TemplStruct {
2712 template<typename T>
2713 void TemplStruct<T>::outOfLine(T)
2718 template<typename T>
2726 TemplStruct<int> ti;
2727 TemplStruct<double> td;
2728 (void)timesTwo<int>(2);
2729 (void)timesTwo<double>(2);
2732 template class TemplStruct<float>;
2734 extern template class TemplStruct<long>;
2736 template<> class TemplStruct<bool> {
2740 void boolSpecializationMethodOnly() {}
2745 template float timesTwo(float);
2746 template<> bool timesTwo<bool>(bool){
2751 auto M
= cxxRecordDecl(hasName("TemplStruct"),
2752 has(fieldDecl(hasType(asString("int")))));
2753 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2754 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2757 auto M
= cxxRecordDecl(hasName("TemplStruct"),
2758 has(fieldDecl(hasType(asString("double")))));
2759 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2760 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2764 functionDecl(hasName("timesTwo"),
2765 hasParameter(0, parmVarDecl(hasType(asString("int")))));
2766 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2767 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2771 functionDecl(hasName("timesTwo"),
2772 hasParameter(0, parmVarDecl(hasType(asString("double")))));
2773 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2774 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2777 // Match on the integer literal in the explicit instantiation:
2779 functionDecl(hasName("timesTwo"),
2780 hasParameter(0, parmVarDecl(hasType(asString("float")))),
2781 hasDescendant(integerLiteral(equals(2))));
2782 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDef
)));
2783 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDef
)));
2786 functionDecl(hasName("timesTwo"),
2787 hasTemplateArgument(0, refersToType(asString("float"))));
2788 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MTempl
)));
2789 // TODO: If we could match on explicit instantiations of function templates,
2790 // this would be EXPECT_TRUE. See Sema::ActOnExplicitInstantiation.
2792 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MTempl
)));
2795 auto M
= functionDecl(hasName("timesTwo"),
2796 hasParameter(0, parmVarDecl(hasType(booleanType()))));
2797 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2798 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2801 // Match on the field within the explicit instantiation:
2802 auto MRecord
= cxxRecordDecl(hasName("TemplStruct"),
2803 has(fieldDecl(hasType(asString("float")))));
2804 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MRecord
)));
2806 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MRecord
)));
2808 // Match on the explicit template instantiation itself:
2809 auto MTempl
= classTemplateSpecializationDecl(
2810 hasName("TemplStruct"),
2811 hasTemplateArgument(0,
2812 templateArgument(refersToType(asString("float")))));
2813 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MTempl
)));
2815 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MTempl
)));
2818 // The template argument is matchable, but the instantiation is not:
2819 auto M
= classTemplateSpecializationDecl(
2820 hasName("TemplStruct"),
2821 hasTemplateArgument(0,
2822 templateArgument(refersToType(asString("float")))),
2823 has(cxxConstructorDecl(hasName("TemplStruct"))));
2824 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2825 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2828 // The template argument is matchable, but the instantiation is not:
2829 auto M
= classTemplateSpecializationDecl(
2830 hasName("TemplStruct"),
2831 hasTemplateArgument(0,
2832 templateArgument(refersToType(asString("long")))),
2833 has(cxxConstructorDecl(hasName("TemplStruct"))));
2834 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2835 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2838 // Instantiated, out-of-line methods are not matchable.
2840 cxxMethodDecl(hasName("outOfLine"), isDefinition(),
2841 hasParameter(0, parmVarDecl(hasType(asString("float")))));
2842 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2843 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2846 // Explicit specialization is written in source and it matches:
2847 auto M
= classTemplateSpecializationDecl(
2848 hasName("TemplStruct"),
2849 hasTemplateArgument(0, templateArgument(refersToType(booleanType()))),
2850 has(cxxConstructorDecl(hasName("TemplStruct"))),
2851 has(cxxMethodDecl(hasName("boolSpecializationMethodOnly"))));
2852 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
2853 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
2861 B func1() { return 42; }
2864 auto M
= expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit")));
2865 EXPECT_TRUE(matchAndVerifyResultTrue(
2866 Code
, traverse(TK_AsIs
, M
),
2867 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2868 EXPECT_TRUE(matchAndVerifyResultTrue(
2869 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2870 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2873 auto M
= expr(unless(integerLiteral(equals(24)))).bind("intLit");
2874 EXPECT_TRUE(matchAndVerifyResultTrue(
2875 Code
, traverse(TK_AsIs
, M
),
2876 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 6)));
2877 EXPECT_TRUE(matchAndVerifyResultTrue(
2878 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2879 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2883 expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr())));
2884 EXPECT_TRUE(matchAndVerifyResultTrue(
2885 Code
, traverse(TK_AsIs
, M
),
2886 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2887 EXPECT_TRUE(matchAndVerifyResultTrue(
2888 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2889 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2892 auto M
= expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr()));
2893 EXPECT_TRUE(matchAndVerifyResultTrue(
2894 Code
, traverse(TK_AsIs
, M
),
2895 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2896 EXPECT_TRUE(matchAndVerifyResultTrue(
2897 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2898 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2901 auto M
= expr(integerLiteral(equals(42)).bind("intLit"), expr());
2902 EXPECT_TRUE(matchAndVerifyResultTrue(
2903 Code
, traverse(TK_AsIs
, M
),
2904 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2905 EXPECT_TRUE(matchAndVerifyResultTrue(
2906 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2907 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2910 auto M
= expr(optionally(integerLiteral(equals(42)).bind("intLit")));
2911 EXPECT_TRUE(matchAndVerifyResultTrue(
2912 Code
, traverse(TK_AsIs
, M
),
2913 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2914 EXPECT_TRUE(matchAndVerifyResultTrue(
2915 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2916 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("intLit", 1)));
2919 auto M
= expr().bind("allExprs");
2920 EXPECT_TRUE(matchAndVerifyResultTrue(
2921 Code
, traverse(TK_AsIs
, M
),
2922 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("allExprs", 6)));
2923 EXPECT_TRUE(matchAndVerifyResultTrue(
2924 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2925 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("allExprs", 1)));
2932 auto &[f, s, t] = arr;
2938 auto M
= bindingDecl(hasName("f"));
2940 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
2942 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2943 true, {"-std=c++17"}));
2946 auto M
= bindingDecl(hasName("f"), has(expr()));
2948 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
2950 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2951 true, {"-std=c++17"}));
2954 auto M
= integerLiteral(hasAncestor(bindingDecl(hasName("f"))));
2956 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
2958 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2959 true, {"-std=c++17"}));
2962 auto M
= declRefExpr(hasAncestor(bindingDecl(hasName("f"))));
2964 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++17"}));
2966 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
2967 true, {"-std=c++17"}));
2971 TEST(Traversal
, traverseNoImplicit
) {
2972 StringRef Code
= R
"cpp(
2975 NonTrivial(const NonTrivial&) {}
2976 NonTrivial& operator=(const NonTrivial&) { return *this; }
2981 struct NoSpecialMethods {
2985 struct ContainsArray {
2987 ContainsArray& operator=(const ContainsArray &other) = default;
2992 NoSpecialMethods nc1;
2993 NoSpecialMethods nc2(nc1);
3001 struct HasCtorInits : NoSpecialMethods, NonTrivial
3005 HasCtorInits() : NoSpecialMethods(), m_i(42) {}
3008 struct CtorInitsNonTrivial : NonTrivial
3012 CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}
3017 auto M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3018 has(cxxRecordDecl(hasName("NoSpecialMethods"))));
3019 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3020 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3022 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3023 has(cxxConstructorDecl(isCopyConstructor())));
3024 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3025 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3027 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3028 has(cxxMethodDecl(isCopyAssignmentOperator())));
3029 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3030 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3032 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3033 has(cxxConstructorDecl(isDefaultConstructor())));
3034 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3035 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3037 M
= cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));
3038 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3039 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3041 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3042 hasMethod(cxxConstructorDecl(isCopyConstructor())));
3043 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3044 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3046 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3047 hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));
3048 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3049 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3051 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3052 hasMethod(cxxConstructorDecl(isDefaultConstructor())));
3053 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3054 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3056 M
= cxxRecordDecl(hasName("NoSpecialMethods"),
3057 hasMethod(cxxDestructorDecl()));
3058 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3059 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3062 // Because the copy-assignment operator is not spelled in the
3063 // source (ie, isImplicit()), we don't match it
3065 cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),
3066 callee(cxxMethodDecl(isCopyAssignmentOperator())));
3067 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3068 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3071 // Compiler generates a forStmt to copy the array
3072 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, forStmt())));
3074 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, forStmt())));
3077 // The defaulted method declaration can be matched, but not its
3078 // definition, in IgnoreUnlessSpelledInSource mode
3079 auto MDecl
= cxxMethodDecl(ofClass(cxxRecordDecl(hasName("ContainsArray"))),
3080 isCopyAssignmentOperator(), isDefaulted());
3082 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDecl
)));
3083 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDecl
)));
3085 auto MDef
= cxxMethodDecl(MDecl
, has(compoundStmt()));
3087 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MDef
)));
3088 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MDef
)));
3090 auto MBody
= cxxMethodDecl(MDecl
, hasBody(compoundStmt()));
3092 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MBody
)));
3094 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MBody
)));
3096 auto MIsDefn
= cxxMethodDecl(MDecl
, isDefinition());
3098 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MIsDefn
)));
3100 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MIsDefn
)));
3102 auto MIsInline
= cxxMethodDecl(MDecl
, isInline());
3104 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, MIsInline
)));
3106 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MIsInline
)));
3108 // The parameter of the defaulted method can still be matched.
3110 cxxMethodDecl(MDecl
, hasParameter(0, parmVarDecl(hasName("other"))));
3112 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, MParm
)));
3113 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, MParm
)));
3117 cxxConstructorDecl(hasName("HasCtorInits"),
3118 has(cxxCtorInitializer(forField(hasName("m_i")))));
3119 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3120 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3124 cxxConstructorDecl(hasName("HasCtorInits"),
3125 has(cxxCtorInitializer(forField(hasName("m_nt")))));
3126 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3127 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3130 auto M
= cxxConstructorDecl(hasName("HasCtorInits"),
3131 hasAnyConstructorInitializer(cxxCtorInitializer(
3132 forField(hasName("m_nt")))));
3133 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3134 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3138 cxxConstructorDecl(hasName("HasCtorInits"),
3139 forEachConstructorInitializer(
3140 cxxCtorInitializer(forField(hasName("m_nt")))));
3141 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3142 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3145 auto M
= cxxConstructorDecl(
3146 hasName("CtorInitsNonTrivial"),
3147 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(
3148 hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));
3149 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3150 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3153 auto M
= cxxConstructorDecl(
3154 hasName("HasCtorInits"),
3155 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(
3156 cxxConstructorDecl(hasName("NoSpecialMethods"))))))));
3157 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3158 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3161 auto M
= cxxCtorInitializer(forField(hasName("m_nt")));
3162 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3163 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3179 auto M
= cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3180 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3181 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3185 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3186 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3187 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3191 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3192 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3193 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3196 auto M
= cxxForRangeStmt(has(declStmt()));
3197 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3198 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3202 cxxForRangeStmt(hasLoopVariable(varDecl(hasName("i"))),
3203 hasRangeInit(declRefExpr(to(varDecl(hasName("arr"))))));
3204 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3205 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3208 auto M
= cxxForRangeStmt(unless(hasInitStatement(stmt())));
3209 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3210 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3213 auto M
= cxxForRangeStmt(hasBody(stmt()));
3214 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3215 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3218 auto M
= cxxForRangeStmt(hasDescendant(ifStmt()));
3219 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3220 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3223 EXPECT_TRUE(matches(
3224 Code
, traverse(TK_AsIs
, cxxForRangeStmt(has(declStmt(
3225 hasSingleDecl(varDecl(hasName("i")))))))));
3227 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3228 cxxForRangeStmt(has(varDecl(hasName("i")))))));
3231 EXPECT_TRUE(matches(
3232 Code
, traverse(TK_AsIs
, cxxForRangeStmt(has(declStmt(hasSingleDecl(
3233 varDecl(hasInitializer(declRefExpr(
3234 to(varDecl(hasName("arr")))))))))))));
3235 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3236 cxxForRangeStmt(has(declRefExpr(
3237 to(varDecl(hasName("arr")))))))));
3240 auto M
= cxxForRangeStmt(has(compoundStmt()));
3241 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3242 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3245 auto M
= binaryOperator(hasOperatorName("!="));
3246 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3247 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3250 auto M
= unaryOperator(hasOperatorName("++"));
3251 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3252 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3255 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__range"))));
3256 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3257 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3260 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__begin"))));
3261 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3262 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3265 auto M
= declStmt(hasSingleDecl(varDecl(matchesName("__end"))));
3266 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3267 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3270 auto M
= ifStmt(hasParent(compoundStmt(hasParent(cxxForRangeStmt()))));
3271 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3272 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3275 auto M
= cxxForRangeStmt(
3276 has(varDecl(hasName("i"), hasParent(cxxForRangeStmt()))));
3277 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3278 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3281 auto M
= cxxForRangeStmt(hasDescendant(varDecl(
3282 hasName("i"), hasParent(declStmt(hasParent(cxxForRangeStmt()))))));
3283 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3284 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3287 auto M
= cxxForRangeStmt(hasRangeInit(declRefExpr(
3288 to(varDecl(hasName("arr"))), hasParent(cxxForRangeStmt()))));
3289 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3290 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3294 auto M
= cxxForRangeStmt(hasRangeInit(declRefExpr(
3295 to(varDecl(hasName("arr"))), hasParent(varDecl(hasParent(declStmt(
3296 hasParent(cxxForRangeStmt()))))))));
3297 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3298 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3306 Range getRange(int);
3310 for (auto i : getRange(42))
3316 auto M
= integerLiteral(equals(42));
3317 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3318 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3321 auto M
= callExpr(hasDescendant(integerLiteral(equals(42))));
3322 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3323 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3326 auto M
= compoundStmt(hasDescendant(integerLiteral(equals(42))));
3327 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3328 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3335 for (auto& a = arr; auto i : a)
3342 auto M
= cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3344 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3346 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3347 true, {"-std=c++20"}));
3351 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3353 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3355 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3356 true, {"-std=c++20"}));
3360 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3362 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3364 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3365 true, {"-std=c++20"}));
3369 cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i"))))));
3371 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3373 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3374 true, {"-std=c++20"}));
3377 auto M
= cxxForRangeStmt(
3378 hasInitStatement(declStmt(hasSingleDecl(varDecl(
3380 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3381 hasLoopVariable(varDecl(hasName("i"))),
3382 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3384 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3386 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3387 true, {"-std=c++20"}));
3390 auto M
= cxxForRangeStmt(
3391 has(declStmt(hasSingleDecl(varDecl(
3393 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3394 hasLoopVariable(varDecl(hasName("i"))),
3395 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3397 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3399 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3400 true, {"-std=c++20"}));
3403 auto M
= cxxForRangeStmt(hasInitStatement(declStmt(
3404 hasSingleDecl(varDecl(hasName("a"))), hasParent(cxxForRangeStmt()))));
3406 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3408 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3409 true, {"-std=c++20"}));
3417 Range getRange(int);
3423 for (auto j = getNum(42); auto i : getRange(j))
3429 auto M
= integerLiteral(equals(42));
3431 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3433 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3434 true, {"-std=c++20"}));
3437 auto M
= compoundStmt(hasDescendant(integerLiteral(equals(42))));
3439 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3441 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3442 true, {"-std=c++20"}));
3446 void hasDefaultArg(int i, int j = 0)
3449 void callDefaultArg()
3454 auto hasDefaultArgCall
= [](auto InnerMatcher
) {
3455 return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),
3459 auto M
= hasDefaultArgCall(has(integerLiteral(equals(42))));
3460 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3461 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3464 auto M
= hasDefaultArgCall(has(cxxDefaultArgExpr()));
3465 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3466 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3469 auto M
= hasDefaultArgCall(argumentCountIs(2));
3470 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3471 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3474 auto M
= hasDefaultArgCall(argumentCountIs(1));
3475 EXPECT_FALSE(matches(Code
, traverse(TK_AsIs
, M
)));
3476 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3479 auto M
= hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));
3480 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3481 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3484 auto M
= hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));
3485 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3486 EXPECT_FALSE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3499 auto M
= cxxDestructorDecl(isDefaulted(),
3500 ofClass(cxxRecordDecl(has(fieldDecl()))));
3501 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, M
)));
3502 EXPECT_TRUE(matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
)));
3507 static constexpr bool getTrue() { return true; }
3512 explicit(S::getTrue()) A();
3518 EXPECT_TRUE(matchesConditionally(
3523 hasExplicitSpecifier(expr(ignoringImplicit(
3524 callExpr(has(ignoringImplicit(declRefExpr())))))))),
3525 true, {"-std=c++20"}));
3526 EXPECT_TRUE(matchesConditionally(
3528 traverse(TK_IgnoreUnlessSpelledInSource
,
3531 hasExplicitSpecifier(callExpr(has(declRefExpr()))))),
3532 true, {"-std=c++20"}));
3536 template <typename MatcherT
>
3537 bool matcherTemplateWithBinding(StringRef Code
, const MatcherT
&M
) {
3538 return matchAndVerifyResultTrue(
3539 Code
, M
.bind("matchedStmt"),
3540 std::make_unique
<VerifyIdIsBoundTo
<ReturnStmt
>>("matchedStmt", 1));
3543 TEST(Traversal
, traverseWithBinding
) {
3544 // Some existing matcher code expects to take a matcher as a
3545 // template arg and bind to it. Verify that that works.
3547 llvm::StringRef Code
= R
"cpp(
3553 EXPECT_TRUE(matcherTemplateWithBinding(
3554 Code
, traverse(TK_AsIs
,
3555 returnStmt(has(implicitCastExpr(has(floatLiteral())))))));
3558 TEST(Traversal
, traverseMatcherNesting
) {
3560 StringRef Code
= R
"cpp(
3573 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
,
3574 callExpr(has(callExpr(traverse(
3575 TK_AsIs
, callExpr(has(implicitCastExpr(
3576 has(floatLiteral())))))))))));
3578 EXPECT_TRUE(matches(
3580 traverse(TK_IgnoreUnlessSpelledInSource
,
3581 traverse(TK_AsIs
, implicitCastExpr(has(floatLiteral()))))));
3584 TEST(Traversal
, traverseMatcherThroughImplicit
) {
3585 StringRef Code
= R
"cpp(
3590 void constructImplicit() {
3596 auto Matcher
= traverse(TK_IgnoreUnlessSpelledInSource
, implicitCastExpr());
3598 // Verfiy that it does not segfault
3599 EXPECT_FALSE(matches(Code
, Matcher
));
3602 TEST(Traversal
, traverseMatcherThroughMemoization
) {
3604 StringRef Code
= R
"cpp(
3611 auto Matcher
= varDecl(hasInitializer(floatLiteral()));
3613 // Matchers such as hasDescendant memoize their result regarding AST
3614 // nodes. In the matcher below, the first use of hasDescendant(Matcher)
3615 // fails, and the use of it inside the traverse() matcher should pass
3616 // causing the overall matcher to be a true match.
3617 // This test verifies that the first false result is not re-used, which
3618 // would cause the overall matcher to be incorrectly false.
3620 EXPECT_TRUE(matches(
3622 functionDecl(anyOf(hasDescendant(Matcher
),
3623 traverse(TK_IgnoreUnlessSpelledInSource
,
3624 functionDecl(hasDescendant(Matcher
)))))));
3627 TEST(Traversal
, traverseUnlessSpelledInSource
) {
3629 StringRef Code
= R
"cpp(
3702 [a, b = c](int d) { int e = d; };
3706 [] <typename TemplateType> (TemplateType t, TemplateType u) { int e = t + u; };
3712 auto l = [&] { ++count; };
3720 traverse(TK_IgnoreUnlessSpelledInSource
,
3721 returnStmt(forFunction(functionDecl(hasName("func1"))),
3722 hasReturnValue(integerLiteral(equals(42))))),
3723 langCxx20OrLater()));
3727 traverse(TK_IgnoreUnlessSpelledInSource
,
3728 integerLiteral(equals(42),
3729 hasParent(returnStmt(forFunction(
3730 functionDecl(hasName("func1"))))))),
3731 langCxx20OrLater()));
3733 EXPECT_TRUE(matches(
3735 traverse(TK_IgnoreUnlessSpelledInSource
,
3736 returnStmt(forFunction(functionDecl(hasName("func2"))),
3737 hasReturnValue(cxxTemporaryObjectExpr(
3738 hasArgument(0, integerLiteral(equals(42))))))),
3739 langCxx20OrLater()));
3740 EXPECT_TRUE(matches(
3743 TK_IgnoreUnlessSpelledInSource
,
3744 integerLiteral(equals(42),
3745 hasParent(cxxTemporaryObjectExpr(hasParent(returnStmt(
3746 forFunction(functionDecl(hasName("func2"))))))))),
3747 langCxx20OrLater()));
3751 traverse(TK_IgnoreUnlessSpelledInSource
,
3752 returnStmt(forFunction(functionDecl(hasName("func3"))),
3753 hasReturnValue(cxxConstructExpr(hasArgument(
3754 0, integerLiteral(equals(42))))))),
3755 langCxx20OrLater()));
3757 EXPECT_TRUE(matches(
3760 TK_IgnoreUnlessSpelledInSource
,
3761 integerLiteral(equals(42),
3762 hasParent(cxxConstructExpr(hasParent(returnStmt(
3763 forFunction(functionDecl(hasName("func3"))))))))),
3764 langCxx20OrLater()));
3768 traverse(TK_IgnoreUnlessSpelledInSource
,
3769 returnStmt(forFunction(functionDecl(hasName("func4"))),
3770 hasReturnValue(cxxTemporaryObjectExpr()))),
3771 langCxx20OrLater()));
3775 traverse(TK_IgnoreUnlessSpelledInSource
,
3776 returnStmt(forFunction(functionDecl(hasName("func5"))),
3777 hasReturnValue(cxxTemporaryObjectExpr()))),
3778 langCxx20OrLater()));
3782 traverse(TK_IgnoreUnlessSpelledInSource
,
3783 returnStmt(forFunction(functionDecl(hasName("func6"))),
3784 hasReturnValue(cxxTemporaryObjectExpr()))),
3785 langCxx20OrLater()));
3789 traverse(TK_IgnoreUnlessSpelledInSource
,
3790 returnStmt(forFunction(functionDecl(hasName("func7"))),
3791 hasReturnValue(cxxTemporaryObjectExpr()))),
3792 langCxx20OrLater()));
3796 traverse(TK_IgnoreUnlessSpelledInSource
,
3797 returnStmt(forFunction(functionDecl(hasName("func8"))),
3798 hasReturnValue(cxxFunctionalCastExpr(
3799 hasSourceExpression(initListExpr()))))),
3800 langCxx20OrLater()));
3804 traverse(TK_IgnoreUnlessSpelledInSource
,
3805 returnStmt(forFunction(functionDecl(hasName("func9"))),
3806 hasReturnValue(cxxFunctionalCastExpr(
3807 hasSourceExpression(initListExpr()))))),
3808 langCxx20OrLater()));
3810 EXPECT_TRUE(matches(
3813 TK_IgnoreUnlessSpelledInSource
,
3814 returnStmt(forFunction(functionDecl(hasName("func10"))),
3815 hasReturnValue(declRefExpr(to(varDecl(hasName("a"))))))),
3816 langCxx20OrLater()));
3820 traverse(TK_IgnoreUnlessSpelledInSource
,
3821 declRefExpr(to(varDecl(hasName("a"))),
3822 hasParent(returnStmt(forFunction(
3823 functionDecl(hasName("func10"))))))),
3824 langCxx20OrLater()));
3826 EXPECT_TRUE(matches(
3829 TK_IgnoreUnlessSpelledInSource
,
3830 returnStmt(forFunction(functionDecl(hasName("func11"))),
3831 hasReturnValue(declRefExpr(to(varDecl(hasName("b"))))))),
3832 langCxx20OrLater()));
3836 traverse(TK_IgnoreUnlessSpelledInSource
,
3837 declRefExpr(to(varDecl(hasName("b"))),
3838 hasParent(returnStmt(forFunction(
3839 functionDecl(hasName("func11"))))))),
3840 langCxx20OrLater()));
3842 EXPECT_TRUE(matches(
3845 TK_IgnoreUnlessSpelledInSource
,
3846 returnStmt(forFunction(functionDecl(hasName("func12"))),
3847 hasReturnValue(declRefExpr(to(varDecl(hasName("c"))))))),
3848 langCxx20OrLater()));
3852 traverse(TK_IgnoreUnlessSpelledInSource
,
3853 declRefExpr(to(varDecl(hasName("c"))),
3854 hasParent(returnStmt(forFunction(
3855 functionDecl(hasName("func12"))))))),
3856 langCxx20OrLater()));
3858 EXPECT_TRUE(matches(
3861 TK_IgnoreUnlessSpelledInSource
,
3862 lambdaExpr(forFunction(functionDecl(hasName("func13"))),
3863 has(compoundStmt(hasDescendant(varDecl(hasName("e"))))),
3864 has(declRefExpr(to(varDecl(hasName("a"))))),
3865 has(varDecl(hasName("b"), hasInitializer(declRefExpr(to(
3866 varDecl(hasName("c"))))))),
3867 has(parmVarDecl(hasName("d"))))),
3868 langCxx20OrLater()));
3872 traverse(TK_IgnoreUnlessSpelledInSource
,
3873 declRefExpr(to(varDecl(hasName("a"))),
3874 hasParent(lambdaExpr(forFunction(
3875 functionDecl(hasName("func13"))))))),
3876 langCxx20OrLater()));
3878 EXPECT_TRUE(matches(
3880 traverse(TK_IgnoreUnlessSpelledInSource
,
3881 varDecl(hasName("b"),
3882 hasInitializer(declRefExpr(to(varDecl(hasName("c"))))),
3883 hasParent(lambdaExpr(
3884 forFunction(functionDecl(hasName("func13"))))))),
3885 langCxx20OrLater()));
3887 EXPECT_TRUE(matches(Code
,
3888 traverse(TK_IgnoreUnlessSpelledInSource
,
3889 compoundStmt(hasParent(lambdaExpr(forFunction(
3890 functionDecl(hasName("func13"))))))),
3891 langCxx20OrLater()));
3893 EXPECT_TRUE(matches(
3895 traverse(TK_IgnoreUnlessSpelledInSource
,
3896 templateTypeParmDecl(hasName("TemplateType"),
3897 hasParent(lambdaExpr(forFunction(
3898 functionDecl(hasName("func14"))))))),
3899 langCxx20OrLater()));
3901 EXPECT_TRUE(matches(
3903 traverse(TK_IgnoreUnlessSpelledInSource
,
3904 lambdaExpr(forFunction(functionDecl(hasName("func14"))),
3905 has(templateTypeParmDecl(hasName("TemplateType"))))),
3906 langCxx20OrLater()));
3908 EXPECT_TRUE(matches(
3910 traverse(TK_IgnoreUnlessSpelledInSource
,
3911 functionDecl(hasName("func14"), hasDescendant(floatLiteral()))),
3912 langCxx20OrLater()));
3914 EXPECT_TRUE(matches(
3916 traverse(TK_IgnoreUnlessSpelledInSource
,
3918 hasDescendant(varDecl(hasName("count")).bind("countVar")),
3920 declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))),
3921 langCxx20OrLater()));
3925 int explicit_captured = 0;
3926 int implicit_captured = 0;
3927 auto l = [&, explicit_captured](int i) {
3928 if (i || explicit_captured || implicit_captured) return;
3933 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, ifStmt())));
3935 matches(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, ifStmt())));
3937 auto lambdaExplicitCapture
= declRefExpr(
3938 to(varDecl(hasName("explicit_captured"))), unless(hasAncestor(ifStmt())));
3939 auto lambdaImplicitCapture
= declRefExpr(
3940 to(varDecl(hasName("implicit_captured"))), unless(hasAncestor(ifStmt())));
3942 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, lambdaExplicitCapture
)));
3943 EXPECT_TRUE(matches(
3944 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, lambdaExplicitCapture
)));
3946 EXPECT_TRUE(matches(Code
, traverse(TK_AsIs
, lambdaImplicitCapture
)));
3947 EXPECT_FALSE(matches(
3948 Code
, traverse(TK_IgnoreUnlessSpelledInSource
, lambdaImplicitCapture
)));
3955 bool operator==(const S& other)
3970 auto M
= unaryOperator(
3971 hasOperatorName("!"),
3972 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="))));
3974 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3976 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3977 true, {"-std=c++20"}));
3980 auto M
= declRefExpr(to(varDecl(hasName("s1"))));
3982 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3984 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3985 true, {"-std=c++20"}));
3988 auto M
= cxxOperatorCallExpr(hasOverloadedOperatorName("=="));
3990 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
3992 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
3993 true, {"-std=c++20"}));
3996 auto M
= cxxOperatorCallExpr(hasOverloadedOperatorName("!="));
3998 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4000 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4001 true, {"-std=c++20"}));
4003 auto withDescendants
= [](StringRef lName
, StringRef rName
) {
4004 return stmt(hasDescendant(declRefExpr(to(varDecl(hasName(lName
))))),
4005 hasDescendant(declRefExpr(to(varDecl(hasName(rName
))))));
4008 auto M
= cxxRewrittenBinaryOperator(withDescendants("s1", "s2"));
4010 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4012 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4013 true, {"-std=c++20"}));
4016 auto M
= cxxRewrittenBinaryOperator(
4017 has(declRefExpr(to(varDecl(hasName("s1"))))),
4018 has(declRefExpr(to(varDecl(hasName("s2"))))));
4020 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4022 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4023 true, {"-std=c++20"}));
4026 auto M
= cxxRewrittenBinaryOperator(
4027 hasLHS(expr(hasParent(cxxRewrittenBinaryOperator()))),
4028 hasRHS(expr(hasParent(cxxRewrittenBinaryOperator()))));
4030 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4032 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4033 true, {"-std=c++20"}));
4036 EXPECT_TRUE(matchesConditionally(
4039 cxxRewrittenBinaryOperator(
4040 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4041 isComparisonOperator(),
4042 hasLHS(ignoringImplicit(
4043 declRefExpr(to(varDecl(hasName("s1")))))),
4044 hasRHS(ignoringImplicit(
4045 declRefExpr(to(varDecl(hasName("s2")))))),
4046 hasEitherOperand(ignoringImplicit(
4047 declRefExpr(to(varDecl(hasName("s2")))))),
4048 hasOperands(ignoringImplicit(
4049 declRefExpr(to(varDecl(hasName("s1"))))),
4050 ignoringImplicit(declRefExpr(
4051 to(varDecl(hasName("s2")))))))),
4052 true, {"-std=c++20"}));
4053 EXPECT_TRUE(matchesConditionally(
4055 traverse(TK_IgnoreUnlessSpelledInSource
,
4056 cxxRewrittenBinaryOperator(
4057 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4058 isComparisonOperator(),
4059 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4060 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4061 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4062 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4063 declRefExpr(to(varDecl(hasName("s2"))))))),
4064 true, {"-std=c++20"}));
4069 struct strong_ordering {
4071 constexpr operator int() const { return n; }
4072 static const strong_ordering equal, greater, less;
4074 constexpr strong_ordering strong_ordering::equal = {0};
4075 constexpr strong_ordering strong_ordering::greater = {1};
4076 constexpr strong_ordering strong_ordering::less = {-1};
4079 struct HasSpaceshipMem {
4081 constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
4086 HasSpaceshipMem hs1, hs2;
4090 HasSpaceshipMem hs3, hs4;
4094 HasSpaceshipMem hs5, hs6;
4098 HasSpaceshipMem hs7, hs8;
4102 HasSpaceshipMem hs9, hs10;
4106 HasSpaceshipMem hs11, hs12;
4111 auto withArgs
= [](StringRef lName
, StringRef rName
) {
4112 return cxxOperatorCallExpr(
4113 hasArgument(0, declRefExpr(to(varDecl(hasName(lName
))))),
4114 hasArgument(1, declRefExpr(to(varDecl(hasName(rName
))))));
4117 auto M
= ifStmt(hasCondition(cxxOperatorCallExpr(
4118 hasOverloadedOperatorName("=="), withArgs("hs1", "hs2"))));
4120 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4122 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4123 true, {"-std=c++20"}));
4127 unaryOperator(hasOperatorName("!"),
4128 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4129 withArgs("hs3", "hs4"))));
4131 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4133 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4134 true, {"-std=c++20"}));
4138 unaryOperator(hasOperatorName("!"),
4139 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4140 withArgs("hs3", "hs4"))));
4142 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4144 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4145 true, {"-std=c++20"}));
4148 auto M
= binaryOperator(
4149 hasOperatorName("<"),
4150 hasLHS(hasDescendant(cxxOperatorCallExpr(
4151 hasOverloadedOperatorName("<=>"), withArgs("hs5", "hs6")))),
4152 hasRHS(integerLiteral(equals(0))));
4154 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4156 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4157 true, {"-std=c++20"}));
4160 auto M
= cxxRewrittenBinaryOperator(withDescendants("hs3", "hs4"));
4162 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4164 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4165 true, {"-std=c++20"}));
4168 auto M
= declRefExpr(to(varDecl(hasName("hs3"))));
4170 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4172 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4173 true, {"-std=c++20"}));
4176 auto M
= cxxRewrittenBinaryOperator(has(
4177 unaryOperator(hasOperatorName("!"), withDescendants("hs3", "hs4"))));
4179 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4181 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4182 true, {"-std=c++20"}));
4185 auto M
= cxxRewrittenBinaryOperator(
4186 has(declRefExpr(to(varDecl(hasName("hs3"))))),
4187 has(declRefExpr(to(varDecl(hasName("hs4"))))));
4189 matchesConditionally(Code
, traverse(TK_AsIs
, M
), true, {"-std=c++20"}));
4191 matchesConditionally(Code
, traverse(TK_IgnoreUnlessSpelledInSource
, M
),
4192 true, {"-std=c++20"}));
4195 EXPECT_TRUE(matchesConditionally(
4198 cxxRewrittenBinaryOperator(
4199 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4200 isComparisonOperator(),
4201 hasLHS(ignoringImplicit(
4202 declRefExpr(to(varDecl(hasName("hs3")))))),
4203 hasRHS(ignoringImplicit(
4204 declRefExpr(to(varDecl(hasName("hs4")))))),
4205 hasEitherOperand(ignoringImplicit(
4206 declRefExpr(to(varDecl(hasName("hs3")))))),
4207 hasOperands(ignoringImplicit(
4208 declRefExpr(to(varDecl(hasName("hs3"))))),
4209 ignoringImplicit(declRefExpr(
4210 to(varDecl(hasName("hs4")))))))),
4211 true, {"-std=c++20"}));
4212 EXPECT_TRUE(matchesConditionally(
4214 traverse(TK_IgnoreUnlessSpelledInSource
,
4215 cxxRewrittenBinaryOperator(
4216 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4217 isComparisonOperator(),
4218 hasLHS(declRefExpr(to(varDecl(hasName("hs3"))))),
4219 hasRHS(declRefExpr(to(varDecl(hasName("hs4"))))),
4220 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs3"))))),
4221 hasOperands(declRefExpr(to(varDecl(hasName("hs3")))),
4222 declRefExpr(to(varDecl(hasName("hs4"))))))),
4223 true, {"-std=c++20"}));
4226 EXPECT_TRUE(matchesConditionally(
4229 cxxRewrittenBinaryOperator(
4230 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4231 isComparisonOperator(),
4232 hasLHS(ignoringImplicit(
4233 declRefExpr(to(varDecl(hasName("hs5")))))),
4234 hasRHS(ignoringImplicit(
4235 declRefExpr(to(varDecl(hasName("hs6")))))),
4236 hasEitherOperand(ignoringImplicit(
4237 declRefExpr(to(varDecl(hasName("hs5")))))),
4238 hasOperands(ignoringImplicit(
4239 declRefExpr(to(varDecl(hasName("hs5"))))),
4240 ignoringImplicit(declRefExpr(
4241 to(varDecl(hasName("hs6")))))))),
4242 true, {"-std=c++20"}));
4243 EXPECT_TRUE(matchesConditionally(
4245 traverse(TK_IgnoreUnlessSpelledInSource
,
4246 cxxRewrittenBinaryOperator(
4247 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4248 isComparisonOperator(),
4249 hasLHS(declRefExpr(to(varDecl(hasName("hs5"))))),
4250 hasRHS(declRefExpr(to(varDecl(hasName("hs6"))))),
4251 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs5"))))),
4252 hasOperands(declRefExpr(to(varDecl(hasName("hs5")))),
4253 declRefExpr(to(varDecl(hasName("hs6"))))))),
4254 true, {"-std=c++20"}));
4257 EXPECT_TRUE(matchesConditionally(
4260 cxxRewrittenBinaryOperator(
4261 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4262 isComparisonOperator(),
4263 hasLHS(ignoringImplicit(
4264 declRefExpr(to(varDecl(hasName("hs7")))))),
4265 hasRHS(ignoringImplicit(
4266 declRefExpr(to(varDecl(hasName("hs8")))))),
4267 hasEitherOperand(ignoringImplicit(
4268 declRefExpr(to(varDecl(hasName("hs7")))))),
4269 hasOperands(ignoringImplicit(
4270 declRefExpr(to(varDecl(hasName("hs7"))))),
4271 ignoringImplicit(declRefExpr(
4272 to(varDecl(hasName("hs8")))))))),
4273 true, {"-std=c++20"}));
4274 EXPECT_TRUE(matchesConditionally(
4276 traverse(TK_IgnoreUnlessSpelledInSource
,
4277 cxxRewrittenBinaryOperator(
4278 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4279 isComparisonOperator(),
4280 hasLHS(declRefExpr(to(varDecl(hasName("hs7"))))),
4281 hasRHS(declRefExpr(to(varDecl(hasName("hs8"))))),
4282 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs7"))))),
4283 hasOperands(declRefExpr(to(varDecl(hasName("hs7")))),
4284 declRefExpr(to(varDecl(hasName("hs8"))))))),
4285 true, {"-std=c++20"}));
4288 EXPECT_TRUE(matchesConditionally(
4291 cxxRewrittenBinaryOperator(
4292 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4293 isComparisonOperator(),
4294 hasLHS(ignoringImplicit(
4295 declRefExpr(to(varDecl(hasName("hs9")))))),
4296 hasRHS(ignoringImplicit(
4297 declRefExpr(to(varDecl(hasName("hs10")))))),
4298 hasEitherOperand(ignoringImplicit(
4299 declRefExpr(to(varDecl(hasName("hs9")))))),
4300 hasOperands(ignoringImplicit(
4301 declRefExpr(to(varDecl(hasName("hs9"))))),
4302 ignoringImplicit(declRefExpr(
4303 to(varDecl(hasName("hs10")))))))),
4304 true, {"-std=c++20"}));
4305 EXPECT_TRUE(matchesConditionally(
4307 traverse(TK_IgnoreUnlessSpelledInSource
,
4308 cxxRewrittenBinaryOperator(
4309 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4310 isComparisonOperator(),
4311 hasLHS(declRefExpr(to(varDecl(hasName("hs9"))))),
4312 hasRHS(declRefExpr(to(varDecl(hasName("hs10"))))),
4313 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs9"))))),
4314 hasOperands(declRefExpr(to(varDecl(hasName("hs9")))),
4315 declRefExpr(to(varDecl(hasName("hs10"))))))),
4316 true, {"-std=c++20"}));
4319 EXPECT_TRUE(matchesConditionally(
4322 cxxRewrittenBinaryOperator(
4323 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4324 isComparisonOperator(),
4325 hasLHS(ignoringImplicit(
4326 declRefExpr(to(varDecl(hasName("hs11")))))),
4327 hasRHS(ignoringImplicit(
4328 declRefExpr(to(varDecl(hasName("hs12")))))),
4329 hasEitherOperand(ignoringImplicit(
4330 declRefExpr(to(varDecl(hasName("hs11")))))),
4331 hasOperands(ignoringImplicit(
4332 declRefExpr(to(varDecl(hasName("hs11"))))),
4333 ignoringImplicit(declRefExpr(
4334 to(varDecl(hasName("hs12")))))))),
4335 true, {"-std=c++20"}));
4336 EXPECT_TRUE(matchesConditionally(
4339 TK_IgnoreUnlessSpelledInSource
,
4340 cxxRewrittenBinaryOperator(
4341 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4342 isComparisonOperator(),
4343 hasLHS(declRefExpr(to(varDecl(hasName("hs11"))))),
4344 hasRHS(declRefExpr(to(varDecl(hasName("hs12"))))),
4345 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs11"))))),
4346 hasOperands(declRefExpr(to(varDecl(hasName("hs11")))),
4347 declRefExpr(to(varDecl(hasName("hs12"))))))),
4348 true, {"-std=c++20"}));
4356 bool operator==(const S& other) const
4363 bool operator==(const HasOpEqMem&) const { return true; }
4366 struct HasOpEqFree {
4368 bool operator==(const HasOpEqFree&, const HasOpEqFree&) { return true; }
4402 EXPECT_TRUE(matchesConditionally(
4406 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4407 isComparisonOperator(),
4408 hasLHS(ignoringImplicit(
4409 declRefExpr(to(varDecl(hasName("s1")))))),
4410 hasRHS(ignoringImplicit(
4411 declRefExpr(to(varDecl(hasName("s2")))))),
4412 hasEitherOperand(ignoringImplicit(
4413 declRefExpr(to(varDecl(hasName("s2")))))),
4414 hasOperands(ignoringImplicit(
4415 declRefExpr(to(varDecl(hasName("s1"))))),
4416 ignoringImplicit(declRefExpr(
4417 to(varDecl(hasName("s2")))))))),
4418 true, {"-std=c++20"}));
4419 EXPECT_TRUE(matchesConditionally(
4421 traverse(TK_AsIs
, binaryOperation(hasOperatorName("!="),
4422 hasLHS(ignoringImplicit(declRefExpr(
4423 to(varDecl(hasName("i1")))))),
4424 hasRHS(ignoringImplicit(declRefExpr(
4425 to(varDecl(hasName("i2")))))))),
4426 true, {"-std=c++20"}));
4427 EXPECT_TRUE(matchesConditionally(
4429 traverse(TK_AsIs
, binaryOperation(hasOperatorName("=="),
4430 hasLHS(ignoringImplicit(declRefExpr(
4431 to(varDecl(hasName("M1")))))),
4432 hasRHS(ignoringImplicit(declRefExpr(
4433 to(varDecl(hasName("M2")))))))),
4434 true, {"-std=c++20"}));
4435 EXPECT_TRUE(matchesConditionally(
4437 traverse(TK_AsIs
, binaryOperation(hasOperatorName("=="),
4438 hasLHS(ignoringImplicit(declRefExpr(
4439 to(varDecl(hasName("F1")))))),
4440 hasRHS(ignoringImplicit(declRefExpr(
4441 to(varDecl(hasName("F2")))))))),
4442 true, {"-std=c++20"}));
4443 EXPECT_TRUE(matchesConditionally(
4445 traverse(TK_IgnoreUnlessSpelledInSource
,
4447 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4448 isComparisonOperator(),
4449 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4450 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4451 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4452 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4453 declRefExpr(to(varDecl(hasName("s2"))))))),
4454 true, {"-std=c++20"}));
4455 EXPECT_TRUE(matchesConditionally(
4458 TK_IgnoreUnlessSpelledInSource
,
4459 binaryOperation(hasOperatorName("!="),
4460 hasLHS(declRefExpr(to(varDecl(hasName("i1"))))),
4461 hasRHS(declRefExpr(to(varDecl(hasName("i2"))))))),
4462 true, {"-std=c++20"}));
4463 EXPECT_TRUE(matchesConditionally(
4466 TK_IgnoreUnlessSpelledInSource
,
4467 binaryOperation(hasOperatorName("=="),
4468 hasLHS(declRefExpr(to(varDecl(hasName("M1"))))),
4469 hasRHS(declRefExpr(to(varDecl(hasName("M2"))))))),
4470 true, {"-std=c++20"}));
4471 EXPECT_TRUE(matchesConditionally(
4474 TK_IgnoreUnlessSpelledInSource
,
4475 binaryOperation(hasOperatorName("=="),
4476 hasLHS(declRefExpr(to(varDecl(hasName("F1"))))),
4477 hasRHS(declRefExpr(to(varDecl(hasName("F2"))))))),
4478 true, {"-std=c++20"}));
4482 TEST(IgnoringImpCasts
, PathologicalLambda
) {
4484 // Test that deeply nested lambdas are not a performance penalty
4485 StringRef Code
= R
"cpp(
4550 EXPECT_TRUE(matches(Code
, integerLiteral(equals(42))));
4551 EXPECT_TRUE(matches(Code
, functionDecl(hasDescendant(integerLiteral(equals(42))))));
4554 TEST(IgnoringImpCasts
, MatchesImpCasts
) {
4555 // This test checks that ignoringImpCasts matches when implicit casts are
4556 // present and its inner matcher alone does not match.
4557 // Note that this test creates an implicit const cast.
4558 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4559 varDecl(hasInitializer(ignoringImpCasts(
4560 declRefExpr(to(varDecl(hasName("x")))))))));
4561 // This test creates an implict cast from int to char.
4562 EXPECT_TRUE(matches("char x = 0;",
4563 varDecl(hasInitializer(ignoringImpCasts(
4564 integerLiteral(equals(0)))))));
4567 TEST(IgnoringImpCasts
, DoesNotMatchIncorrectly
) {
4568 // These tests verify that ignoringImpCasts does not match if the inner
4569 // matcher does not match.
4570 // Note that the first test creates an implicit const cast.
4571 EXPECT_TRUE(notMatches("int x; const int y = x;",
4572 varDecl(hasInitializer(ignoringImpCasts(
4573 unless(anything()))))));
4574 EXPECT_TRUE(notMatches("int x; int y = x;",
4575 varDecl(hasInitializer(ignoringImpCasts(
4576 unless(anything()))))));
4578 // These tests verify that ignoringImplictCasts does not look through explicit
4579 // casts or parentheses.
4580 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4581 varDecl(hasInitializer(ignoringImpCasts(
4582 integerLiteral())))));
4583 EXPECT_TRUE(notMatches(
4586 varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))))));
4587 EXPECT_TRUE(notMatches("float i = (float)0;",
4588 varDecl(hasInitializer(ignoringImpCasts(
4589 integerLiteral())))));
4590 EXPECT_TRUE(notMatches("float i = float(0);",
4591 varDecl(hasInitializer(ignoringImpCasts(
4592 integerLiteral())))));
4595 TEST(IgnoringImpCasts
, MatchesWithoutImpCasts
) {
4596 // This test verifies that expressions that do not have implicit casts
4597 // still match the inner matcher.
4598 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4599 varDecl(hasInitializer(ignoringImpCasts(
4600 declRefExpr(to(varDecl(hasName("x")))))))));
4603 TEST(IgnoringParenCasts
, MatchesParenCasts
) {
4604 // This test checks that ignoringParenCasts matches when parentheses and/or
4605 // casts are present and its inner matcher alone does not match.
4606 EXPECT_TRUE(matches("int x = (0);",
4607 varDecl(hasInitializer(ignoringParenCasts(
4608 integerLiteral(equals(0)))))));
4609 EXPECT_TRUE(matches("int x = (((((0)))));",
4610 varDecl(hasInitializer(ignoringParenCasts(
4611 integerLiteral(equals(0)))))));
4613 // This test creates an implict cast from int to char in addition to the
4615 EXPECT_TRUE(matches("char x = (0);",
4616 varDecl(hasInitializer(ignoringParenCasts(
4617 integerLiteral(equals(0)))))));
4619 EXPECT_TRUE(matches("char x = (char)0;",
4620 varDecl(hasInitializer(ignoringParenCasts(
4621 integerLiteral(equals(0)))))));
4622 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
4623 varDecl(hasInitializer(ignoringParenCasts(
4624 integerLiteral(equals(0)))))));
4627 TEST(IgnoringParenCasts
, MatchesWithoutParenCasts
) {
4628 // This test verifies that expressions that do not have any casts still match.
4629 EXPECT_TRUE(matches("int x = 0;",
4630 varDecl(hasInitializer(ignoringParenCasts(
4631 integerLiteral(equals(0)))))));
4634 TEST(IgnoringParenCasts
, DoesNotMatchIncorrectly
) {
4635 // These tests verify that ignoringImpCasts does not match if the inner
4636 // matcher does not match.
4637 EXPECT_TRUE(notMatches("int x = ((0));",
4638 varDecl(hasInitializer(ignoringParenCasts(
4639 unless(anything()))))));
4641 // This test creates an implicit cast from int to char in addition to the
4643 EXPECT_TRUE(notMatches("char x = ((0));",
4644 varDecl(hasInitializer(ignoringParenCasts(
4645 unless(anything()))))));
4647 EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
4648 varDecl(hasInitializer(ignoringParenCasts(
4649 unless(anything()))))));
4652 TEST(IgnoringParenAndImpCasts
, MatchesParenImpCasts
) {
4653 // This test checks that ignoringParenAndImpCasts matches when
4654 // parentheses and/or implicit casts are present and its inner matcher alone
4656 // Note that this test creates an implicit const cast.
4657 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4658 varDecl(hasInitializer(ignoringParenImpCasts(
4659 declRefExpr(to(varDecl(hasName("x")))))))));
4660 // This test creates an implicit cast from int to char.
4661 EXPECT_TRUE(matches("const char x = (0);",
4662 varDecl(hasInitializer(ignoringParenImpCasts(
4663 integerLiteral(equals(0)))))));
4666 TEST(IgnoringParenAndImpCasts
, MatchesWithoutParenImpCasts
) {
4667 // This test verifies that expressions that do not have parentheses or
4668 // implicit casts still match.
4669 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4670 varDecl(hasInitializer(ignoringParenImpCasts(
4671 declRefExpr(to(varDecl(hasName("x")))))))));
4672 EXPECT_TRUE(matches("int x = 0;",
4673 varDecl(hasInitializer(ignoringParenImpCasts(
4674 integerLiteral(equals(0)))))));
4677 TEST(IgnoringParenAndImpCasts
, DoesNotMatchIncorrectly
) {
4678 // These tests verify that ignoringParenImpCasts does not match if
4679 // the inner matcher does not match.
4680 // This test creates an implicit cast.
4681 EXPECT_TRUE(notMatches("char c = ((3));",
4682 varDecl(hasInitializer(ignoringParenImpCasts(
4683 unless(anything()))))));
4684 // These tests verify that ignoringParenAndImplictCasts does not look
4685 // through explicit casts.
4686 EXPECT_TRUE(notMatches("float y = (float(0));",
4687 varDecl(hasInitializer(ignoringParenImpCasts(
4688 integerLiteral())))));
4689 EXPECT_TRUE(notMatches("float y = (float)0;",
4690 varDecl(hasInitializer(ignoringParenImpCasts(
4691 integerLiteral())))));
4692 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4693 varDecl(hasInitializer(ignoringParenImpCasts(
4694 integerLiteral())))));
4697 TEST(HasSourceExpression
, MatchesImplicitCasts
) {
4698 EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
4699 "void r() {string a_string; URL url = a_string; }",
4700 traverse(TK_AsIs
, implicitCastExpr(hasSourceExpression(
4701 cxxConstructExpr())))));
4704 TEST(HasSourceExpression
, MatchesExplicitCasts
) {
4706 matches("float x = static_cast<float>(42);",
4707 traverse(TK_AsIs
, explicitCastExpr(hasSourceExpression(
4708 hasDescendant(expr(integerLiteral())))))));
4711 TEST(UsingDeclaration
, MatchesSpecificTarget
) {
4712 EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",
4713 usingDecl(hasAnyUsingShadowDecl(
4714 hasTargetDecl(functionDecl())))));
4715 EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",
4716 usingDecl(hasAnyUsingShadowDecl(
4717 hasTargetDecl(functionDecl())))));
4720 TEST(UsingDeclaration
, ThroughUsingDeclaration
) {
4721 EXPECT_TRUE(matches(
4722 "namespace a { void f(); } using a::f; void g() { f(); }",
4723 declRefExpr(throughUsingDecl(anything()))));
4724 EXPECT_TRUE(notMatches(
4725 "namespace a { void f(); } using a::f; void g() { a::f(); }",
4726 declRefExpr(throughUsingDecl(anything()))));
4729 TEST(SingleDecl
, IsSingleDecl
) {
4730 StatementMatcher SingleDeclStmt
=
4731 declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));
4732 EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt
));
4733 EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt
));
4734 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4738 TEST(DeclStmt
, ContainsDeclaration
) {
4739 DeclarationMatcher MatchesInit
= varDecl(hasInitializer(anything()));
4741 EXPECT_TRUE(matches("void f() {int a = 4;}",
4742 declStmt(containsDeclaration(0, MatchesInit
))));
4743 EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
4744 declStmt(containsDeclaration(0, MatchesInit
),
4745 containsDeclaration(1, MatchesInit
))));
4746 unsigned WrongIndex
= 42;
4747 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4748 declStmt(containsDeclaration(WrongIndex
,
4752 TEST(SwitchCase
, MatchesEachCase
) {
4753 EXPECT_TRUE(notMatches("void x() { switch(42); }",
4754 switchStmt(forEachSwitchCase(caseStmt()))));
4755 EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
4756 switchStmt(forEachSwitchCase(caseStmt()))));
4757 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
4758 switchStmt(forEachSwitchCase(caseStmt()))));
4759 EXPECT_TRUE(notMatches(
4760 "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
4761 ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
4762 EXPECT_TRUE(matches(
4763 "void x() { switch(42) { case 1+1: case 4:; } }",
4764 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4765 constantExpr(has(integerLiteral())))))))));
4766 EXPECT_TRUE(notMatches(
4767 "void x() { switch(42) { case 1+1: case 2+2:; } }",
4768 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4769 constantExpr(has(integerLiteral())))))))));
4770 EXPECT_TRUE(notMatches(
4771 "void x() { switch(42) { case 1 ... 2:; } }",
4772 traverse(TK_AsIs
, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4773 constantExpr(has(integerLiteral())))))))));
4774 EXPECT_TRUE(matchAndVerifyResultTrue(
4775 "void x() { switch (42) { case 1: case 2: case 3: default:; } }",
4776 switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
4777 std::make_unique
<VerifyIdIsBoundTo
<CaseStmt
>>("x", 3)));
4780 TEST(Declaration
, HasExplicitSpecifier
) {
4782 EXPECT_TRUE(notMatches("void f();",
4783 functionDecl(hasExplicitSpecifier(constantExpr())),
4784 langCxx20OrLater()));
4786 notMatches("template<bool b> struct S { explicit operator int(); };",
4788 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
4789 langCxx20OrLater()));
4791 notMatches("template<bool b> struct S { explicit(b) operator int(); };",
4793 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
4794 langCxx20OrLater()));
4796 matches("struct S { explicit(true) operator int(); };",
4797 traverse(TK_AsIs
, cxxConversionDecl(hasExplicitSpecifier(
4798 constantExpr(has(cxxBoolLiteral()))))),
4799 langCxx20OrLater()));
4801 matches("struct S { explicit(false) operator int(); };",
4802 traverse(TK_AsIs
, cxxConversionDecl(hasExplicitSpecifier(
4803 constantExpr(has(cxxBoolLiteral()))))),
4804 langCxx20OrLater()));
4806 notMatches("template<bool b> struct S { explicit(b) S(int); };",
4807 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
4808 constantExpr(has(cxxBoolLiteral()))))),
4809 langCxx20OrLater()));
4811 matches("struct S { explicit(true) S(int); };",
4812 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
4813 constantExpr(has(cxxBoolLiteral()))))),
4814 langCxx20OrLater()));
4816 matches("struct S { explicit(false) S(int); };",
4817 traverse(TK_AsIs
, cxxConstructorDecl(hasExplicitSpecifier(
4818 constantExpr(has(cxxBoolLiteral()))))),
4819 langCxx20OrLater()));
4821 notMatches("template<typename T> struct S { S(int); };"
4822 "template<bool b = true> explicit(b) S(int) -> S<int>;",
4823 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
4824 constantExpr(has(cxxBoolLiteral()))))),
4825 langCxx20OrLater()));
4827 matches("template<typename T> struct S { S(int); };"
4828 "explicit(true) S(int) -> S<int>;",
4829 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
4830 constantExpr(has(cxxBoolLiteral()))))),
4831 langCxx20OrLater()));
4833 matches("template<typename T> struct S { S(int); };"
4834 "explicit(false) S(int) -> S<int>;",
4835 traverse(TK_AsIs
, cxxDeductionGuideDecl(hasExplicitSpecifier(
4836 constantExpr(has(cxxBoolLiteral()))))),
4837 langCxx20OrLater()));
4840 TEST(ForEachConstructorInitializer
, MatchesInitializers
) {
4841 EXPECT_TRUE(matches(
4842 "struct X { X() : i(42), j(42) {} int i, j; };",
4843 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
4846 TEST(ForEachLambdaCapture
, MatchesCaptures
) {
4847 EXPECT_TRUE(matches(
4848 "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
4849 lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));
4850 auto matcher
= lambdaExpr(forEachLambdaCapture(
4851 lambdaCapture(capturesVar(varDecl(hasType(isInteger())))).bind("LC")));
4852 EXPECT_TRUE(matchAndVerifyResultTrue(
4853 "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",
4854 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
4855 EXPECT_TRUE(matchAndVerifyResultTrue(
4856 "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "
4858 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
4861 TEST(ForEachLambdaCapture
, IgnoreUnlessSpelledInSource
) {
4863 traverse(TK_IgnoreUnlessSpelledInSource
,
4864 lambdaExpr(forEachLambdaCapture(
4865 lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))
4868 notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",
4869 matcher
, langCxx11OrLater()));
4871 notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",
4872 matcher
, langCxx11OrLater()));
4873 EXPECT_TRUE(matchAndVerifyResultTrue(
4878 auto f = [=, &y]() { return x + y + z; };
4881 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
4884 TEST(ForEachLambdaCapture
, MatchImplicitCapturesOnly
) {
4886 lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));
4887 EXPECT_TRUE(matchAndVerifyResultTrue(
4888 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
4889 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
4890 EXPECT_TRUE(matchAndVerifyResultTrue(
4891 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
4892 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 2)));
4895 TEST(ForEachLambdaCapture
, MatchExplicitCapturesOnly
) {
4896 auto matcher
= lambdaExpr(
4897 forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));
4898 EXPECT_TRUE(matchAndVerifyResultTrue(
4899 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
4900 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
4901 EXPECT_TRUE(matchAndVerifyResultTrue(
4902 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
4903 matcher
, std::make_unique
<VerifyIdIsBoundTo
<LambdaCapture
>>("LC", 1)));
4906 TEST(HasConditionVariableStatement
, DoesNotMatchCondition
) {
4907 EXPECT_TRUE(notMatches(
4908 "void x() { if(true) {} }",
4909 ifStmt(hasConditionVariableStatement(declStmt()))));
4910 EXPECT_TRUE(notMatches(
4911 "void x() { int x; if((x = 42)) {} }",
4912 ifStmt(hasConditionVariableStatement(declStmt()))));
4915 TEST(HasConditionVariableStatement
, MatchesConditionVariables
) {
4916 EXPECT_TRUE(matches(
4917 "void x() { if(int* a = 0) {} }",
4918 ifStmt(hasConditionVariableStatement(declStmt()))));
4921 TEST(ForEach
, BindsOneNode
) {
4922 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
4923 recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),
4924 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("x", 1)));
4927 TEST(ForEach
, BindsMultipleNodes
) {
4928 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",
4929 recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),
4930 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 3)));
4933 TEST(ForEach
, BindsRecursiveCombinations
) {
4934 EXPECT_TRUE(matchAndVerifyResultTrue(
4935 "class C { class D { int x; int y; }; class E { int y; int z; }; };",
4936 recordDecl(hasName("C"),
4937 forEach(recordDecl(forEach(fieldDecl().bind("f"))))),
4938 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 4)));
4941 TEST(ForEach
, DoesNotIgnoreImplicit
) {
4942 StringRef Code
= R
"cpp(
4950 EXPECT_TRUE(matchAndVerifyResultFalse(
4951 Code
, binaryOperator(forEach(declRefExpr().bind("dre"))),
4952 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 0)));
4954 EXPECT_TRUE(matchAndVerifyResultTrue(
4956 binaryOperator(forEach(
4957 implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))),
4958 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
4960 EXPECT_TRUE(matchAndVerifyResultTrue(
4963 forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))),
4964 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
4966 EXPECT_TRUE(matchAndVerifyResultTrue(
4968 traverse(TK_IgnoreUnlessSpelledInSource
,
4969 binaryOperator(forEach(declRefExpr().bind("dre")))),
4970 std::make_unique
<VerifyIdIsBoundTo
<DeclRefExpr
>>("dre", 2)));
4973 TEST(ForEachDescendant
, BindsOneNode
) {
4974 EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",
4975 recordDecl(hasName("C"),
4976 forEachDescendant(fieldDecl(hasName("x")).bind("x"))),
4977 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("x", 1)));
4980 TEST(ForEachDescendant
, NestedForEachDescendant
) {
4981 DeclarationMatcher m
= recordDecl(
4982 isDefinition(), decl().bind("x"), hasName("C"));
4983 EXPECT_TRUE(matchAndVerifyResultTrue(
4984 "class A { class B { class C {}; }; };",
4985 recordDecl(hasName("A"), anyOf(m
, forEachDescendant(m
))),
4986 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", "C")));
4988 // Check that a partial match of 'm' that binds 'x' in the
4989 // first part of anyOf(m, anything()) will not overwrite the
4990 // binding created by the earlier binding in the hasDescendant.
4991 EXPECT_TRUE(matchAndVerifyResultTrue(
4992 "class A { class B { class C {}; }; };",
4993 recordDecl(hasName("A"), allOf(hasDescendant(m
), anyOf(m
, anything()))),
4994 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", "C")));
4997 TEST(ForEachDescendant
, BindsMultipleNodes
) {
4998 EXPECT_TRUE(matchAndVerifyResultTrue(
4999 "class C { class D { int x; int y; }; "
5000 " class E { class F { int y; int z; }; }; };",
5001 recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),
5002 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 4)));
5005 TEST(ForEachDescendant
, BindsRecursiveCombinations
) {
5006 EXPECT_TRUE(matchAndVerifyResultTrue(
5007 "class C { class D { "
5008 " class E { class F { class G { int y; int z; }; }; }; }; };",
5009 recordDecl(hasName("C"), forEachDescendant(recordDecl(
5010 forEachDescendant(fieldDecl().bind("f"))))),
5011 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("f", 8)));
5014 TEST(ForEachDescendant
, BindsCombinations
) {
5015 EXPECT_TRUE(matchAndVerifyResultTrue(
5016 "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "
5018 compoundStmt(forEachDescendant(ifStmt().bind("if")),
5019 forEachDescendant(whileStmt().bind("while"))),
5020 std::make_unique
<VerifyIdIsBoundTo
<IfStmt
>>("if", 6)));
5023 TEST(ForEachTemplateArgument
, OnFunctionDecl
) {
5024 const std::string Code
= R
"(
5025 template <typename T, typename U> void f(T, U) {}
5031 EXPECT_TRUE(matches(
5032 Code
, functionDecl(forEachTemplateArgument(refersToType(builtinType()))),
5033 langCxx11OrLater()));
5035 functionDecl(forEachTemplateArgument(
5036 templateArgument(refersToType(builtinType().bind("BT")))
5040 EXPECT_TRUE(matchAndVerifyResultTrue(
5042 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("FN", 2)));
5043 EXPECT_TRUE(matchAndVerifyResultTrue(
5045 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgument
>>("TA", 2)));
5046 EXPECT_TRUE(matchAndVerifyResultTrue(
5048 std::make_unique
<VerifyIdIsBoundTo
<BuiltinType
>>("BT", 2)));
5051 TEST(ForEachTemplateArgument
, OnClassTemplateSpecialization
) {
5052 const std::string Code
= R
"(
5053 template <typename T, unsigned N, unsigned M>
5056 static constexpr unsigned R = 2;
5058 Matrix<int, R * 2, R * 4> M;
5060 EXPECT_TRUE(matches(
5061 Code
, templateSpecializationType(forEachTemplateArgument(isExpr(expr()))),
5062 langCxx11OrLater()));
5063 auto matcher
= templateSpecializationType(
5064 forEachTemplateArgument(
5065 templateArgument(isExpr(expr().bind("E"))).bind("TA")))
5068 EXPECT_TRUE(matchAndVerifyResultTrue(
5070 std::make_unique
<VerifyIdIsBoundTo
<TemplateSpecializationType
>>("TST",
5072 EXPECT_TRUE(matchAndVerifyResultTrue(
5074 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgument
>>("TA", 2)));
5075 EXPECT_TRUE(matchAndVerifyResultTrue(
5076 Code
, matcher
, std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("E", 2)));
5079 TEST(Has
, DoesNotDeleteBindings
) {
5080 EXPECT_TRUE(matchAndVerifyResultTrue(
5081 "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),
5082 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5085 TEST(TemplateArgumentLoc
, Matches
) {
5086 EXPECT_TRUE(matchAndVerifyResultTrue(
5088 template <typename A, int B, template <typename> class C> class X {};
5091 template <typename> class C {};
5094 templateArgumentLoc().bind("x"),
5095 std::make_unique
<VerifyIdIsBoundTo
<TemplateArgumentLoc
>>("x", 3)));
5098 TEST(LoopingMatchers
, DoNotOverwritePreviousMatchResultOnFailure
) {
5099 // Those matchers cover all the cases where an inner matcher is called
5100 // and there is not a 1:1 relationship between the match of the outer
5101 // matcher and the match of the inner matcher.
5102 // The pattern to look for is:
5103 // ... return InnerMatcher.matches(...); ...
5104 // In which case no special handling is needed.
5106 // On the other hand, if there are multiple alternative matches
5107 // (for example forEach*) or matches might be discarded (for example has*)
5108 // the implementation must make sure that the discarded matches do not
5109 // affect the bindings.
5110 // When new such matchers are added, add a test here that:
5111 // - matches a simple node, and binds it as the first thing in the matcher:
5112 // recordDecl(decl().bind("x"), hasName("X")))
5113 // - uses the matcher under test afterwards in a way that not the first
5114 // alternative is matched; for anyOf, that means the first branch
5115 // would need to return false; for hasAncestor, it means that not
5116 // the direct parent matches the inner matcher.
5118 EXPECT_TRUE(matchAndVerifyResultTrue(
5119 "class X { int y; };",
5121 recordDecl().bind("x"), hasName("::X"),
5122 anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),
5123 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("x", 1)));
5124 EXPECT_TRUE(matchAndVerifyResultTrue(
5125 "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),
5126 anyOf(unless(anything()), anything())),
5127 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("x", 1)));
5128 EXPECT_TRUE(matchAndVerifyResultTrue(
5129 "template<typename T1, typename T2> class X {}; X<float, int> x;",
5130 classTemplateSpecializationDecl(
5132 hasAnyTemplateArgument(refersToType(asString("int")))),
5133 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5134 EXPECT_TRUE(matchAndVerifyResultTrue(
5135 "class X { void f(); void g(); };",
5136 cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
5137 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5138 EXPECT_TRUE(matchAndVerifyResultTrue(
5139 "class X { X() : a(1), b(2) {} double a; int b; };",
5140 recordDecl(decl().bind("x"),
5141 has(cxxConstructorDecl(
5142 hasAnyConstructorInitializer(forField(hasName("b")))))),
5143 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5144 EXPECT_TRUE(matchAndVerifyResultTrue(
5145 "void x(int, int) { x(0, 42); }",
5146 callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),
5147 std::make_unique
<VerifyIdIsBoundTo
<Expr
>>("x", 1)));
5148 EXPECT_TRUE(matchAndVerifyResultTrue(
5149 "void x(int, int y) {}",
5150 functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),
5151 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5152 EXPECT_TRUE(matchAndVerifyResultTrue(
5153 "void x() { return; if (true) {} }",
5154 functionDecl(decl().bind("x"),
5155 has(compoundStmt(hasAnySubstatement(ifStmt())))),
5156 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5157 EXPECT_TRUE(matchAndVerifyResultTrue(
5158 "namespace X { void b(int); void b(); }"
5160 usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(
5161 functionDecl(parameterCountIs(1))))),
5162 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5163 EXPECT_TRUE(matchAndVerifyResultTrue(
5164 "class A{}; class B{}; class C : B, A {};",
5165 cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A")),
5166 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5167 EXPECT_TRUE(matchAndVerifyResultTrue(
5168 "class A{}; typedef A B; typedef A C; typedef A D;"
5170 cxxRecordDecl(decl().bind("x"), isDerivedFrom("C")),
5171 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5172 EXPECT_TRUE(matchAndVerifyResultTrue(
5173 "class A { class B { void f() {} }; };",
5174 functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5175 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5176 EXPECT_TRUE(matchAndVerifyResultTrue(
5177 "template <typename T> struct A { struct B {"
5178 " void f() { if(true) {} }"
5180 "void t() { A<int>::B b; b.f(); }",
5181 ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5182 std::make_unique
<VerifyIdIsBoundTo
<Stmt
>>("x", 2)));
5183 EXPECT_TRUE(matchAndVerifyResultTrue(
5185 recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),
5186 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5187 EXPECT_TRUE(matchAndVerifyResultTrue(
5188 "class A { A() : s(), i(42) {} const char *s; int i; };",
5189 cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),
5190 forEachConstructorInitializer(forField(hasName("i")))),
5191 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("x", 1)));
5194 TEST(ForEachDescendant
, BindsCorrectNodes
) {
5195 EXPECT_TRUE(matchAndVerifyResultTrue(
5196 "class C { void f(); int i; };",
5197 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5198 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("decl", 1)));
5199 EXPECT_TRUE(matchAndVerifyResultTrue(
5200 "class C { void f() {} int i; };",
5201 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5202 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("decl", 1)));
5205 TEST(FindAll
, BindsNodeOnMatch
) {
5206 EXPECT_TRUE(matchAndVerifyResultTrue(
5208 recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),
5209 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("v", 1)));
5212 TEST(FindAll
, BindsDescendantNodeOnMatch
) {
5213 EXPECT_TRUE(matchAndVerifyResultTrue(
5214 "class A { int a; int b; };",
5215 recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),
5216 std::make_unique
<VerifyIdIsBoundTo
<FieldDecl
>>("v", 2)));
5219 TEST(FindAll
, BindsNodeAndDescendantNodesOnOneMatch
) {
5220 EXPECT_TRUE(matchAndVerifyResultTrue(
5221 "class A { int a; int b; };",
5222 recordDecl(hasName("::A"),
5223 findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),
5224 fieldDecl().bind("v"))))),
5225 std::make_unique
<VerifyIdIsBoundTo
<Decl
>>("v", 3)));
5227 EXPECT_TRUE(matchAndVerifyResultTrue(
5228 "class A { class B {}; class C {}; };",
5229 recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),
5230 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("v", 3)));
5233 TEST(HasAncenstor
, MatchesDeclarationAncestors
) {
5234 EXPECT_TRUE(matches(
5235 "class A { class B { class C {}; }; };",
5236 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));
5239 TEST(HasAncenstor
, FailsIfNoAncestorMatches
) {
5240 EXPECT_TRUE(notMatches(
5241 "class A { class B { class C {}; }; };",
5242 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));
5245 TEST(HasAncestor
, MatchesDeclarationsThatGetVisitedLater
) {
5246 EXPECT_TRUE(matches(
5247 "class A { class B { void f() { C c; } class C {}; }; };",
5248 varDecl(hasName("c"), hasType(recordDecl(hasName("C"),
5249 hasAncestor(recordDecl(hasName("A"))))))));
5252 TEST(HasAncenstor
, MatchesStatementAncestors
) {
5253 EXPECT_TRUE(matches(
5254 "void f() { if (true) { while (false) { 42; } } }",
5255 integerLiteral(equals(42), hasAncestor(ifStmt()))));
5258 TEST(HasAncestor
, DrillsThroughDifferentHierarchies
) {
5259 EXPECT_TRUE(matches(
5260 "void f() { if (true) { int x = 42; } }",
5261 integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));
5264 TEST(HasAncestor
, BindsRecursiveCombinations
) {
5265 EXPECT_TRUE(matchAndVerifyResultTrue(
5266 "class C { class D { class E { class F { int y; }; }; }; };",
5267 fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),
5268 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("r", 1)));
5271 TEST(HasAncestor
, BindsCombinationsWithHasDescendant
) {
5272 EXPECT_TRUE(matchAndVerifyResultTrue(
5273 "class C { class D { class E { class F { int y; }; }; }; };",
5274 fieldDecl(hasAncestor(
5276 hasDescendant(recordDecl(isDefinition(),
5277 hasAncestor(recordDecl())))
5280 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("d", "E")));
5283 TEST(HasAncestor
, MatchesClosestAncestor
) {
5284 EXPECT_TRUE(matchAndVerifyResultTrue(
5285 "template <typename T> struct C {"
5287 " struct I { void g(T) { int x; } } i; i.g(42);"
5290 "template struct C<int>;",
5291 varDecl(hasName("x"),
5292 hasAncestor(functionDecl(hasParameter(
5293 0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),
5294 std::make_unique
<VerifyIdIsBoundTo
<FunctionDecl
>>("f", "g", 2)));
5297 TEST(HasAncestor
, MatchesInTemplateInstantiations
) {
5298 EXPECT_TRUE(matches(
5299 "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
5301 fieldDecl(hasType(asString("int")),
5302 hasAncestor(recordDecl(hasName("A"))))));
5305 TEST(HasAncestor
, MatchesInImplicitCode
) {
5306 EXPECT_TRUE(matches(
5307 "struct X {}; struct A { A() {} X x; };",
5309 hasAnyConstructorInitializer(withInitializer(expr(
5310 hasAncestor(recordDecl(hasName("A")))))))));
5313 TEST(HasParent
, MatchesOnlyParent
) {
5314 EXPECT_TRUE(matches(
5315 "void f() { if (true) { int x = 42; } }",
5316 compoundStmt(hasParent(ifStmt()))));
5317 EXPECT_TRUE(notMatches(
5318 "void f() { for (;;) { int x = 42; } }",
5319 compoundStmt(hasParent(ifStmt()))));
5320 EXPECT_TRUE(notMatches(
5321 "void f() { if (true) for (;;) { int x = 42; } }",
5322 compoundStmt(hasParent(ifStmt()))));
5325 TEST(MatcherMemoize
, HasParentDiffersFromHas
) {
5326 // Test introduced after detecting a bug in memoization
5327 constexpr auto code
= "void f() { throw 1; }";
5328 EXPECT_TRUE(notMatches(
5330 cxxThrowExpr(hasParent(expr()))));
5331 EXPECT_TRUE(matches(
5333 cxxThrowExpr(has(expr()))));
5334 EXPECT_TRUE(matches(
5336 cxxThrowExpr(anyOf(hasParent(expr()), has(expr())))));
5339 TEST(MatcherMemoize
, HasDiffersFromHasDescendant
) {
5340 // Test introduced after detecting a bug in memoization
5341 constexpr auto code
= "void f() { throw 1+1; }";
5342 EXPECT_TRUE(notMatches(
5344 cxxThrowExpr(has(integerLiteral()))));
5345 EXPECT_TRUE(matches(
5347 cxxThrowExpr(hasDescendant(integerLiteral()))));
5349 notMatches(code
, cxxThrowExpr(allOf(hasDescendant(integerLiteral()),
5350 has(integerLiteral())))));
5352 TEST(HasAncestor
, MatchesAllAncestors
) {
5353 EXPECT_TRUE(matches(
5354 "template <typename T> struct C { static void f() { 42; } };"
5355 "void t() { C<int>::f(); }",
5359 hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
5360 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
5363 TEST(HasAncestor
, ImplicitArrayCopyCtorDeclRefExpr
) {
5364 EXPECT_TRUE(matches("struct MyClass {\n"
5366 " static MyClass Create() { return MyClass(); }\n"
5368 declRefExpr(to(decl(hasAncestor(decl()))))));
5371 TEST(HasAncestor
, AnonymousUnionMemberExpr
) {
5372 EXPECT_TRUE(matches("int F() {\n"
5373 " union { int i; };\n"
5376 memberExpr(member(hasAncestor(decl())))));
5377 EXPECT_TRUE(matches("void f() {\n"
5379 " struct { int a; int b; };\n"
5383 memberExpr(member(hasAncestor(decl())))));
5384 EXPECT_TRUE(matches("void f() {\n"
5386 " struct { int a; int b; };\n"
5390 declRefExpr(to(decl(hasAncestor(decl()))))));
5392 TEST(HasAncestor
, NonParmDependentTemplateParmVarDeclRefExpr
) {
5393 EXPECT_TRUE(matches("struct PartitionAllocator {\n"
5394 " template<typename T>\n"
5395 " static int quantizedSize(int count) {\n"
5398 " void f() { quantizedSize<int>(10); }\n"
5400 declRefExpr(to(decl(hasAncestor(decl()))))));
5403 TEST(HasAncestor
, AddressOfExplicitSpecializationFunction
) {
5404 EXPECT_TRUE(matches("template <class T> void f();\n"
5405 "template <> void f<int>();\n"
5406 "void (*get_f())() { return f<int>; }\n",
5407 declRefExpr(to(decl(hasAncestor(decl()))))));
5410 TEST(HasParent
, MatchesAllParents
) {
5411 EXPECT_TRUE(matches(
5412 "template <typename T> struct C { static void f() { 42; } };"
5413 "void t() { C<int>::f(); }",
5416 hasParent(compoundStmt(hasParent(functionDecl(
5417 hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));
5419 matches("template <typename T> struct C { static void f() { 42; } };"
5420 "void t() { C<int>::f(); }",
5423 hasParent(compoundStmt(hasParent(functionDecl(hasParent(
5424 cxxRecordDecl(unless(isTemplateInstantiation()))))))))));
5425 EXPECT_TRUE(matches(
5426 "template <typename T> struct C { static void f() { 42; } };"
5427 "void t() { C<int>::f(); }",
5428 integerLiteral(equals(42),
5429 hasParent(compoundStmt(
5430 allOf(hasParent(functionDecl(hasParent(
5431 cxxRecordDecl(isTemplateInstantiation())))),
5432 hasParent(functionDecl(hasParent(cxxRecordDecl(
5433 unless(isTemplateInstantiation())))))))))));
5435 notMatches("template <typename T> struct C { static void f() {} };"
5436 "void t() { C<int>::f(); }",
5437 compoundStmt(hasParent(recordDecl()))));
5440 TEST(HasParent
, NoDuplicateParents
) {
5441 class HasDuplicateParents
: public BoundNodesCallback
{
5443 bool run(const BoundNodes
*Nodes
) override
{ return false; }
5444 bool run(const BoundNodes
*Nodes
, ASTContext
*Context
) override
{
5445 const Stmt
*Node
= Nodes
->getNodeAs
<Stmt
>("node");
5446 std::set
<const void *> Parents
;
5447 for (const auto &Parent
: Context
->getParents(*Node
)) {
5448 if (!Parents
.insert(Parent
.getMemoizationData()).second
) {
5455 EXPECT_FALSE(matchAndVerifyResultTrue(
5456 "template <typename T> int Foo() { return 1 + 2; }\n"
5457 "int x = Foo<int>() + Foo<unsigned>();",
5458 stmt().bind("node"), std::make_unique
<HasDuplicateParents
>()));
5461 TEST(HasAnyBase
, BindsInnerBoundNodes
) {
5462 EXPECT_TRUE(matchAndVerifyResultTrue(
5463 "struct Inner {}; struct Proxy : Inner {}; struct Main : public "
5465 cxxRecordDecl(hasName("Main"),
5466 hasAnyBase(cxxBaseSpecifier(hasType(
5467 cxxRecordDecl(hasName("Inner")).bind("base-class")))))
5469 std::make_unique
<VerifyIdIsBoundTo
<CXXRecordDecl
>>("base-class",
5473 TEST(TypeMatching
, PointeeTypes
) {
5474 EXPECT_TRUE(matches("int b; int &a = b;",
5475 referenceType(pointee(builtinType()))));
5476 EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));
5478 EXPECT_TRUE(matches("int *a;",
5479 loc(pointerType(pointee(builtinType())))));
5481 EXPECT_TRUE(matches(
5483 pointerType(pointee(isConstQualified(), builtinType()))));
5484 EXPECT_TRUE(notMatches(
5486 pointerType(pointee(isConstQualified(), builtinType()))));
5489 TEST(ElaboratedTypeNarrowing
, hasQualifier
) {
5490 EXPECT_TRUE(matches(
5497 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5498 EXPECT_TRUE(notMatches(
5503 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5504 EXPECT_TRUE(notMatches(
5507 elaboratedType(hasQualifier(nestedNameSpecifier()))));
5510 TEST(ElaboratedTypeNarrowing
, namesType
) {
5511 EXPECT_TRUE(matches(
5518 elaboratedType(elaboratedType(namesType(recordType(
5519 hasDeclaration(namedDecl(hasName("D")))))))));
5520 EXPECT_TRUE(notMatches(
5525 elaboratedType(elaboratedType(namesType(typedefType())))));
5528 TEST(NNS
, BindsNestedNameSpecifiers
) {
5529 EXPECT_TRUE(matchAndVerifyResultTrue(
5530 "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
5531 nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
5532 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>(
5533 "nns", "ns::struct E::")));
5536 TEST(NNS
, BindsNestedNameSpecifierLocs
) {
5537 EXPECT_TRUE(matchAndVerifyResultTrue(
5538 "namespace ns { struct B {}; } ns::B b;",
5539 loc(nestedNameSpecifier()).bind("loc"),
5540 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("loc", 1)));
5543 TEST(NNS
, DescendantsOfNestedNameSpecifiers
) {
5544 StringRef Fragment
=
5545 "namespace a { struct A { struct B { struct C {}; }; }; };"
5546 "void f() { a::A::B::C c; }";
5547 EXPECT_TRUE(matches(
5549 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5550 hasDescendant(nestedNameSpecifier(
5551 specifiesNamespace(hasName("a")))))));
5552 EXPECT_TRUE(notMatches(
5554 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5555 has(nestedNameSpecifier(
5556 specifiesNamespace(hasName("a")))))));
5557 EXPECT_TRUE(matches(
5559 nestedNameSpecifier(specifiesType(asString("struct a::A")),
5560 has(nestedNameSpecifier(
5561 specifiesNamespace(hasName("a")))))));
5563 // Not really useful because a NestedNameSpecifier can af at most one child,
5564 // but to complete the interface.
5565 EXPECT_TRUE(matchAndVerifyResultTrue(
5567 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5568 forEach(nestedNameSpecifier().bind("x"))),
5569 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>("x", 1)));
5572 TEST(NNS
, NestedNameSpecifiersAsDescendants
) {
5573 StringRef Fragment
=
5574 "namespace a { struct A { struct B { struct C {}; }; }; };"
5575 "void f() { a::A::B::C c; }";
5576 EXPECT_TRUE(matches(
5578 decl(hasDescendant(nestedNameSpecifier(specifiesType(
5579 asString("struct a::A")))))));
5580 EXPECT_TRUE(matchAndVerifyResultTrue(
5582 functionDecl(hasName("f"),
5583 forEachDescendant(nestedNameSpecifier().bind("x"))),
5584 // Nested names: a, a::A and a::A::B.
5585 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifier
>>("x", 3)));
5588 TEST(NNSLoc
, DescendantsOfNestedNameSpecifierLocs
) {
5589 StringRef Fragment
=
5590 "namespace a { struct A { struct B { struct C {}; }; }; };"
5591 "void f() { a::A::B::C c; }";
5592 EXPECT_TRUE(matches(
5594 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5595 hasDescendant(loc(nestedNameSpecifier(
5596 specifiesNamespace(hasName("a"))))))));
5597 EXPECT_TRUE(notMatches(
5599 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5600 has(loc(nestedNameSpecifier(
5601 specifiesNamespace(hasName("a"))))))));
5602 EXPECT_TRUE(matches(
5604 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
5605 has(loc(nestedNameSpecifier(
5606 specifiesNamespace(hasName("a"))))))));
5608 EXPECT_TRUE(matchAndVerifyResultTrue(
5610 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5611 forEach(nestedNameSpecifierLoc().bind("x"))),
5612 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("x", 1)));
5615 TEST(NNSLoc
, NestedNameSpecifierLocsAsDescendants
) {
5616 StringRef Fragment
=
5617 "namespace a { struct A { struct B { struct C {}; }; }; };"
5618 "void f() { a::A::B::C c; }";
5619 EXPECT_TRUE(matches(
5621 decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
5622 asString("struct a::A"))))))));
5623 EXPECT_TRUE(matchAndVerifyResultTrue(
5625 functionDecl(hasName("f"),
5626 forEachDescendant(nestedNameSpecifierLoc().bind("x"))),
5627 // Nested names: a, a::A and a::A::B.
5628 std::make_unique
<VerifyIdIsBoundTo
<NestedNameSpecifierLoc
>>("x", 3)));
5631 TEST(Attr
, AttrsAsDescendants
) {
5632 StringRef Fragment
= "namespace a { struct [[clang::warn_unused_result]] "
5633 "F{}; [[noreturn]] void foo(); }";
5634 EXPECT_TRUE(matches(Fragment
, namespaceDecl(hasDescendant(attr()))));
5635 EXPECT_TRUE(matchAndVerifyResultTrue(
5637 namespaceDecl(hasName("a"),
5638 forEachDescendant(attr(unless(isImplicit())).bind("x"))),
5639 std::make_unique
<VerifyIdIsBoundTo
<Attr
>>("x", 2)));
5642 TEST(Attr
, ParentsOfAttrs
) {
5643 StringRef Fragment
=
5644 "namespace a { struct [[clang::warn_unused_result]] F{}; }";
5645 EXPECT_TRUE(matches(Fragment
, attr(hasAncestor(namespaceDecl()))));
5648 template <typename T
> class VerifyMatchOnNode
: public BoundNodesCallback
{
5650 VerifyMatchOnNode(StringRef Id
, const internal::Matcher
<T
> &InnerMatcher
,
5652 : Id(Id
), InnerMatcher(InnerMatcher
), InnerId(InnerId
) {
5655 bool run(const BoundNodes
*Nodes
) override
{ return false; }
5657 bool run(const BoundNodes
*Nodes
, ASTContext
*Context
) override
{
5658 const T
*Node
= Nodes
->getNodeAs
<T
>(Id
);
5659 return selectFirst
<T
>(InnerId
, match(InnerMatcher
, *Node
, *Context
)) !=
5664 internal::Matcher
<T
> InnerMatcher
;
5665 std::string InnerId
;
5668 TEST(MatchFinder
, CanMatchDeclarationsRecursively
) {
5669 EXPECT_TRUE(matchAndVerifyResultTrue(
5670 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5671 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5672 "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),
5674 EXPECT_TRUE(matchAndVerifyResultFalse(
5675 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5676 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5677 "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),
5681 TEST(MatchFinder
, CanMatchStatementsRecursively
) {
5682 EXPECT_TRUE(matchAndVerifyResultTrue(
5683 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5684 std::make_unique
<VerifyMatchOnNode
<Stmt
>>(
5685 "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));
5686 EXPECT_TRUE(matchAndVerifyResultFalse(
5687 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5688 std::make_unique
<VerifyMatchOnNode
<Stmt
>>(
5689 "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));
5692 TEST(MatchFinder
, CanMatchSingleNodesRecursively
) {
5693 EXPECT_TRUE(matchAndVerifyResultTrue(
5694 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5695 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5696 "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));
5697 EXPECT_TRUE(matchAndVerifyResultFalse(
5698 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5699 std::make_unique
<VerifyMatchOnNode
<Decl
>>(
5700 "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));
5703 TEST(StatementMatcher
, HasReturnValue
) {
5704 StatementMatcher RetVal
= returnStmt(hasReturnValue(binaryOperator()));
5705 EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal
));
5706 EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal
));
5707 EXPECT_FALSE(matches("void F() { return; }", RetVal
));
5710 TEST(StatementMatcher
, ForFunction
) {
5711 StringRef CppString1
= "struct PosVec {"
5712 " PosVec& operator=(const PosVec&) {"
5713 " auto x = [] { return 1; };"
5717 StringRef CppString2
= "void F() {"
5727 returnStmt(forFunction(hasName("operator=")),
5728 has(unaryOperator(hasOperatorName("*"))))));
5732 returnStmt(forFunction(hasName("operator=")),
5733 has(integerLiteral()))));
5737 returnStmt(forFunction(hasName("operator()")),
5738 has(integerLiteral()))));
5739 EXPECT_TRUE(matches(CppString2
, returnStmt(forFunction(hasName("F2")))));
5740 EXPECT_TRUE(notMatches(CppString2
, returnStmt(forFunction(hasName("F")))));
5743 TEST(StatementMatcher
, ForCallable
) {
5744 // These tests are copied over from the forFunction() test above.
5745 StringRef CppString1
= "struct PosVec {"
5746 " PosVec& operator=(const PosVec&) {"
5747 " auto x = [] { return 1; };"
5751 StringRef CppString2
= "void F() {"
5762 returnStmt(forCallable(functionDecl(hasName("operator="))),
5763 has(unaryOperator(hasOperatorName("*"))))));
5767 returnStmt(forCallable(functionDecl(hasName("operator="))),
5768 has(integerLiteral()))));
5772 returnStmt(forCallable(functionDecl(hasName("operator()"))),
5773 has(integerLiteral()))));
5774 EXPECT_TRUE(matches(CppString2
,
5775 returnStmt(forCallable(functionDecl(hasName("F2"))))));
5776 EXPECT_TRUE(notMatches(CppString2
,
5777 returnStmt(forCallable(functionDecl(hasName("F"))))));
5779 // These tests are specific to forCallable().
5780 StringRef ObjCString1
= "@interface I"
5785 " void (^block)() = ^{ 0x2b | ~0x2b; };"
5792 binaryOperator(forCallable(blockDecl()))));
5797 binaryOperator(forCallable(objcMethodDecl()))));
5799 StringRef ObjCString2
= "@interface I"
5805 " void (^block)() = ^{};"
5812 binaryOperator(forCallable(objcMethodDecl()))));
5817 binaryOperator(forCallable(blockDecl()))));
5820 TEST(Matcher
, ForEachOverriden
) {
5821 const auto ForEachOverriddenInClass
= [](const char *ClassName
) {
5822 return cxxMethodDecl(ofClass(hasName(ClassName
)), isVirtual(),
5823 forEachOverridden(cxxMethodDecl().bind("overridden")))
5826 static const char Code1
[] = "class A { virtual void f(); };"
5827 "class B : public A { void f(); };"
5828 "class C : public B { void f(); };";
5829 // C::f overrides A::f.
5830 EXPECT_TRUE(matchAndVerifyResultTrue(
5831 Code1
, ForEachOverriddenInClass("C"),
5832 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 1)));
5833 EXPECT_TRUE(matchAndVerifyResultTrue(
5834 Code1
, ForEachOverriddenInClass("C"),
5835 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
5837 // B::f overrides A::f.
5838 EXPECT_TRUE(matchAndVerifyResultTrue(
5839 Code1
, ForEachOverriddenInClass("B"),
5840 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 1)));
5841 EXPECT_TRUE(matchAndVerifyResultTrue(
5842 Code1
, ForEachOverriddenInClass("B"),
5843 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
5845 // A::f overrides nothing.
5846 EXPECT_TRUE(notMatches(Code1
, ForEachOverriddenInClass("A")));
5848 static const char Code2
[] =
5849 "class A1 { virtual void f(); };"
5850 "class A2 { virtual void f(); };"
5851 "class B : public A1, public A2 { void f(); };";
5852 // B::f overrides A1::f and A2::f. This produces two matches.
5853 EXPECT_TRUE(matchAndVerifyResultTrue(
5854 Code2
, ForEachOverriddenInClass("B"),
5855 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("override", "f", 2)));
5856 EXPECT_TRUE(matchAndVerifyResultTrue(
5857 Code2
, ForEachOverriddenInClass("B"),
5858 std::make_unique
<VerifyIdIsBoundTo
<CXXMethodDecl
>>("overridden", "f",
5860 // A1::f overrides nothing.
5861 EXPECT_TRUE(notMatches(Code2
, ForEachOverriddenInClass("A1")));
5864 TEST(Matcher
, HasAnyDeclaration
) {
5865 StringRef Fragment
= "void foo(int p1);"
5866 "void foo(int *p2);"
5868 "template <typename T> void baz(T t) { foo(t); }";
5871 matches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
5872 hasParameter(0, parmVarDecl(hasName("p1"))))))));
5874 matches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
5875 hasParameter(0, parmVarDecl(hasName("p2"))))))));
5877 notMatches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
5878 hasParameter(0, parmVarDecl(hasName("p3"))))))));
5879 EXPECT_TRUE(notMatches(Fragment
, unresolvedLookupExpr(hasAnyDeclaration(
5880 functionDecl(hasName("bar"))))));
5883 TEST(SubstTemplateTypeParmType
, HasReplacementType
) {
5884 StringRef Fragment
= "template<typename T>"
5888 EXPECT_TRUE(matches(Fragment
, substTemplateTypeParmType(hasReplacementType(
5889 qualType(asString("int"))))));
5890 EXPECT_TRUE(notMatches(Fragment
, substTemplateTypeParmType(hasReplacementType(
5891 qualType(asString("double"))))));
5893 notMatches("template<int N>"
5895 "double j = F<5>();",
5896 substTemplateTypeParmType(hasReplacementType(qualType()))));
5899 TEST(ClassTemplateSpecializationDecl
, HasSpecializedTemplate
) {
5900 auto Matcher
= classTemplateSpecializationDecl(
5901 hasSpecializedTemplate(classTemplateDecl()));
5903 matches("template<typename T> class A {}; typedef A<int> B;", Matcher
));
5904 EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher
));
5907 TEST(CXXNewExpr
, Array
) {
5908 StatementMatcher NewArray
= cxxNewExpr(isArray());
5910 EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray
));
5911 EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray
));
5913 StatementMatcher NewArraySize10
=
5914 cxxNewExpr(hasArraySize(integerLiteral(equals(10))));
5916 matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10
));
5918 notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10
));
5921 TEST(CXXNewExpr
, PlacementArgs
) {
5922 StatementMatcher IsPlacementNew
= cxxNewExpr(hasAnyPlacementArg(anything()));
5924 EXPECT_TRUE(matches(R
"(
5925 void* operator new(decltype(sizeof(void*)), void*);
5926 int *foo(void* Storage) {
5927 return new (Storage) int;
5931 EXPECT_TRUE(matches(R
"(
5932 void* operator new(decltype(sizeof(void*)), void*, unsigned);
5933 int *foo(void* Storage) {
5934 return new (Storage, 16) int;
5936 cxxNewExpr(hasPlacementArg(
5937 1, ignoringImpCasts(integerLiteral(equals(16)))))));
5939 EXPECT_TRUE(notMatches(R
"(
5940 void* operator new(decltype(sizeof(void*)), void*);
5941 int *foo(void* Storage) {
5947 TEST(HasUnqualifiedLoc
, BindsToConstIntVarDecl
) {
5948 EXPECT_TRUE(matches(
5950 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
5951 hasUnqualifiedLoc(loc(asString("int"))))))));
5954 TEST(HasUnqualifiedLoc
, BindsToVolatileIntVarDecl
) {
5955 EXPECT_TRUE(matches(
5956 "volatile int x = 0;",
5957 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
5958 hasUnqualifiedLoc(loc(asString("int"))))))));
5961 TEST(HasUnqualifiedLoc
, BindsToConstVolatileIntVarDecl
) {
5962 EXPECT_TRUE(matches(
5963 "const volatile int x = 0;",
5964 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
5965 hasUnqualifiedLoc(loc(asString("int"))))))));
5968 TEST(HasUnqualifiedLoc
, BindsToConstPointerVarDecl
) {
5969 auto matcher
= varDecl(
5971 hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))));
5972 EXPECT_TRUE(matches("int* const x = 0;", matcher
));
5973 EXPECT_TRUE(notMatches("int const x = 0;", matcher
));
5976 TEST(HasUnqualifiedLoc
, BindsToPointerToConstVolatileIntVarDecl
) {
5978 matches("const volatile int* x = 0;",
5979 varDecl(hasName("x"),
5980 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(
5981 hasUnqualifiedLoc(loc(asString("int"))))))))));
5984 TEST(HasUnqualifiedLoc
, BindsToConstIntFunctionDecl
) {
5986 matches("const int f() { return 5; }",
5987 functionDecl(hasName("f"),
5988 hasReturnTypeLoc(qualifiedTypeLoc(
5989 hasUnqualifiedLoc(loc(asString("int"))))))));
5992 TEST(HasUnqualifiedLoc
, FloatBindsToConstFloatVarDecl
) {
5993 EXPECT_TRUE(matches(
5994 "const float x = 0;",
5995 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
5996 hasUnqualifiedLoc(loc(asString("float"))))))));
5999 TEST(HasUnqualifiedLoc
, FloatDoesNotBindToIntVarDecl
) {
6000 EXPECT_TRUE(notMatches(
6002 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6003 hasUnqualifiedLoc(loc(asString("float"))))))));
6006 TEST(HasUnqualifiedLoc
, FloatDoesNotBindToConstIntVarDecl
) {
6007 EXPECT_TRUE(notMatches(
6009 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6010 hasUnqualifiedLoc(loc(asString("float"))))))));
6013 TEST(HasReturnTypeLoc
, BindsToIntReturnTypeLoc
) {
6014 EXPECT_TRUE(matches(
6015 "int f() { return 5; }",
6016 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6019 TEST(HasReturnTypeLoc
, BindsToFloatReturnTypeLoc
) {
6020 EXPECT_TRUE(matches(
6021 "float f() { return 5.0; }",
6022 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6025 TEST(HasReturnTypeLoc
, BindsToVoidReturnTypeLoc
) {
6026 EXPECT_TRUE(matches(
6028 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));
6031 TEST(HasReturnTypeLoc
, FloatDoesNotBindToIntReturnTypeLoc
) {
6032 EXPECT_TRUE(notMatches(
6033 "int f() { return 5; }",
6034 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6037 TEST(HasReturnTypeLoc
, IntDoesNotBindToFloatReturnTypeLoc
) {
6038 EXPECT_TRUE(notMatches(
6039 "float f() { return 5.0; }",
6040 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6043 TEST(HasPointeeLoc
, BindsToAnyPointeeTypeLoc
) {
6044 auto matcher
= varDecl(hasName("x"),
6045 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6046 EXPECT_TRUE(matches("int* x;", matcher
));
6047 EXPECT_TRUE(matches("float* x;", matcher
));
6048 EXPECT_TRUE(matches("char* x;", matcher
));
6049 EXPECT_TRUE(matches("void* x;", matcher
));
6052 TEST(HasPointeeLoc
, DoesNotBindToTypeLocWithoutPointee
) {
6053 auto matcher
= varDecl(hasName("x"),
6054 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6055 EXPECT_TRUE(notMatches("int x;", matcher
));
6056 EXPECT_TRUE(notMatches("float x;", matcher
));
6057 EXPECT_TRUE(notMatches("char x;", matcher
));
6060 TEST(HasPointeeLoc
, BindsToTypeLocPointingToInt
) {
6062 matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6065 TEST(HasPointeeLoc
, BindsToTypeLocPointingToIntPointer
) {
6066 EXPECT_TRUE(matches("int** x;",
6067 pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));
6070 TEST(HasPointeeLoc
, BindsToTypeLocPointingToTypeLocPointingToInt
) {
6071 EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
6072 hasPointeeLoc(loc(asString("int"))))))));
6075 TEST(HasPointeeLoc
, BindsToTypeLocPointingToFloat
) {
6076 EXPECT_TRUE(matches("float* x;",
6077 pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6080 TEST(HasPointeeLoc
, IntPointeeDoesNotBindToTypeLocPointingToFloat
) {
6081 EXPECT_TRUE(notMatches("float* x;",
6082 pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6085 TEST(HasPointeeLoc
, FloatPointeeDoesNotBindToTypeLocPointingToInt
) {
6086 EXPECT_TRUE(notMatches(
6087 "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6090 TEST(HasReferentLoc
, BindsToAnyReferentTypeLoc
) {
6091 auto matcher
= varDecl(
6092 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6093 EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher
));
6094 EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher
));
6095 EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher
));
6096 EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher
));
6097 EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher
));
6100 TEST(HasReferentLoc
, DoesNotBindToTypeLocWithoutReferent
) {
6101 auto matcher
= varDecl(
6102 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6103 EXPECT_TRUE(notMatches("int r;", matcher
));
6104 EXPECT_TRUE(notMatches("int r = 3;", matcher
));
6105 EXPECT_TRUE(notMatches("const int r = 3;", matcher
));
6106 EXPECT_TRUE(notMatches("int* r;", matcher
));
6107 EXPECT_TRUE(notMatches("float r;", matcher
));
6108 EXPECT_TRUE(notMatches("char r;", matcher
));
6111 TEST(HasReferentLoc
, BindsToAnyRvalueReference
) {
6112 auto matcher
= varDecl(
6113 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6114 EXPECT_TRUE(matches("int&& r = 3;", matcher
));
6115 EXPECT_TRUE(matches("auto&& r = 3;", matcher
));
6116 EXPECT_TRUE(matches("float&& r = 3.0;", matcher
));
6119 TEST(HasReferentLoc
, BindsToIntReferenceTypeLoc
) {
6120 EXPECT_TRUE(matches("int rr = 3; int& r = rr;",
6121 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6124 TEST(HasReferentLoc
, BindsToIntRvalueReferenceTypeLoc
) {
6125 EXPECT_TRUE(matches("int&& r = 3;",
6126 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6129 TEST(HasReferentLoc
, BindsToFloatReferenceTypeLoc
) {
6131 matches("float rr = 3.0; float& r = rr;",
6132 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6135 TEST(HasReferentLoc
, BindsToParameterWithIntReferenceTypeLoc
) {
6136 EXPECT_TRUE(matches(
6137 "int f(int& r) { return r; }",
6138 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6139 hasReferentLoc(loc(asString("int"))))))));
6142 TEST(HasReferentLoc
, IntReferenceDoesNotBindToFloatReferenceTypeLoc
) {
6144 notMatches("float rr = 3.0; float& r = rr;",
6145 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6148 TEST(HasReferentLoc
, FloatReferenceDoesNotBindToIntReferenceTypeLoc
) {
6150 notMatches("int rr = 3; int& r = rr;",
6151 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6154 TEST(HasReferentLoc
, DoesNotBindToParameterWithoutIntReferenceTypeLoc
) {
6155 EXPECT_TRUE(notMatches(
6156 "int f(int r) { return r; }",
6157 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6158 hasReferentLoc(loc(asString("int"))))))));
6161 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithIntArgument
) {
6162 EXPECT_TRUE(matches(
6163 "template<typename T> class A {}; A<int> a;",
6164 varDecl(hasName("a"),
6165 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6166 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6167 hasTypeLoc(loc(asString("int")))))))))));
6170 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithDoubleArgument
) {
6171 EXPECT_TRUE(matches(
6172 "template<typename T> class A {}; A<double> a;",
6173 varDecl(hasName("a"),
6174 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6175 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6176 hasTypeLoc(loc(asString("double")))))))))));
6179 TEST(HasAnyTemplateArgumentLoc
, BindsToExplicitSpecializationWithIntArgument
) {
6180 EXPECT_TRUE(matches(
6181 "template<typename T> class A {}; template<> class A<int> {};",
6182 classTemplateSpecializationDecl(
6184 hasTypeLoc(templateSpecializationTypeLoc(
6185 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
6188 TEST(HasAnyTemplateArgumentLoc
,
6189 BindsToExplicitSpecializationWithDoubleArgument
) {
6190 EXPECT_TRUE(matches(
6191 "template<typename T> class A {}; template<> class A<double> {};",
6192 classTemplateSpecializationDecl(
6194 hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6195 hasTypeLoc(loc(asString("double")))))))));
6198 TEST(HasAnyTemplateArgumentLoc
, BindsToSpecializationWithMultipleArguments
) {
6200 template<typename T, typename U> class A {};
6201 template<> class A<double, int> {};
6204 matches(code
, classTemplateSpecializationDecl(
6205 hasName("A"), hasTypeLoc(templateSpecializationTypeLoc(
6206 hasAnyTemplateArgumentLoc(hasTypeLoc(
6207 loc(asString("double")))))))));
6208 EXPECT_TRUE(matches(
6210 classTemplateSpecializationDecl(
6212 hasTypeLoc(templateSpecializationTypeLoc(
6213 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))))));
6216 TEST(HasAnyTemplateArgumentLoc
, DoesNotBindToSpecializationWithIntArgument
) {
6217 EXPECT_TRUE(notMatches(
6218 "template<typename T> class A {}; A<int> a;",
6219 classTemplateSpecializationDecl(
6221 hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6222 hasTypeLoc(loc(asString("double")))))))));
6225 TEST(HasAnyTemplateArgumentLoc
,
6226 DoesNotBindToExplicitSpecializationWithIntArgument
) {
6227 EXPECT_TRUE(notMatches(
6228 "template<typename T> class A {}; template<> class A<int> {};",
6229 classTemplateSpecializationDecl(
6231 hasTypeLoc(templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6232 hasTypeLoc(loc(asString("double")))))))));
6235 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithIntArgument
) {
6237 matches("template<typename T> class A {}; A<int> a;",
6238 varDecl(hasName("a"),
6239 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6240 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6241 0, hasTypeLoc(loc(asString("int")))))))))));
6244 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithDoubleArgument
) {
6246 matches("template<typename T> class A {}; A<double> a;",
6247 varDecl(hasName("a"),
6248 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6249 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6250 0, hasTypeLoc(loc(asString("double")))))))))));
6253 TEST(HasTemplateArgumentLoc
, BindsToExplicitSpecializationWithIntArgument
) {
6254 EXPECT_TRUE(matches(
6255 "template<typename T> class A {}; template<> class A<int> {};",
6256 classTemplateSpecializationDecl(
6258 hasTypeLoc(templateSpecializationTypeLoc(
6259 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))))));
6262 TEST(HasTemplateArgumentLoc
, BindsToExplicitSpecializationWithDoubleArgument
) {
6263 EXPECT_TRUE(matches(
6264 "template<typename T> class A {}; template<> class A<double> {};",
6265 classTemplateSpecializationDecl(
6267 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6268 0, hasTypeLoc(loc(asString("double")))))))));
6271 TEST(HasTemplateArgumentLoc
, BindsToSpecializationWithMultipleArguments
) {
6273 template<typename T, typename U> class A {};
6274 template<> class A<double, int> {};
6276 EXPECT_TRUE(matches(
6277 code
, classTemplateSpecializationDecl(
6279 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6280 0, hasTypeLoc(loc(asString("double")))))))));
6281 EXPECT_TRUE(matches(
6282 code
, classTemplateSpecializationDecl(
6284 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6285 1, hasTypeLoc(loc(asString("int")))))))));
6288 TEST(HasTemplateArgumentLoc
, DoesNotBindToSpecializationWithIntArgument
) {
6289 EXPECT_TRUE(notMatches(
6290 "template<typename T> class A {}; A<int> a;",
6291 classTemplateSpecializationDecl(
6293 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6294 0, hasTypeLoc(loc(asString("double")))))))));
6297 TEST(HasTemplateArgumentLoc
,
6298 DoesNotBindToExplicitSpecializationWithIntArgument
) {
6299 EXPECT_TRUE(notMatches(
6300 "template<typename T> class A {}; template<> class A<int> {};",
6301 classTemplateSpecializationDecl(
6303 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6304 0, hasTypeLoc(loc(asString("double")))))))));
6307 TEST(HasTemplateArgumentLoc
,
6308 DoesNotBindToSpecializationWithMisplacedArguments
) {
6310 template<typename T, typename U> class A {};
6311 template<> class A<double, int> {};
6313 EXPECT_TRUE(notMatches(
6314 code
, classTemplateSpecializationDecl(
6316 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6317 1, hasTypeLoc(loc(asString("double")))))))));
6318 EXPECT_TRUE(notMatches(
6319 code
, classTemplateSpecializationDecl(
6321 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6322 0, hasTypeLoc(loc(asString("int")))))))));
6325 TEST(HasTemplateArgumentLoc
, DoesNotBindWithBadIndex
) {
6327 template<typename T, typename U> class A {};
6328 template<> class A<double, int> {};
6330 EXPECT_TRUE(notMatches(
6331 code
, classTemplateSpecializationDecl(
6333 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6334 -1, hasTypeLoc(loc(asString("double")))))))));
6335 EXPECT_TRUE(notMatches(
6336 code
, classTemplateSpecializationDecl(
6338 hasTypeLoc(templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6339 100, hasTypeLoc(loc(asString("int")))))))));
6342 TEST(HasTemplateArgumentLoc
, BindsToDeclRefExprWithIntArgument
) {
6343 EXPECT_TRUE(matches(R
"(
6344 template<typename T> T f(T t) { return t; }
6345 int g() { int i = f<int>(3); return i; }
6347 declRefExpr(to(functionDecl(hasName("f"))),
6348 hasTemplateArgumentLoc(
6349 0, hasTypeLoc(loc(asString("int")))))));
6352 TEST(HasTemplateArgumentLoc
, BindsToDeclRefExprWithDoubleArgument
) {
6353 EXPECT_TRUE(matches(
6355 template<typename T> T f(T t) { return t; }
6356 double g() { double i = f<double>(3.0); return i; }
6359 to(functionDecl(hasName("f"))),
6360 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6363 TEST(HasTemplateArgumentLoc
, DoesNotBindToDeclRefExprWithDoubleArgument
) {
6364 EXPECT_TRUE(notMatches(
6366 template<typename T> T f(T t) { return t; }
6367 double g() { double i = f<double>(3.0); return i; }
6370 to(functionDecl(hasName("f"))),
6371 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6374 TEST(HasNamedTypeLoc
, BindsToElaboratedObjectDeclaration
) {
6375 EXPECT_TRUE(matches(
6377 template <typename T>
6381 varDecl(hasName("c"),
6382 hasTypeLoc(elaboratedTypeLoc(
6383 hasNamedTypeLoc(templateSpecializationTypeLoc(
6384 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6387 TEST(HasNamedTypeLoc
, DoesNotBindToNonElaboratedObjectDeclaration
) {
6388 EXPECT_TRUE(matches(
6390 template <typename T>
6394 varDecl(hasName("c"),
6395 hasTypeLoc(elaboratedTypeLoc(
6396 hasNamedTypeLoc(templateSpecializationTypeLoc(
6397 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6400 } // namespace ast_matchers
6401 } // namespace clang