[NFC][Coroutines] Use structured binding with llvm::enumerate in CoroSplit (#116879)
[llvm-project.git] / clang / unittests / ASTMatchers / ASTMatchersTraversalTest.cpp
blob1d18869a6b8afcc0b039cce5732a198daae66bb9
1 //= unittests/ASTMatchers/ASTMatchersTraversalTest.cpp - matchers unit tests =//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
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"
21 namespace clang {
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) {
32 EXPECT_TRUE(matches(
33 "template <typename T> struct A {"
34 " template <typename T2> struct F {};"
35 "};"
36 "template <typename T> struct B : A<T>::template F<T> {};"
37 "B<int> b;",
38 cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
41 TEST(DeclarationMatcher, hasDeclContext) {
42 EXPECT_TRUE(matches(
43 "namespace N {"
44 " namespace M {"
45 " class D {};"
46 " }"
47 "}",
48 recordDecl(hasDeclContext(namespaceDecl(hasName("M"))))));
49 EXPECT_TRUE(notMatches(
50 "namespace N {"
51 " namespace M {"
52 " class D {};"
53 " }"
54 "}",
55 recordDecl(hasDeclContext(namespaceDecl(hasName("N"))))));
57 EXPECT_TRUE(matches("namespace {"
58 " namespace M {"
59 " class D {};"
60 " }"
61 "}",
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) {
117 EXPECT_TRUE(matches(
118 "int* i;",
119 varDecl(hasName("i"), hasType(qualType(has(builtinType()))))));
120 EXPECT_TRUE(notMatches(
121 "int* i;",
122 varDecl(hasName("i"), hasType(qualType(has(pointerType()))))));
125 TEST(StatementMatcher, Has) {
126 StatementMatcher HasVariableI =
127 expr(hasType(pointsTo(recordDecl(hasName("X")))),
128 has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i")))))));
130 EXPECT_TRUE(matches(
131 "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));
132 EXPECT_TRUE(notMatches(
133 "class X; X *x(int); void c() { int i; x(42); }", HasVariableI));
136 TEST(StatementMatcher, HasDescendant) {
137 StatementMatcher HasDescendantVariableI =
138 expr(hasType(pointsTo(recordDecl(hasName("X")))),
139 hasDescendant(declRefExpr(to(varDecl(hasName("i"))))));
141 EXPECT_TRUE(matches(
142 "class X; X *x(bool); bool b(int); void c() { int i; x(b(i)); }",
143 HasDescendantVariableI));
144 EXPECT_TRUE(notMatches(
145 "class X; X *x(bool); bool b(int); void c() { int i; x(b(42)); }",
146 HasDescendantVariableI));
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; };",
159 TypeDerivedFromA));
160 EXPECT_TRUE(notMatches("class A {};", TypeA));
162 TypeMatcher TypeAHasClassB = hasDeclaration(
163 recordDecl(hasName("A"), has(recordDecl(hasName("B")))));
165 EXPECT_TRUE(
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 {"
191 " void f(S s);"
192 "};",
193 parmVarDecl(hasType(elaboratedType(
194 namesType(injectedClassNameType()))))));
195 EXPECT_TRUE(notMatches("template <typename T> struct S {"
196 " void g(S<T> s);"
197 "};",
198 parmVarDecl(hasType(elaboratedType(
199 namesType(injectedClassNameType()))))));
200 // InjectedClassNameType -> CXXRecordDecl
201 EXPECT_TRUE(matches("template <typename T> struct S {"
202 " void f(S s);"
203 "};",
204 parmVarDecl(hasType(namedDecl(hasName("S"))))));
206 static const char Using[] = "template <typename T>"
207 "struct Base {"
208 " typedef T Foo;"
209 "};"
211 "template <typename T>"
212 "struct S : private Base<T> {"
213 " using typename Base<T>::Foo;"
214 " void f(Foo);"
215 "};";
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) {
238 EXPECT_TRUE(matches(
239 "namespace n { template <typename T> struct X {}; }"
240 "void f(n::X<int>);",
241 parmVarDecl(hasType(qualType(hasDeclaration(cxxRecordDecl()))))));
242 EXPECT_TRUE(matches(
243 "namespace n { template <typename T> struct X {}; }"
244 "void f(n::X<int>);",
245 parmVarDecl(hasType(elaboratedType(hasDeclaration(cxxRecordDecl()))))));
248 TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) {
249 EXPECT_TRUE(matches(
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) {
258 EXPECT_TRUE(matches(
259 "template <typename T> class A {}; A<int> a;",
260 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
261 hasDeclaration(namedDecl(hasName("A"))))))))));
262 EXPECT_TRUE(matches(
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"))))))))));
267 EXPECT_TRUE(matches(
268 "template <typename T> class A {}; A<int> a;",
269 varDecl(hasType(elaboratedType(namesType(
270 templateSpecializationType(hasDeclaration(cxxRecordDecl()))))))));
273 TEST(HasDeclaration, HasDeclarationOfCXXNewExpr) {
274 EXPECT_TRUE(
275 matches("int *A = new int();",
276 cxxNewExpr(hasDeclaration(functionDecl(parameterCountIs(1))))));
279 TEST(HasDeclaration, HasDeclarationOfTypeAlias) {
280 EXPECT_TRUE(matches(
281 "template <typename T> using C = T; C<int> c;",
282 varDecl(hasType(elaboratedType(namesType(templateSpecializationType(
283 hasDeclaration(typeAliasTemplateDecl()))))))));
286 TEST(HasUnqualifiedDesugaredType, DesugarsUsing) {
287 EXPECT_TRUE(
288 matches("struct A {}; using B = A; B b;",
289 varDecl(hasType(hasUnqualifiedDesugaredType(recordType())))));
290 EXPECT_TRUE(
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")))))));
300 EXPECT_TRUE(matches(
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")));
312 EXPECT_TRUE(
313 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));
314 EXPECT_TRUE(
315 notMatches("class X {}; void y(X *x) { x; }",
316 expr(hasType(ClassX))));
317 EXPECT_TRUE(
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")));
324 EXPECT_TRUE(
325 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));
326 EXPECT_TRUE(
327 notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
328 EXPECT_TRUE(
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"));
344 EXPECT_TRUE(
345 matches("class X {}; void y(X &x) { x; }", expr(hasType(ClassX))));
346 EXPECT_TRUE(
347 notMatches("class X {}; void y(X *x) { x; }",
348 expr(hasType(ClassX))));
351 TEST(HasType, TakesDeclMatcherAndMatchesValueDecl) {
352 DeclarationMatcher ClassX = recordDecl(hasName("X"));
353 EXPECT_TRUE(
354 matches("class X {}; void y() { X x; }", varDecl(hasType(ClassX))));
355 EXPECT_TRUE(
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,
392 {"-fblocks"}));
395 TEST(HasTypeLoc, MatchesCXXBaseSpecifierAndCtorInitializer) {
396 llvm::StringRef code = R"cpp(
397 class Foo {};
398 class Bar : public Foo {
399 Bar() : Foo() {}
401 )cpp";
403 EXPECT_TRUE(matches(
404 code, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("Foo")))))));
405 EXPECT_TRUE(
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) {
422 EXPECT_TRUE(
423 matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);",
424 cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("Foo"))))));
427 TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) {
428 EXPECT_TRUE(
429 matches("template <typename T> T make() { return T(); }",
430 cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T"))))));
433 TEST(HasTypeLoc, MatchesCompoundLiteralExpr) {
434 EXPECT_TRUE(
435 matches("int* x = (int[2]) { 0, 1 };",
436 compoundLiteralExpr(hasTypeLoc(loc(asString("int[2]"))))));
439 TEST(HasTypeLoc, MatchesDeclaratorDecl) {
440 EXPECT_TRUE(matches("int x;",
441 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
442 EXPECT_TRUE(matches("int x(3);",
443 varDecl(hasName("x"), hasTypeLoc(loc(asString("int"))))));
444 EXPECT_TRUE(matches("struct Foo { Foo(int, int); }; Foo x(1, 2);",
445 varDecl(hasName("x"), hasTypeLoc(loc(asString("Foo"))))));
447 // Make sure we don't crash on implicit constructors.
448 EXPECT_TRUE(notMatches("class X {}; X x;",
449 declaratorDecl(hasTypeLoc(loc(asString("int"))))));
452 TEST(HasTypeLoc, MatchesExplicitCastExpr) {
453 EXPECT_TRUE(matches("auto x = (int) 3;",
454 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
455 EXPECT_TRUE(matches("auto x = static_cast<int>(3);",
456 explicitCastExpr(hasTypeLoc(loc(asString("int"))))));
459 TEST(HasTypeLoc, MatchesObjCPropertyDecl) {
460 EXPECT_TRUE(matchesObjC(R"objc(
461 @interface Foo
462 @property int enabled;
463 @end
464 )objc",
465 objcPropertyDecl(hasTypeLoc(loc(asString("int"))))));
468 TEST(HasTypeLoc, MatchesTemplateArgumentLoc) {
469 EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;",
470 templateArgumentLoc(hasTypeLoc(loc(asString("int"))))));
473 TEST(HasTypeLoc, MatchesTypedefNameDecl) {
474 EXPECT_TRUE(matches("typedef int X;",
475 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
476 EXPECT_TRUE(matches("using X = int;",
477 typedefNameDecl(hasTypeLoc(loc(asString("int"))))));
480 TEST(Callee, MatchesDeclarations) {
481 StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x"))));
483 EXPECT_TRUE(matches("class Y { void x() { x(); } };", CallMethodX));
484 EXPECT_TRUE(notMatches("class Y { void x() {} };", CallMethodX));
486 CallMethodX = traverse(TK_AsIs, callExpr(callee(cxxConversionDecl())));
487 EXPECT_TRUE(
488 matches("struct Y { operator int() const; }; int i = Y();", CallMethodX));
489 EXPECT_TRUE(notMatches("struct Y { operator int() const; }; Y y = Y();",
490 CallMethodX));
493 TEST(Callee, MatchesMemberExpressions) {
494 EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
495 callExpr(callee(memberExpr()))));
496 EXPECT_TRUE(
497 notMatches("class Y { void x() { this->x(); } };", callExpr(callee(callExpr()))));
500 TEST(Matcher, Argument) {
501 StatementMatcher CallArgumentY = callExpr(
502 hasArgument(0, declRefExpr(to(varDecl(hasName("y"))))));
504 EXPECT_TRUE(matches("void x(int) { int y; x(y); }", CallArgumentY));
505 EXPECT_TRUE(
506 matches("class X { void x(int) { int y; x(y); } };", CallArgumentY));
507 EXPECT_TRUE(notMatches("void x(int) { int z; x(z); }", CallArgumentY));
509 StatementMatcher WrongIndex = callExpr(
510 hasArgument(42, declRefExpr(to(varDecl(hasName("y"))))));
511 EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex));
514 TEST(Matcher, AnyArgument) {
515 auto HasArgumentY = hasAnyArgument(
516 ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
517 StatementMatcher CallArgumentY = callExpr(HasArgumentY);
518 StatementMatcher CtorArgumentY = cxxConstructExpr(HasArgumentY);
519 StatementMatcher UnresolvedCtorArgumentY =
520 cxxUnresolvedConstructExpr(HasArgumentY);
521 StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY);
522 EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY));
523 EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY));
524 EXPECT_TRUE(matches("struct Y { Y(int, int); };"
525 "void x() { int y; (void)Y(1, y); }",
526 CtorArgumentY));
527 EXPECT_TRUE(matches("struct Y { Y(int, int); };"
528 "void x() { int y; (void)Y(y, 42); }",
529 CtorArgumentY));
530 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }",
531 UnresolvedCtorArgumentY));
532 EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }",
533 UnresolvedCtorArgumentY));
534 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end "
535 "void x(I* i) { int y; [i f:y]; }",
536 ObjCCallArgumentY));
537 EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "
538 "void x(I* i) { int z; [i f:z]; }",
539 ObjCCallArgumentY));
540 EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
541 EXPECT_TRUE(notMatches("struct Y { Y(int, int); };"
542 "void x() { int y; (void)Y(1, 2); }",
543 CtorArgumentY));
544 EXPECT_TRUE(notMatches("template <class Y>"
545 "void x() { int y; (void)Y(1, 2); }",
546 UnresolvedCtorArgumentY));
548 StatementMatcher ImplicitCastedArgument =
549 traverse(TK_AsIs, callExpr(hasAnyArgument(implicitCastExpr())));
550 EXPECT_TRUE(matches("void x(long) { int y; x(y); }", ImplicitCastedArgument));
553 TEST(Matcher, HasReceiver) {
554 EXPECT_TRUE(matchesObjC(
555 "@interface NSString @end "
556 "void f(NSString *x) {"
557 "[x containsString];"
558 "}",
559 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
561 EXPECT_FALSE(matchesObjC(
562 "@interface NSString +(NSString *) stringWithFormat; @end "
563 "void f() { [NSString stringWithFormat]; }",
564 objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x"))))))));
567 TEST(Matcher, MatchesMethodsOnLambda) {
568 StringRef Code = R"cpp(
569 struct A {
570 ~A() {}
572 void foo()
574 A a;
575 auto l = [a] { };
576 auto lCopy = l;
577 auto lPtrDecay = +[] { };
578 (void)lPtrDecay;
580 )cpp";
582 EXPECT_TRUE(matches(
583 Code, cxxConstructorDecl(
584 hasBody(compoundStmt()),
585 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),
586 isCopyConstructor())));
587 EXPECT_TRUE(matches(
588 Code, cxxConstructorDecl(
589 hasBody(compoundStmt()),
590 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))),
591 isMoveConstructor())));
592 EXPECT_TRUE(matches(
593 Code, cxxDestructorDecl(
594 hasBody(compoundStmt()),
595 hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))))));
596 EXPECT_TRUE(matches(
597 Code, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt(
598 hasReturnValue(implicitCastExpr()))))),
599 hasAncestor(lambdaExpr(hasAncestor(
600 varDecl(hasName("lPtrDecay"))))))));
603 TEST(Matcher, MatchesCoroutine) {
604 FileContentMappings M;
605 M.push_back(std::make_pair("/coro_header", R"cpp(
606 namespace std {
608 template <class... Args>
609 struct void_t_imp {
610 using type = void;
612 template <class... Args>
613 using void_t = typename void_t_imp<Args...>::type;
615 template <class T, class = void>
616 struct traits_sfinae_base {};
618 template <class T>
619 struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
620 using promise_type = typename T::promise_type;
623 template <class Ret, class... Args>
624 struct coroutine_traits : public traits_sfinae_base<Ret> {};
625 } // namespace std
626 struct awaitable {
627 bool await_ready() noexcept;
628 template <typename F>
629 void await_suspend(F) noexcept;
630 void await_resume() noexcept;
631 } a;
632 struct promise {
633 void get_return_object();
634 awaitable initial_suspend();
635 awaitable final_suspend() noexcept;
636 awaitable yield_value(int); // expected-note 2{{candidate}}
637 void return_value(int); // expected-note 2{{here}}
638 void unhandled_exception();
640 template <typename... T>
641 struct std::coroutine_traits<void, T...> { using promise_type = promise; };
642 namespace std {
643 template <class PromiseType = void>
644 struct coroutine_handle {
645 static coroutine_handle from_address(void *) noexcept;
647 } // namespace std
648 )cpp"));
649 StringRef CoReturnCode = R"cpp(
650 #include <coro_header>
651 void check_match_co_return() {
652 co_return 1;
654 )cpp";
655 EXPECT_TRUE(matchesConditionally(CoReturnCode,
656 coreturnStmt(isExpansionInMainFile()), true,
657 {"-std=c++20", "-I/"}, M));
658 StringRef CoAwaitCode = R"cpp(
659 #include <coro_header>
660 void check_match_co_await() {
661 co_await a;
663 )cpp";
664 EXPECT_TRUE(matchesConditionally(CoAwaitCode,
665 coawaitExpr(isExpansionInMainFile()), true,
666 {"-std=c++20", "-I/"}, M));
667 StringRef CoYieldCode = R"cpp(
668 #include <coro_header>
669 void check_match_co_yield() {
670 co_yield 1.0;
672 )cpp";
673 EXPECT_TRUE(matchesConditionally(CoYieldCode,
674 coyieldExpr(isExpansionInMainFile()), true,
675 {"-std=c++20", "-I/"}, M));
677 StringRef NonCoroCode = R"cpp(
678 #include <coro_header>
679 void non_coro_function() {
681 )cpp";
683 EXPECT_TRUE(matchesConditionally(CoReturnCode, coroutineBodyStmt(), true,
684 {"-std=c++20", "-I/"}, M));
685 EXPECT_TRUE(matchesConditionally(CoAwaitCode, coroutineBodyStmt(), true,
686 {"-std=c++20", "-I/"}, M));
687 EXPECT_TRUE(matchesConditionally(CoYieldCode, coroutineBodyStmt(), true,
688 {"-std=c++20", "-I/"}, M));
690 EXPECT_FALSE(matchesConditionally(NonCoroCode, coroutineBodyStmt(), true,
691 {"-std=c++20", "-I/"}, M));
693 StringRef CoroWithDeclCode = R"cpp(
694 #include <coro_header>
695 void coro() {
696 int thevar;
697 co_return 1;
699 )cpp";
700 EXPECT_TRUE(matchesConditionally(
701 CoroWithDeclCode,
702 coroutineBodyStmt(hasBody(compoundStmt(
703 has(declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))),
704 true, {"-std=c++20", "-I/"}, M));
706 StringRef CoroWithTryCatchDeclCode = R"cpp(
707 #include <coro_header>
708 void coro() try {
709 int thevar;
710 co_return 1;
711 } catch (...) {}
712 )cpp";
713 EXPECT_TRUE(matchesConditionally(
714 CoroWithTryCatchDeclCode,
715 coroutineBodyStmt(hasBody(compoundStmt(has(cxxTryStmt(has(compoundStmt(has(
716 declStmt(containsDeclaration(0, varDecl(hasName("thevar")))))))))))),
717 true, {"-std=c++20", "-I/"}, M));
720 TEST(Matcher, isClassMessage) {
721 EXPECT_TRUE(matchesObjC(
722 "@interface NSString +(NSString *) stringWithFormat; @end "
723 "void f() { [NSString stringWithFormat]; }",
724 objcMessageExpr(isClassMessage())));
726 EXPECT_FALSE(matchesObjC(
727 "@interface NSString @end "
728 "void f(NSString *x) {"
729 "[x containsString];"
730 "}",
731 objcMessageExpr(isClassMessage())));
734 TEST(Matcher, isInstanceMessage) {
735 EXPECT_TRUE(matchesObjC(
736 "@interface NSString @end "
737 "void f(NSString *x) {"
738 "[x containsString];"
739 "}",
740 objcMessageExpr(isInstanceMessage())));
742 EXPECT_FALSE(matchesObjC(
743 "@interface NSString +(NSString *) stringWithFormat; @end "
744 "void f() { [NSString stringWithFormat]; }",
745 objcMessageExpr(isInstanceMessage())));
749 TEST(Matcher, isClassMethod) {
750 EXPECT_TRUE(matchesObjC(
751 "@interface Bar + (void)bar; @end",
752 objcMethodDecl(isClassMethod())));
754 EXPECT_TRUE(matchesObjC(
755 "@interface Bar @end"
756 "@implementation Bar + (void)bar {} @end",
757 objcMethodDecl(isClassMethod())));
759 EXPECT_FALSE(matchesObjC(
760 "@interface Foo - (void)foo; @end",
761 objcMethodDecl(isClassMethod())));
763 EXPECT_FALSE(matchesObjC(
764 "@interface Foo @end "
765 "@implementation Foo - (void)foo {} @end",
766 objcMethodDecl(isClassMethod())));
769 TEST(Matcher, isInstanceMethod) {
770 EXPECT_TRUE(matchesObjC(
771 "@interface Foo - (void)foo; @end",
772 objcMethodDecl(isInstanceMethod())));
774 EXPECT_TRUE(matchesObjC(
775 "@interface Foo @end "
776 "@implementation Foo - (void)foo {} @end",
777 objcMethodDecl(isInstanceMethod())));
779 EXPECT_FALSE(matchesObjC(
780 "@interface Bar + (void)bar; @end",
781 objcMethodDecl(isInstanceMethod())));
783 EXPECT_FALSE(matchesObjC(
784 "@interface Bar @end"
785 "@implementation Bar + (void)bar {} @end",
786 objcMethodDecl(isInstanceMethod())));
789 TEST(MatcherCXXMemberCallExpr, On) {
790 StringRef Snippet1 = R"cc(
791 struct Y {
792 void m();
794 void z(Y y) { y.m(); }
795 )cc";
796 StringRef Snippet2 = R"cc(
797 struct Y {
798 void m();
800 struct X : public Y {};
801 void z(X x) { x.m(); }
802 )cc";
803 auto MatchesY = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))));
804 EXPECT_TRUE(matches(Snippet1, MatchesY));
805 EXPECT_TRUE(notMatches(Snippet2, MatchesY));
807 auto MatchesX = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("X")))));
808 EXPECT_TRUE(matches(Snippet2, MatchesX));
810 // Parens are ignored.
811 StringRef Snippet3 = R"cc(
812 struct Y {
813 void m();
815 Y g();
816 void z(Y y) { (g()).m(); }
817 )cc";
818 auto MatchesCall = cxxMemberCallExpr(on(callExpr()));
819 EXPECT_TRUE(matches(Snippet3, MatchesCall));
822 TEST(MatcherCXXMemberCallExpr, OnImplicitObjectArgument) {
823 StringRef Snippet1 = R"cc(
824 struct Y {
825 void m();
827 void z(Y y) { y.m(); }
828 )cc";
829 StringRef Snippet2 = R"cc(
830 struct Y {
831 void m();
833 struct X : public Y {};
834 void z(X x) { x.m(); }
835 )cc";
836 auto MatchesY = traverse(TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(
837 hasType(cxxRecordDecl(hasName("Y"))))));
838 EXPECT_TRUE(matches(Snippet1, MatchesY));
839 EXPECT_TRUE(matches(Snippet2, MatchesY));
841 auto MatchesX = traverse(TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(
842 hasType(cxxRecordDecl(hasName("X"))))));
843 EXPECT_TRUE(notMatches(Snippet2, MatchesX));
845 // Parens are not ignored.
846 StringRef Snippet3 = R"cc(
847 struct Y {
848 void m();
850 Y g();
851 void z(Y y) { (g()).m(); }
852 )cc";
853 auto MatchesCall = traverse(
854 TK_AsIs, cxxMemberCallExpr(onImplicitObjectArgument(callExpr())));
855 EXPECT_TRUE(notMatches(Snippet3, MatchesCall));
858 TEST(Matcher, HasObjectExpr) {
859 StringRef Snippet1 = R"cc(
860 struct X {
861 int m;
862 int f(X x) { return x.m; }
864 )cc";
865 StringRef Snippet2 = R"cc(
866 struct X {
867 int m;
868 int f(X x) { return m; }
870 )cc";
871 auto MatchesX =
872 memberExpr(hasObjectExpression(hasType(cxxRecordDecl(hasName("X")))));
873 EXPECT_TRUE(matches(Snippet1, MatchesX));
874 EXPECT_TRUE(notMatches(Snippet2, MatchesX));
876 auto MatchesXPointer = memberExpr(
877 hasObjectExpression(hasType(pointsTo(cxxRecordDecl(hasName("X"))))));
878 EXPECT_TRUE(notMatches(Snippet1, MatchesXPointer));
879 EXPECT_TRUE(matches(Snippet2, MatchesXPointer));
882 TEST(ForEachArgumentWithParam, ReportsNoFalsePositives) {
883 StatementMatcher ArgumentY =
884 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
885 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");
886 StatementMatcher CallExpr =
887 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));
889 // IntParam does not match.
890 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));
891 // ArgumentY does not match.
892 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));
895 TEST(ForEachArgumentWithParam, MatchesCXXMemberCallExpr) {
896 StatementMatcher ArgumentY =
897 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
898 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");
899 StatementMatcher CallExpr =
900 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));
901 EXPECT_TRUE(matchAndVerifyResultTrue(
902 "struct S {"
903 " const S& operator[](int i) { return *this; }"
904 "};"
905 "void f(S S1) {"
906 " int y = 1;"
907 " S1[y];"
908 "}",
909 CallExpr, std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 1)));
911 StatementMatcher CallExpr2 =
912 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));
913 EXPECT_TRUE(matchAndVerifyResultTrue(
914 "struct S {"
915 " static void g(int i);"
916 "};"
917 "void f() {"
918 " int y = 1;"
919 " S::g(y);"
920 "}",
921 CallExpr2, std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 1)));
924 TEST(ForEachArgumentWithParam, MatchesCallExpr) {
925 StatementMatcher ArgumentY =
926 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
927 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");
928 StatementMatcher CallExpr =
929 callExpr(forEachArgumentWithParam(ArgumentY, IntParam));
931 EXPECT_TRUE(
932 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,
933 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>(
934 "param")));
935 EXPECT_TRUE(
936 matchAndVerifyResultTrue("void f(int i) { int y; f(y); }", CallExpr,
937 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>(
938 "arg")));
940 EXPECT_TRUE(matchAndVerifyResultTrue(
941 "void f(int i, int j) { int y; f(y, y); }", CallExpr,
942 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", 2)));
943 EXPECT_TRUE(matchAndVerifyResultTrue(
944 "void f(int i, int j) { int y; f(y, y); }", CallExpr,
945 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));
948 TEST(ForEachArgumentWithParam, MatchesConstructExpr) {
949 StatementMatcher ArgumentY =
950 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
951 DeclarationMatcher IntParam = parmVarDecl(hasType(isInteger())).bind("param");
952 StatementMatcher ConstructExpr = traverse(
953 TK_AsIs, cxxConstructExpr(forEachArgumentWithParam(ArgumentY, IntParam)));
955 EXPECT_TRUE(matchAndVerifyResultTrue(
956 "struct C {"
957 " C(int i) {}"
958 "};"
959 "int y = 0;"
960 "C Obj(y);",
961 ConstructExpr,
962 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param")));
965 TEST(ForEachArgumentWithParam, HandlesBoundNodesForNonMatches) {
966 EXPECT_TRUE(matchAndVerifyResultTrue(
967 "void g(int i, int j) {"
968 " int a;"
969 " int b;"
970 " int c;"
971 " g(a, 0);"
972 " g(a, b);"
973 " g(0, b);"
974 "}",
975 functionDecl(
976 forEachDescendant(varDecl().bind("v")),
977 forEachDescendant(callExpr(forEachArgumentWithParam(
978 declRefExpr(to(decl(equalsBoundNode("v")))), parmVarDecl())))),
979 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));
982 TEST_P(ASTMatchersTest,
983 ForEachArgumentWithParamMatchesExplicitObjectParamOnOperatorCalls) {
984 if (!GetParam().isCXX23OrLater()) {
985 return;
988 auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");
989 auto SelfParam = parmVarDecl().bind("param");
990 StatementMatcher CallExpr =
991 callExpr(forEachArgumentWithParam(DeclRef, SelfParam));
993 StringRef S = R"cpp(
994 struct A {
995 int operator()(this const A &self);
997 A obj;
998 int global = obj();
999 )cpp";
1001 auto Args = GetParam().getCommandLineArgs();
1002 auto Filename = getFilenameForTesting(GetParam().Language);
1004 EXPECT_TRUE(matchAndVerifyResultTrue(
1005 S, CallExpr,
1006 std::make_unique<VerifyIdIsBoundTo<ParmVarDecl>>("param", "self"), Args,
1007 Filename));
1008 EXPECT_TRUE(matchAndVerifyResultTrue(
1009 S, CallExpr,
1010 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args,
1011 Filename));
1014 TEST(ForEachArgumentWithParamType, ReportsNoFalsePositives) {
1015 StatementMatcher ArgumentY =
1016 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1017 TypeMatcher IntType = qualType(isInteger()).bind("type");
1018 StatementMatcher CallExpr =
1019 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1021 // IntParam does not match.
1022 EXPECT_TRUE(notMatches("void f(int* i) { int* y; f(y); }", CallExpr));
1023 // ArgumentY does not match.
1024 EXPECT_TRUE(notMatches("void f(int i) { int x; f(x); }", CallExpr));
1027 TEST(ForEachArgumentWithParamType, MatchesCXXMemberCallExpr) {
1028 StatementMatcher ArgumentY =
1029 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1030 TypeMatcher IntType = qualType(isInteger()).bind("type");
1031 StatementMatcher CallExpr =
1032 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1033 EXPECT_TRUE(matchAndVerifyResultTrue(
1034 "struct S {"
1035 " const S& operator[](int i) { return *this; }"
1036 "};"
1037 "void f(S S1) {"
1038 " int y = 1;"
1039 " S1[y];"
1040 "}",
1041 CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));
1043 StatementMatcher CallExpr2 =
1044 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1045 EXPECT_TRUE(matchAndVerifyResultTrue(
1046 "struct S {"
1047 " static void g(int i);"
1048 "};"
1049 "void f() {"
1050 " int y = 1;"
1051 " S::g(y);"
1052 "}",
1053 CallExpr2, std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 1)));
1056 TEST(ForEachArgumentWithParamType, MatchesCallExpr) {
1057 StatementMatcher ArgumentY =
1058 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1059 TypeMatcher IntType = qualType(isInteger()).bind("type");
1060 StatementMatcher CallExpr =
1061 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1063 EXPECT_TRUE(matchAndVerifyResultTrue(
1064 "void f(int i) { int y; f(y); }", CallExpr,
1065 std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
1066 EXPECT_TRUE(matchAndVerifyResultTrue(
1067 "void f(int i) { int y; f(y); }", CallExpr,
1068 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
1070 EXPECT_TRUE(matchAndVerifyResultTrue(
1071 "void f(int i, int j) { int y; f(y, y); }", CallExpr,
1072 std::make_unique<VerifyIdIsBoundTo<QualType>>("type", 2)));
1073 EXPECT_TRUE(matchAndVerifyResultTrue(
1074 "void f(int i, int j) { int y; f(y, y); }", CallExpr,
1075 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg", 2)));
1078 TEST(ForEachArgumentWithParamType, MatchesConstructExpr) {
1079 StatementMatcher ArgumentY =
1080 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1081 TypeMatcher IntType = qualType(isInteger()).bind("type");
1082 StatementMatcher ConstructExpr =
1083 cxxConstructExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1085 EXPECT_TRUE(matchAndVerifyResultTrue(
1086 "struct C {"
1087 " C(int i) {}"
1088 "};"
1089 "int y = 0;"
1090 "C Obj(y);",
1091 ConstructExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
1092 EXPECT_TRUE(matchAndVerifyResultTrue(
1093 "struct C {"
1094 " C(int i) {}"
1095 "};"
1096 "int y = 0;"
1097 "C Obj(y);",
1098 ConstructExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
1101 TEST(ForEachArgumentWithParamType, HandlesKandRFunctions) {
1102 StatementMatcher ArgumentY =
1103 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1104 TypeMatcher IntType = qualType(isInteger()).bind("type");
1105 StatementMatcher CallExpr =
1106 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1108 EXPECT_TRUE(matchesC("void f();\n"
1109 "void call_it(void) { int x, y; f(x, y); }\n"
1110 "void f(a, b) int a, b; {}\n"
1111 "void call_it2(void) { int x, y; f(x, y); }",
1112 CallExpr));
1115 TEST(ForEachArgumentWithParamType, HandlesBoundNodesForNonMatches) {
1116 EXPECT_TRUE(matchAndVerifyResultTrue(
1117 "void g(int i, int j) {"
1118 " int a;"
1119 " int b;"
1120 " int c;"
1121 " g(a, 0);"
1122 " g(a, b);"
1123 " g(0, b);"
1124 "}",
1125 functionDecl(
1126 forEachDescendant(varDecl().bind("v")),
1127 forEachDescendant(callExpr(forEachArgumentWithParamType(
1128 declRefExpr(to(decl(equalsBoundNode("v")))), qualType())))),
1129 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("v", 4)));
1132 TEST(ForEachArgumentWithParamType, MatchesFunctionPtrCalls) {
1133 StatementMatcher ArgumentY =
1134 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1135 TypeMatcher IntType = qualType(builtinType()).bind("type");
1136 StatementMatcher CallExpr =
1137 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1139 EXPECT_TRUE(matchAndVerifyResultTrue(
1140 "void f(int i) {"
1141 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1142 CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
1143 EXPECT_TRUE(matchAndVerifyResultTrue(
1144 "void f(int i) {"
1145 "void (*f_ptr)(int) = f; int y; f_ptr(y); }",
1146 CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
1149 TEST(ForEachArgumentWithParamType, MatchesMemberFunctionPtrCalls) {
1150 StatementMatcher ArgumentY =
1151 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1152 TypeMatcher IntType = qualType(builtinType()).bind("type");
1153 StatementMatcher CallExpr =
1154 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1156 StringRef S = "struct A {\n"
1157 " int f(int i) { return i + 1; }\n"
1158 " int (A::*x)(int);\n"
1159 "};\n"
1160 "void f() {\n"
1161 " int y = 42;\n"
1162 " A a;\n"
1163 " a.x = &A::f;\n"
1164 " (a.*(a.x))(y);\n"
1165 "}";
1166 EXPECT_TRUE(matchAndVerifyResultTrue(
1167 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
1168 EXPECT_TRUE(matchAndVerifyResultTrue(
1169 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
1172 TEST(ForEachArgumentWithParamType, MatchesVariadicFunctionPtrCalls) {
1173 StatementMatcher ArgumentY =
1174 declRefExpr(to(varDecl(hasName("y")))).bind("arg");
1175 TypeMatcher IntType = qualType(builtinType()).bind("type");
1176 StatementMatcher CallExpr =
1177 callExpr(forEachArgumentWithParamType(ArgumentY, IntType));
1179 StringRef S = R"cpp(
1180 void fcntl(int fd, int cmd, ...) {}
1182 template <typename Func>
1183 void f(Func F) {
1184 int y = 42;
1185 F(y, 1, 3);
1188 void g() { f(fcntl); }
1189 )cpp";
1191 EXPECT_TRUE(matchAndVerifyResultTrue(
1192 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("type")));
1193 EXPECT_TRUE(matchAndVerifyResultTrue(
1194 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("arg")));
1197 TEST_P(ASTMatchersTest,
1198 ForEachArgumentWithParamTypeMatchesExplicitObjectParamOnOperatorCalls) {
1199 if (!GetParam().isCXX23OrLater()) {
1200 return;
1203 auto DeclRef = declRefExpr(to(varDecl().bind("declOfArg"))).bind("arg");
1204 auto SelfTy = qualType(asString("const A &")).bind("selfType");
1205 StatementMatcher CallExpr =
1206 callExpr(forEachArgumentWithParamType(DeclRef, SelfTy));
1208 StringRef S = R"cpp(
1209 struct A {
1210 int operator()(this const A &self);
1212 A obj;
1213 int global = obj();
1214 )cpp";
1216 auto Args = GetParam().getCommandLineArgs();
1217 auto Filename = getFilenameForTesting(GetParam().Language);
1219 EXPECT_TRUE(matchAndVerifyResultTrue(
1220 S, CallExpr, std::make_unique<VerifyIdIsBoundTo<QualType>>("selfType"),
1221 Args, Filename));
1222 EXPECT_TRUE(matchAndVerifyResultTrue(
1223 S, CallExpr,
1224 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("declOfArg", "obj"), Args,
1225 Filename));
1228 TEST(QualType, hasCanonicalType) {
1229 EXPECT_TRUE(notMatches("typedef int &int_ref;"
1230 "int a;"
1231 "int_ref b = a;",
1232 varDecl(hasType(qualType(referenceType())))));
1233 EXPECT_TRUE(
1234 matches("typedef int &int_ref;"
1235 "int a;"
1236 "int_ref b = a;",
1237 varDecl(hasType(qualType(hasCanonicalType(referenceType()))))));
1240 TEST(HasParameter, CallsInnerMatcher) {
1241 EXPECT_TRUE(matches("class X { void x(int) {} };",
1242 cxxMethodDecl(hasParameter(0, varDecl()))));
1243 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1244 cxxMethodDecl(hasParameter(0, hasName("x")))));
1245 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1246 objcMethodDecl(hasParameter(0, hasName("x")))));
1247 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1248 blockDecl(hasParameter(0, hasName("p")))));
1251 TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
1252 EXPECT_TRUE(notMatches("class X { void x(int) {} };",
1253 cxxMethodDecl(hasParameter(42, varDecl()))));
1256 TEST(HasType, MatchesParameterVariableTypesStrictly) {
1257 EXPECT_TRUE(matches(
1258 "class X { void x(X x) {} };",
1259 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1260 EXPECT_TRUE(notMatches(
1261 "class X { void x(const X &x) {} };",
1262 cxxMethodDecl(hasParameter(0, hasType(recordDecl(hasName("X")))))));
1263 EXPECT_TRUE(matches("class X { void x(const X *x) {} };",
1264 cxxMethodDecl(hasParameter(
1265 0, hasType(pointsTo(recordDecl(hasName("X"))))))));
1266 EXPECT_TRUE(matches("class X { void x(const X &x) {} };",
1267 cxxMethodDecl(hasParameter(
1268 0, hasType(references(recordDecl(hasName("X"))))))));
1271 TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
1272 EXPECT_TRUE(matches(
1273 "class Y {}; class X { void x(X x, Y y) {} };",
1274 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1275 EXPECT_TRUE(matches(
1276 "class Y {}; class X { void x(Y y, X x) {} };",
1277 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1278 EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
1279 objcMethodDecl(hasAnyParameter(hasName("x")))));
1280 EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
1281 blockDecl(hasAnyParameter(hasName("p")))));
1284 TEST(Returns, MatchesReturnTypes) {
1285 EXPECT_TRUE(matches("class Y { int f() { return 1; } };",
1286 functionDecl(returns(asString("int")))));
1287 EXPECT_TRUE(notMatches("class Y { int f() { return 1; } };",
1288 functionDecl(returns(asString("float")))));
1289 EXPECT_TRUE(matches("class Y { Y getMe() { return *this; } };",
1290 functionDecl(returns(hasDeclaration(
1291 recordDecl(hasName("Y")))))));
1294 TEST(HasAnyParameter, DoesntMatchIfInnerMatcherDoesntMatch) {
1295 EXPECT_TRUE(notMatches(
1296 "class Y {}; class X { void x(int) {} };",
1297 cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
1300 TEST(HasAnyParameter, DoesNotMatchThisPointer) {
1301 EXPECT_TRUE(notMatches("class Y {}; class X { void x() {} };",
1302 cxxMethodDecl(hasAnyParameter(
1303 hasType(pointsTo(recordDecl(hasName("X"))))))));
1306 TEST(HasName, MatchesParameterVariableDeclarations) {
1307 EXPECT_TRUE(matches("class Y {}; class X { void x(int x) {} };",
1308 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1309 EXPECT_TRUE(notMatches("class Y {}; class X { void x(int) {} };",
1310 cxxMethodDecl(hasAnyParameter(hasName("x")))));
1313 TEST(Matcher, MatchesTypeTemplateArgument) {
1314 EXPECT_TRUE(matches(
1315 "template<typename T> struct B {};"
1316 "B<int> b;",
1317 classTemplateSpecializationDecl(hasAnyTemplateArgument(refersToType(
1318 asString("int"))))));
1321 TEST(Matcher, MatchesTemplateTemplateArgument) {
1322 EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
1323 "template<typename T> class Y {};"
1324 "X<Y> xi;",
1325 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1326 refersToTemplate(templateName())))));
1329 TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {
1330 EXPECT_TRUE(matches(
1331 "struct B { int next; };"
1332 "template<int(B::*next_ptr)> struct A {};"
1333 "A<&B::next> a;",
1334 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1335 refersToDeclaration(fieldDecl(hasName("next")))))));
1337 EXPECT_TRUE(notMatches(
1338 "template <typename T> struct A {};"
1339 "A<int> a;",
1340 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1341 refersToDeclaration(decl())))));
1343 EXPECT_TRUE(matches(
1344 "struct B { int next; };"
1345 "template<int(B::*next_ptr)> struct A {};"
1346 "A<&B::next> a;",
1347 templateSpecializationType(hasAnyTemplateArgument(isExpr(
1348 hasDescendant(declRefExpr(to(fieldDecl(hasName("next"))))))))));
1350 EXPECT_TRUE(notMatches(
1351 "template <typename T> struct A {};"
1352 "A<int> a;",
1353 templateSpecializationType(hasAnyTemplateArgument(
1354 refersToDeclaration(decl())))));
1358 TEST(Matcher, MatchesSpecificArgument) {
1359 EXPECT_TRUE(matches(
1360 "template<typename T, typename U> class A {};"
1361 "A<bool, int> a;",
1362 classTemplateSpecializationDecl(hasTemplateArgument(
1363 1, refersToType(asString("int"))))));
1364 EXPECT_TRUE(notMatches(
1365 "template<typename T, typename U> class A {};"
1366 "A<int, bool> a;",
1367 classTemplateSpecializationDecl(hasTemplateArgument(
1368 1, refersToType(asString("int"))))));
1370 EXPECT_TRUE(matches(
1371 "template<typename T, typename U> class A {};"
1372 "A<bool, int> a;",
1373 templateSpecializationType(hasTemplateArgument(
1374 1, refersToType(asString("int"))))));
1375 EXPECT_TRUE(notMatches(
1376 "template<typename T, typename U> class A {};"
1377 "A<int, bool> a;",
1378 templateSpecializationType(hasTemplateArgument(
1379 1, refersToType(asString("int"))))));
1381 EXPECT_TRUE(matches(
1382 "template<typename T> void f() {};"
1383 "void func() { f<int>(); }",
1384 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1385 EXPECT_TRUE(notMatches(
1386 "template<typename T> void f() {};",
1387 functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
1390 TEST(TemplateArgument, Matches) {
1391 EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
1392 classTemplateSpecializationDecl(
1393 hasAnyTemplateArgument(templateArgument()))));
1394 EXPECT_TRUE(matches(
1395 "template<typename T> struct C {}; C<int> c;",
1396 templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
1398 EXPECT_TRUE(matches(
1399 "template<typename T> void f() {};"
1400 "void func() { f<int>(); }",
1401 functionDecl(hasAnyTemplateArgument(templateArgument()))));
1404 TEST(TemplateTypeParmDecl, CXXMethodDecl) {
1405 const char input[] =
1406 "template<typename T>\n"
1407 "class Class {\n"
1408 " void method();\n"
1409 "};\n"
1410 "template<typename U>\n"
1411 "void Class<U>::method() {}\n";
1412 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
1413 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
1416 TEST(TemplateTypeParmDecl, VarDecl) {
1417 const char input[] =
1418 "template<typename T>\n"
1419 "class Class {\n"
1420 " static T pi;\n"
1421 "};\n"
1422 "template<typename U>\n"
1423 "U Class<U>::pi = U(3.1415926535897932385);\n";
1424 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
1425 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
1428 TEST(TemplateTypeParmDecl, VarTemplatePartialSpecializationDecl) {
1429 const char input[] =
1430 "template<typename T>\n"
1431 "struct Struct {\n"
1432 " template<typename T2> static int field;\n"
1433 "};\n"
1434 "template<typename U>\n"
1435 "template<typename U2>\n"
1436 "int Struct<U>::field<U2*> = 123;\n";
1437 EXPECT_TRUE(
1438 matches(input, templateTypeParmDecl(hasName("T")), langCxx14OrLater()));
1439 EXPECT_TRUE(
1440 matches(input, templateTypeParmDecl(hasName("T2")), langCxx14OrLater()));
1441 EXPECT_TRUE(
1442 matches(input, templateTypeParmDecl(hasName("U")), langCxx14OrLater()));
1443 EXPECT_TRUE(
1444 matches(input, templateTypeParmDecl(hasName("U2")), langCxx14OrLater()));
1447 TEST(TemplateTypeParmDecl, ClassTemplatePartialSpecializationDecl) {
1448 const char input[] =
1449 "template<typename T>\n"
1450 "class Class {\n"
1451 " template<typename T2> struct Struct;\n"
1452 "};\n"
1453 "template<typename U>\n"
1454 "template<typename U2>\n"
1455 "struct Class<U>::Struct<U2*> {};\n";
1456 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
1457 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
1458 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
1459 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
1462 TEST(TemplateTypeParmDecl, EnumDecl) {
1463 const char input[] =
1464 "template<typename T>\n"
1465 "struct Struct {\n"
1466 " enum class Enum : T;\n"
1467 "};\n"
1468 "template<typename U>\n"
1469 "enum class Struct<U>::Enum : U {\n"
1470 " e1,\n"
1471 " e2\n"
1472 "};\n";
1473 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
1474 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
1477 TEST(TemplateTypeParmDecl, RecordDecl) {
1478 const char input[] =
1479 "template<typename T>\n"
1480 "class Class {\n"
1481 " struct Struct;\n"
1482 "};\n"
1483 "template<typename U>\n"
1484 "struct Class<U>::Struct {\n"
1485 " U field;\n"
1486 "};\n";
1487 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
1488 EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
1491 TEST(RefersToIntegralType, Matches) {
1492 EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
1493 classTemplateSpecializationDecl(
1494 hasAnyTemplateArgument(refersToIntegralType(
1495 asString("int"))))));
1496 EXPECT_TRUE(notMatches("template<unsigned T> struct C {}; C<42> c;",
1497 classTemplateSpecializationDecl(hasAnyTemplateArgument(
1498 refersToIntegralType(asString("int"))))));
1501 TEST(ConstructorDeclaration, SimpleCase) {
1502 EXPECT_TRUE(matches("class Foo { Foo(int i); };",
1503 cxxConstructorDecl(ofClass(hasName("Foo")))));
1504 EXPECT_TRUE(notMatches("class Foo { Foo(int i); };",
1505 cxxConstructorDecl(ofClass(hasName("Bar")))));
1508 TEST(DestructorDeclaration, MatchesVirtualDestructor) {
1509 EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };",
1510 cxxDestructorDecl(ofClass(hasName("Foo")))));
1513 TEST(DestructorDeclaration, DoesNotMatchImplicitDestructor) {
1514 EXPECT_TRUE(notMatches("class Foo {};",
1515 cxxDestructorDecl(ofClass(hasName("Foo")))));
1518 TEST(HasAnyConstructorInitializer, SimpleCase) {
1519 EXPECT_TRUE(
1520 notMatches("class Foo { Foo() { } };",
1521 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1522 EXPECT_TRUE(
1523 matches("class Foo {"
1524 " Foo() : foo_() { }"
1525 " int foo_;"
1526 "};",
1527 cxxConstructorDecl(hasAnyConstructorInitializer(anything()))));
1530 TEST(HasAnyConstructorInitializer, ForField) {
1531 static const char Code[] =
1532 "class Baz { };"
1533 "class Foo {"
1534 " Foo() : foo_(), bar_() { }"
1535 " Baz foo_;"
1536 " struct {"
1537 " Baz bar_;"
1538 " };"
1539 "};";
1540 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1541 forField(hasType(recordDecl(hasName("Baz"))))))));
1542 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1543 forField(hasName("foo_"))))));
1544 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1545 forField(hasName("bar_"))))));
1546 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1547 forField(hasType(recordDecl(hasName("Bar"))))))));
1550 TEST(HasAnyConstructorInitializer, WithInitializer) {
1551 static const char Code[] =
1552 "class Foo {"
1553 " Foo() : foo_(0) { }"
1554 " int foo_;"
1555 "};";
1556 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1557 withInitializer(integerLiteral(equals(0)))))));
1558 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1559 withInitializer(integerLiteral(equals(1)))))));
1562 TEST(HasAnyConstructorInitializer, IsWritten) {
1563 static const char Code[] =
1564 "struct Bar { Bar(){} };"
1565 "class Foo {"
1566 " Foo() : foo_() { }"
1567 " Bar foo_;"
1568 " Bar bar_;"
1569 "};";
1570 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1571 allOf(forField(hasName("foo_")), isWritten())))));
1572 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1573 allOf(forField(hasName("bar_")), isWritten())))));
1574 EXPECT_TRUE(matches(Code, cxxConstructorDecl(hasAnyConstructorInitializer(
1575 allOf(forField(hasName("bar_")), unless(isWritten()))))));
1578 TEST(HasAnyConstructorInitializer, IsBaseInitializer) {
1579 static const char Code[] =
1580 "struct B {};"
1581 "struct D : B {"
1582 " int I;"
1583 " D(int i) : I(i) {}"
1584 "};"
1585 "struct E : B {"
1586 " E() : B() {}"
1587 "};";
1588 EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(
1589 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1590 hasName("E")))));
1591 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(
1592 hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())),
1593 hasName("D")))));
1594 EXPECT_TRUE(matches(Code, cxxConstructorDecl(allOf(
1595 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1596 hasName("D")))));
1597 EXPECT_TRUE(notMatches(Code, cxxConstructorDecl(allOf(
1598 hasAnyConstructorInitializer(allOf(isMemberInitializer(), isWritten())),
1599 hasName("E")))));
1602 TEST(IfStmt, ChildTraversalMatchers) {
1603 EXPECT_TRUE(matches("void f() { if (false) true; else false; }",
1604 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1605 EXPECT_TRUE(notMatches("void f() { if (false) false; else true; }",
1606 ifStmt(hasThen(cxxBoolLiteral(equals(true))))));
1607 EXPECT_TRUE(matches("void f() { if (false) false; else true; }",
1608 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1609 EXPECT_TRUE(notMatches("void f() { if (false) true; else false; }",
1610 ifStmt(hasElse(cxxBoolLiteral(equals(true))))));
1613 TEST(MatchBinaryOperator, HasOperatorName) {
1614 StatementMatcher OperatorOr = binaryOperator(hasOperatorName("||"));
1616 EXPECT_TRUE(matches("void x() { true || false; }", OperatorOr));
1617 EXPECT_TRUE(notMatches("void x() { true && false; }", OperatorOr));
1620 TEST(MatchBinaryOperator, HasAnyOperatorName) {
1621 StatementMatcher Matcher =
1622 binaryOperator(hasAnyOperatorName("+", "-", "*", "/"));
1624 EXPECT_TRUE(matches("int x(int I) { return I + 2; }", Matcher));
1625 EXPECT_TRUE(matches("int x(int I) { return I - 2; }", Matcher));
1626 EXPECT_TRUE(matches("int x(int I) { return I * 2; }", Matcher));
1627 EXPECT_TRUE(matches("int x(int I) { return I / 2; }", Matcher));
1628 EXPECT_TRUE(notMatches("int x(int I) { return I % 2; }", Matcher));
1629 // Ensure '+= isn't mistaken.
1630 EXPECT_TRUE(notMatches("void x(int &I) { I += 1; }", Matcher));
1633 TEST(MatchBinaryOperator, HasLHSAndHasRHS) {
1634 StatementMatcher OperatorTrueFalse =
1635 binaryOperator(hasLHS(cxxBoolLiteral(equals(true))),
1636 hasRHS(cxxBoolLiteral(equals(false))));
1638 EXPECT_TRUE(matches("void x() { true || false; }", OperatorTrueFalse));
1639 EXPECT_TRUE(matches("void x() { true && false; }", OperatorTrueFalse));
1640 EXPECT_TRUE(notMatches("void x() { false || true; }", OperatorTrueFalse));
1642 StatementMatcher OperatorIntPointer = arraySubscriptExpr(
1643 hasLHS(hasType(isInteger())),
1644 traverse(TK_AsIs, hasRHS(hasType(pointsTo(qualType())))));
1645 EXPECT_TRUE(matches("void x() { 1[\"abc\"]; }", OperatorIntPointer));
1646 EXPECT_TRUE(notMatches("void x() { \"abc\"[1]; }", OperatorIntPointer));
1648 StringRef Code = R"cpp(
1649 struct HasOpEqMem
1651 bool operator==(const HasOpEqMem& other) const
1653 return true;
1657 struct HasOpFree
1660 bool operator==(const HasOpFree& lhs, const HasOpFree& rhs)
1662 return true;
1665 void opMem()
1667 HasOpEqMem s1;
1668 HasOpEqMem s2;
1669 if (s1 == s2)
1670 return;
1673 void opFree()
1675 HasOpFree s1;
1676 HasOpFree s2;
1677 if (s1 == s2)
1678 return;
1680 )cpp";
1681 auto s1Expr = declRefExpr(to(varDecl(hasName("s1"))));
1682 auto s2Expr = declRefExpr(to(varDecl(hasName("s2"))));
1683 EXPECT_TRUE(matches(
1684 Code,
1685 traverse(TK_IgnoreUnlessSpelledInSource,
1686 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1687 hasOperatorName("=="), hasLHS(s1Expr),
1688 hasRHS(s2Expr)))));
1689 EXPECT_TRUE(matches(
1690 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1691 cxxOperatorCallExpr(
1692 forFunction(functionDecl(hasName("opMem"))),
1693 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr)))));
1694 EXPECT_TRUE(matches(
1695 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1696 cxxOperatorCallExpr(
1697 forFunction(functionDecl(hasName("opMem"))),
1698 hasOperatorName("=="), hasOperands(s1Expr, s2Expr)))));
1699 EXPECT_TRUE(matches(
1700 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1701 cxxOperatorCallExpr(
1702 forFunction(functionDecl(hasName("opMem"))),
1703 hasOperatorName("=="), hasEitherOperand(s2Expr)))));
1705 EXPECT_TRUE(matches(
1706 Code,
1707 traverse(TK_IgnoreUnlessSpelledInSource,
1708 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1709 hasOperatorName("=="), hasLHS(s1Expr),
1710 hasRHS(s2Expr)))));
1711 EXPECT_TRUE(matches(
1712 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1713 cxxOperatorCallExpr(
1714 forFunction(functionDecl(hasName("opFree"))),
1715 hasAnyOperatorName("!=", "=="), hasLHS(s1Expr)))));
1716 EXPECT_TRUE(matches(
1717 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1718 cxxOperatorCallExpr(
1719 forFunction(functionDecl(hasName("opFree"))),
1720 hasOperatorName("=="), hasOperands(s1Expr, s2Expr)))));
1721 EXPECT_TRUE(matches(
1722 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1723 cxxOperatorCallExpr(
1724 forFunction(functionDecl(hasName("opFree"))),
1725 hasOperatorName("=="), hasEitherOperand(s2Expr)))));
1728 TEST(MatchBinaryOperator, HasEitherOperand) {
1729 StatementMatcher HasOperand =
1730 binaryOperator(hasEitherOperand(cxxBoolLiteral(equals(false))));
1732 EXPECT_TRUE(matches("void x() { true || false; }", HasOperand));
1733 EXPECT_TRUE(matches("void x() { false && true; }", HasOperand));
1734 EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand));
1737 TEST(MatchBinaryOperator, HasOperands) {
1738 StatementMatcher HasOperands = binaryOperator(
1739 hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2))));
1740 EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands));
1741 EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands));
1742 EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands));
1743 EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands));
1744 EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands));
1745 EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands));
1748 TEST(MatchBinaryOperator, HasOperandsEnsureOrdering) {
1749 StatementMatcher HasOperandsWithBindings = binaryOperator(hasOperands(
1750 cStyleCastExpr(has(declRefExpr(hasDeclaration(valueDecl().bind("d"))))),
1751 declRefExpr(hasDeclaration(valueDecl(equalsBoundNode("d"))))));
1752 EXPECT_TRUE(matches(
1753 "int a; int b = ((int) a) + a;",
1754 traverse(TK_IgnoreUnlessSpelledInSource, HasOperandsWithBindings)));
1755 EXPECT_TRUE(matches(
1756 "int a; int b = a + ((int) a);",
1757 traverse(TK_IgnoreUnlessSpelledInSource, HasOperandsWithBindings)));
1760 TEST(Matcher, BinaryOperatorTypes) {
1761 // Integration test that verifies the AST provides all binary operators in
1762 // a way we expect.
1763 // FIXME: Operator ','
1764 EXPECT_TRUE(
1765 matches("void x() { 3, 4; }", binaryOperator(hasOperatorName(","))));
1766 EXPECT_TRUE(
1767 matches("bool b; bool c = (b = true);",
1768 binaryOperator(hasOperatorName("="))));
1769 EXPECT_TRUE(
1770 matches("bool b = 1 != 2;", binaryOperator(hasOperatorName("!="))));
1771 EXPECT_TRUE(
1772 matches("bool b = 1 == 2;", binaryOperator(hasOperatorName("=="))));
1773 EXPECT_TRUE(matches("bool b = 1 < 2;", binaryOperator(hasOperatorName("<"))));
1774 EXPECT_TRUE(
1775 matches("bool b = 1 <= 2;", binaryOperator(hasOperatorName("<="))));
1776 EXPECT_TRUE(
1777 matches("int i = 1 << 2;", binaryOperator(hasOperatorName("<<"))));
1778 EXPECT_TRUE(
1779 matches("int i = 1; int j = (i <<= 2);",
1780 binaryOperator(hasOperatorName("<<="))));
1781 EXPECT_TRUE(matches("bool b = 1 > 2;", binaryOperator(hasOperatorName(">"))));
1782 EXPECT_TRUE(
1783 matches("bool b = 1 >= 2;", binaryOperator(hasOperatorName(">="))));
1784 EXPECT_TRUE(
1785 matches("int i = 1 >> 2;", binaryOperator(hasOperatorName(">>"))));
1786 EXPECT_TRUE(
1787 matches("int i = 1; int j = (i >>= 2);",
1788 binaryOperator(hasOperatorName(">>="))));
1789 EXPECT_TRUE(
1790 matches("int i = 42 ^ 23;", binaryOperator(hasOperatorName("^"))));
1791 EXPECT_TRUE(
1792 matches("int i = 42; int j = (i ^= 42);",
1793 binaryOperator(hasOperatorName("^="))));
1794 EXPECT_TRUE(
1795 matches("int i = 42 % 23;", binaryOperator(hasOperatorName("%"))));
1796 EXPECT_TRUE(
1797 matches("int i = 42; int j = (i %= 42);",
1798 binaryOperator(hasOperatorName("%="))));
1799 EXPECT_TRUE(
1800 matches("bool b = 42 &23;", binaryOperator(hasOperatorName("&"))));
1801 EXPECT_TRUE(
1802 matches("bool b = true && false;",
1803 binaryOperator(hasOperatorName("&&"))));
1804 EXPECT_TRUE(
1805 matches("bool b = true; bool c = (b &= false);",
1806 binaryOperator(hasOperatorName("&="))));
1807 EXPECT_TRUE(
1808 matches("bool b = 42 | 23;", binaryOperator(hasOperatorName("|"))));
1809 EXPECT_TRUE(
1810 matches("bool b = true || false;",
1811 binaryOperator(hasOperatorName("||"))));
1812 EXPECT_TRUE(
1813 matches("bool b = true; bool c = (b |= false);",
1814 binaryOperator(hasOperatorName("|="))));
1815 EXPECT_TRUE(
1816 matches("int i = 42 *23;", binaryOperator(hasOperatorName("*"))));
1817 EXPECT_TRUE(
1818 matches("int i = 42; int j = (i *= 23);",
1819 binaryOperator(hasOperatorName("*="))));
1820 EXPECT_TRUE(
1821 matches("int i = 42 / 23;", binaryOperator(hasOperatorName("/"))));
1822 EXPECT_TRUE(
1823 matches("int i = 42; int j = (i /= 23);",
1824 binaryOperator(hasOperatorName("/="))));
1825 EXPECT_TRUE(
1826 matches("int i = 42 + 23;", binaryOperator(hasOperatorName("+"))));
1827 EXPECT_TRUE(
1828 matches("int i = 42; int j = (i += 23);",
1829 binaryOperator(hasOperatorName("+="))));
1830 EXPECT_TRUE(
1831 matches("int i = 42 - 23;", binaryOperator(hasOperatorName("-"))));
1832 EXPECT_TRUE(
1833 matches("int i = 42; int j = (i -= 23);",
1834 binaryOperator(hasOperatorName("-="))));
1835 EXPECT_TRUE(
1836 matches("struct A { void x() { void (A::*a)(); (this->*a)(); } };",
1837 binaryOperator(hasOperatorName("->*"))));
1838 EXPECT_TRUE(
1839 matches("struct A { void x() { void (A::*a)(); ((*this).*a)(); } };",
1840 binaryOperator(hasOperatorName(".*"))));
1842 // Member expressions as operators are not supported in matches.
1843 EXPECT_TRUE(
1844 notMatches("struct A { void x(A *a) { a->x(this); } };",
1845 binaryOperator(hasOperatorName("->"))));
1847 // Initializer assignments are not represented as operator equals.
1848 EXPECT_TRUE(
1849 notMatches("bool b = true;", binaryOperator(hasOperatorName("="))));
1851 // Array indexing is not represented as operator.
1852 EXPECT_TRUE(notMatches("int a[42]; void x() { a[23]; }", unaryOperator()));
1854 // Overloaded operators do not match at all.
1855 EXPECT_TRUE(notMatches(
1856 "struct A { bool operator&&(const A &a) const { return false; } };"
1857 "void x() { A a, b; a && b; }",
1858 binaryOperator()));
1861 TEST(MatchUnaryOperator, HasOperatorName) {
1862 StatementMatcher OperatorNot = unaryOperator(hasOperatorName("!"));
1864 EXPECT_TRUE(matches("void x() { !true; } ", OperatorNot));
1865 EXPECT_TRUE(notMatches("void x() { true; } ", OperatorNot));
1868 TEST(MatchUnaryOperator, HasAnyOperatorName) {
1869 StatementMatcher Matcher = unaryOperator(hasAnyOperatorName("-", "*", "++"));
1871 EXPECT_TRUE(matches("int x(int *I) { return *I; }", Matcher));
1872 EXPECT_TRUE(matches("int x(int I) { return -I; }", Matcher));
1873 EXPECT_TRUE(matches("void x(int &I) { I++; }", Matcher));
1874 EXPECT_TRUE(matches("void x(int &I) { ++I; }", Matcher));
1875 EXPECT_TRUE(notMatches("void x(int &I) { I--; }", Matcher));
1876 EXPECT_TRUE(notMatches("void x(int &I) { --I; }", Matcher));
1877 EXPECT_TRUE(notMatches("int *x(int &I) { return &I; }", Matcher));
1880 TEST(MatchUnaryOperator, HasUnaryOperand) {
1881 StatementMatcher OperatorOnFalse =
1882 unaryOperator(hasUnaryOperand(cxxBoolLiteral(equals(false))));
1884 EXPECT_TRUE(matches("void x() { !false; }", OperatorOnFalse));
1885 EXPECT_TRUE(notMatches("void x() { !true; }", OperatorOnFalse));
1887 StringRef Code = R"cpp(
1888 struct HasOpBangMem
1890 bool operator!() const
1892 return false;
1895 struct HasOpBangFree
1898 bool operator!(HasOpBangFree const&)
1900 return false;
1903 void opMem()
1905 HasOpBangMem s1;
1906 if (!s1)
1907 return;
1909 void opFree()
1911 HasOpBangFree s1;
1912 if (!s1)
1913 return;
1915 )cpp";
1916 auto s1Expr = declRefExpr(to(varDecl(hasName("s1"))));
1917 EXPECT_TRUE(matches(
1918 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1919 cxxOperatorCallExpr(
1920 forFunction(functionDecl(hasName("opMem"))),
1921 hasOperatorName("!"), hasUnaryOperand(s1Expr)))));
1922 EXPECT_TRUE(matches(
1923 Code,
1924 traverse(TK_IgnoreUnlessSpelledInSource,
1925 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opMem"))),
1926 hasAnyOperatorName("+", "!"),
1927 hasUnaryOperand(s1Expr)))));
1929 EXPECT_TRUE(matches(
1930 Code, traverse(TK_IgnoreUnlessSpelledInSource,
1931 cxxOperatorCallExpr(
1932 forFunction(functionDecl(hasName("opFree"))),
1933 hasOperatorName("!"), hasUnaryOperand(s1Expr)))));
1934 EXPECT_TRUE(matches(
1935 Code,
1936 traverse(TK_IgnoreUnlessSpelledInSource,
1937 cxxOperatorCallExpr(forFunction(functionDecl(hasName("opFree"))),
1938 hasAnyOperatorName("+", "!"),
1939 hasUnaryOperand(s1Expr)))));
1941 Code = R"cpp(
1942 struct HasIncOperatorsMem
1944 HasIncOperatorsMem& operator++();
1945 HasIncOperatorsMem operator++(int);
1947 struct HasIncOperatorsFree
1950 HasIncOperatorsFree& operator++(HasIncOperatorsFree&);
1951 HasIncOperatorsFree operator++(HasIncOperatorsFree&, int);
1953 void prefixIncOperatorMem()
1955 HasIncOperatorsMem s1;
1956 ++s1;
1958 void prefixIncOperatorFree()
1960 HasIncOperatorsFree s1;
1961 ++s1;
1963 void postfixIncOperatorMem()
1965 HasIncOperatorsMem s1;
1966 s1++;
1968 void postfixIncOperatorFree()
1970 HasIncOperatorsFree s1;
1971 s1++;
1974 struct HasOpPlusInt
1976 HasOpPlusInt& operator+(int);
1978 void plusIntOperator()
1980 HasOpPlusInt s1;
1981 s1+1;
1983 )cpp";
1985 EXPECT_TRUE(matches(
1986 Code,
1987 traverse(TK_IgnoreUnlessSpelledInSource,
1988 cxxOperatorCallExpr(
1989 forFunction(functionDecl(hasName("prefixIncOperatorMem"))),
1990 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1992 EXPECT_TRUE(matches(
1993 Code,
1994 traverse(TK_IgnoreUnlessSpelledInSource,
1995 cxxOperatorCallExpr(
1996 forFunction(functionDecl(hasName("prefixIncOperatorFree"))),
1997 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
1999 EXPECT_TRUE(matches(
2000 Code,
2001 traverse(TK_IgnoreUnlessSpelledInSource,
2002 cxxOperatorCallExpr(
2003 forFunction(functionDecl(hasName("postfixIncOperatorMem"))),
2004 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2006 EXPECT_TRUE(matches(
2007 Code,
2008 traverse(TK_IgnoreUnlessSpelledInSource,
2009 cxxOperatorCallExpr(
2010 forFunction(functionDecl(hasName("postfixIncOperatorFree"))),
2011 hasOperatorName("++"), hasUnaryOperand(declRefExpr())))));
2013 EXPECT_FALSE(matches(
2014 Code, traverse(TK_IgnoreUnlessSpelledInSource,
2015 cxxOperatorCallExpr(
2016 forFunction(functionDecl(hasName("plusIntOperator"))),
2017 hasOperatorName("+"), hasUnaryOperand(expr())))));
2019 Code = R"cpp(
2020 struct HasOpArrow
2022 int& operator*();
2024 void foo()
2026 HasOpArrow s1;
2027 *s1;
2029 )cpp";
2031 EXPECT_TRUE(
2032 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
2033 cxxOperatorCallExpr(hasOperatorName("*"),
2034 hasUnaryOperand(expr())))));
2037 TEST(Matcher, UnaryOperatorTypes) {
2038 // Integration test that verifies the AST provides all unary operators in
2039 // a way we expect.
2040 EXPECT_TRUE(matches("bool b = !true;", unaryOperator(hasOperatorName("!"))));
2041 EXPECT_TRUE(
2042 matches("bool b; bool *p = &b;", unaryOperator(hasOperatorName("&"))));
2043 EXPECT_TRUE(matches("int i = ~ 1;", unaryOperator(hasOperatorName("~"))));
2044 EXPECT_TRUE(
2045 matches("bool *p; bool b = *p;", unaryOperator(hasOperatorName("*"))));
2046 EXPECT_TRUE(
2047 matches("int i; int j = +i;", unaryOperator(hasOperatorName("+"))));
2048 EXPECT_TRUE(
2049 matches("int i; int j = -i;", unaryOperator(hasOperatorName("-"))));
2050 EXPECT_TRUE(
2051 matches("int i; int j = ++i;", unaryOperator(hasOperatorName("++"))));
2052 EXPECT_TRUE(
2053 matches("int i; int j = i++;", unaryOperator(hasOperatorName("++"))));
2054 EXPECT_TRUE(
2055 matches("int i; int j = --i;", unaryOperator(hasOperatorName("--"))));
2056 EXPECT_TRUE(
2057 matches("int i; int j = i--;", unaryOperator(hasOperatorName("--"))));
2059 // We don't match conversion operators.
2060 EXPECT_TRUE(notMatches("int i; double d = (double)i;", unaryOperator()));
2062 // Function calls are not represented as operator.
2063 EXPECT_TRUE(notMatches("void f(); void x() { f(); }", unaryOperator()));
2065 // Overloaded operators do not match at all.
2066 // FIXME: We probably want to add that.
2067 EXPECT_TRUE(notMatches(
2068 "struct A { bool operator!() const { return false; } };"
2069 "void x() { A a; !a; }", unaryOperator(hasOperatorName("!"))));
2072 TEST_P(ASTMatchersTest, HasInit) {
2073 if (!GetParam().isCXX11OrLater()) {
2074 // FIXME: Add a test for `hasInit()` that does not depend on C++.
2075 return;
2078 EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));
2079 EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));
2080 EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));
2083 TEST_P(ASTMatchersTest, HasFoldInit) {
2084 if (!GetParam().isCXX17OrLater()) {
2085 return;
2088 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2089 "return (0 + ... + args); }",
2090 cxxFoldExpr(hasFoldInit(expr()))));
2091 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2092 "return (args + ... + 0); }",
2093 cxxFoldExpr(hasFoldInit(expr()))));
2094 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2095 "return (... + args); };",
2096 cxxFoldExpr(hasFoldInit(expr()))));
2099 TEST_P(ASTMatchersTest, HasPattern) {
2100 if (!GetParam().isCXX17OrLater()) {
2101 return;
2104 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2105 "return (0 + ... + args); }",
2106 cxxFoldExpr(hasPattern(expr()))));
2107 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2108 "return (args + ... + 0); }",
2109 cxxFoldExpr(hasPattern(expr()))));
2110 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2111 "return (... + args); };",
2112 cxxFoldExpr(hasPattern(expr()))));
2115 TEST_P(ASTMatchersTest, HasLHSAndHasRHS) {
2116 if (!GetParam().isCXX17OrLater()) {
2117 return;
2120 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2121 "return (0 + ... + args); }",
2122 cxxFoldExpr(hasLHS(expr()))));
2123 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2124 "return (args + ... + 0); }",
2125 cxxFoldExpr(hasLHS(expr()))));
2126 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2127 "return (... + args); };",
2128 cxxFoldExpr(hasLHS(expr()))));
2129 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2130 "return (args + ...); };",
2131 cxxFoldExpr(hasLHS(expr()))));
2133 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2134 "return (0 + ... + args); }",
2135 cxxFoldExpr(hasRHS(expr()))));
2136 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2137 "return (args + ... + 0); }",
2138 cxxFoldExpr(hasRHS(expr()))));
2139 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2140 "return (... + args); };",
2141 cxxFoldExpr(hasRHS(expr()))));
2142 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2143 "return (args + ...); };",
2144 cxxFoldExpr(hasRHS(expr()))));
2147 TEST_P(ASTMatchersTest, HasEitherOperandAndHasOperands) {
2148 if (!GetParam().isCXX17OrLater()) {
2149 return;
2152 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2153 "return (0 + ... + args); }",
2154 cxxFoldExpr(hasEitherOperand(integerLiteral()))));
2155 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2156 "return (args + ... + 0); }",
2157 cxxFoldExpr(hasEitherOperand(integerLiteral()))));
2159 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2160 "return (0 + ... + args); }",
2161 cxxFoldExpr(hasEitherOperand(
2162 declRefExpr(to(namedDecl(hasName("args"))))))));
2163 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2164 "return (args + ... + 0); }",
2165 cxxFoldExpr(hasEitherOperand(
2166 declRefExpr(to(namedDecl(hasName("args"))))))));
2167 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2168 "return (... + args); };",
2169 cxxFoldExpr(hasEitherOperand(
2170 declRefExpr(to(namedDecl(hasName("args"))))))));
2171 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
2172 "return (args + ...); };",
2173 cxxFoldExpr(hasEitherOperand(
2174 declRefExpr(to(namedDecl(hasName("args"))))))));
2176 EXPECT_TRUE(matches(
2177 "template <typename... Args> auto sum(Args... args) { "
2178 "return (0 + ... + args); }",
2179 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2180 integerLiteral()))));
2181 EXPECT_TRUE(matches(
2182 "template <typename... Args> auto sum(Args... args) { "
2183 "return (args + ... + 0); }",
2184 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2185 integerLiteral()))));
2186 EXPECT_FALSE(matches(
2187 "template <typename... Args> auto sum(Args... args) { "
2188 "return (... + args); };",
2189 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2190 integerLiteral()))));
2191 EXPECT_FALSE(matches(
2192 "template <typename... Args> auto sum(Args... args) { "
2193 "return (args + ...); };",
2194 cxxFoldExpr(hasOperands(declRefExpr(to(namedDecl(hasName("args")))),
2195 integerLiteral()))));
2198 TEST_P(ASTMatchersTest, Callee) {
2199 if (!GetParam().isCXX17OrLater()) {
2200 return;
2203 EXPECT_TRUE(matches(
2204 "struct Dummy {}; Dummy operator+(Dummy, Dummy); template "
2205 "<typename... Args> auto sum(Args... args) { return (0 + ... + args); }",
2206 cxxFoldExpr(callee(expr()))));
2207 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
2208 "return (0 + ... + args); }",
2209 cxxFoldExpr(callee(expr()))));
2212 TEST(ArraySubscriptMatchers, ArrayIndex) {
2213 EXPECT_TRUE(matches(
2214 "int i[2]; void f() { i[1] = 1; }",
2215 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2216 EXPECT_TRUE(matches(
2217 "int i[2]; void f() { 1[i] = 1; }",
2218 arraySubscriptExpr(hasIndex(integerLiteral(equals(1))))));
2219 EXPECT_TRUE(notMatches(
2220 "int i[2]; void f() { i[1] = 1; }",
2221 arraySubscriptExpr(hasIndex(integerLiteral(equals(0))))));
2224 TEST(ArraySubscriptMatchers, MatchesArrayBase) {
2225 EXPECT_TRUE(
2226 matches("int i[2]; void f() { i[1] = 2; }",
2227 traverse(TK_AsIs, arraySubscriptExpr(hasBase(implicitCastExpr(
2228 hasSourceExpression(declRefExpr())))))));
2231 TEST(Matcher, OfClass) {
2232 StatementMatcher Constructor = cxxConstructExpr(hasDeclaration(cxxMethodDecl(
2233 ofClass(hasName("X")))));
2235 EXPECT_TRUE(
2236 matches("class X { public: X(); }; void x(int) { X x; }", Constructor));
2237 EXPECT_TRUE(
2238 matches("class X { public: X(); }; void x(int) { X x = X(); }",
2239 Constructor));
2240 EXPECT_TRUE(
2241 notMatches("class Y { public: Y(); }; void x(int) { Y y; }",
2242 Constructor));
2245 TEST(Matcher, VisitsTemplateInstantiations) {
2246 EXPECT_TRUE(matches(
2247 "class A { public: void x(); };"
2248 "template <typename T> class B { public: void y() { T t; t.x(); } };"
2249 "void f() { B<A> b; b.y(); }",
2250 callExpr(callee(cxxMethodDecl(hasName("x"))))));
2252 EXPECT_TRUE(matches(
2253 "class A { public: void x(); };"
2254 "class C {"
2255 " public:"
2256 " template <typename T> class B { public: void y() { T t; t.x(); } };"
2257 "};"
2258 "void f() {"
2259 " C::B<A> b; b.y();"
2260 "}",
2261 recordDecl(hasName("C"), hasDescendant(callExpr(
2262 callee(cxxMethodDecl(hasName("x"))))))));
2265 TEST(Matcher, HasCondition) {
2266 StatementMatcher IfStmt =
2267 ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
2268 EXPECT_TRUE(matches("void x() { if (true) {} }", IfStmt));
2269 EXPECT_TRUE(notMatches("void x() { if (false) {} }", IfStmt));
2271 StatementMatcher ForStmt =
2272 forStmt(hasCondition(cxxBoolLiteral(equals(true))));
2273 EXPECT_TRUE(matches("void x() { for (;true;) {} }", ForStmt));
2274 EXPECT_TRUE(notMatches("void x() { for (;false;) {} }", ForStmt));
2276 StatementMatcher WhileStmt =
2277 whileStmt(hasCondition(cxxBoolLiteral(equals(true))));
2278 EXPECT_TRUE(matches("void x() { while (true) {} }", WhileStmt));
2279 EXPECT_TRUE(notMatches("void x() { while (false) {} }", WhileStmt));
2281 StatementMatcher SwitchStmt =
2282 switchStmt(hasCondition(integerLiteral(equals(42))));
2283 EXPECT_TRUE(matches("void x() { switch (42) {case 42:;} }", SwitchStmt));
2284 EXPECT_TRUE(notMatches("void x() { switch (43) {case 43:;} }", SwitchStmt));
2287 TEST(For, ForLoopInternals) {
2288 EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
2289 forStmt(hasCondition(anything()))));
2290 EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
2291 forStmt(hasLoopInit(anything()))));
2294 TEST(For, ForRangeLoopInternals) {
2295 EXPECT_TRUE(matches("void f(){ int a[] {1, 2}; for (int i : a); }",
2296 cxxForRangeStmt(hasLoopVariable(anything()))));
2297 EXPECT_TRUE(matches(
2298 "void f(){ int a[] {1, 2}; for (int i : a); }",
2299 cxxForRangeStmt(hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))))));
2302 TEST(For, NegativeForLoopInternals) {
2303 EXPECT_TRUE(notMatches("void f(){ for (int i = 0; ; ++i); }",
2304 forStmt(hasCondition(expr()))));
2305 EXPECT_TRUE(notMatches("void f() {int i; for (; i < 4; ++i) {} }",
2306 forStmt(hasLoopInit(anything()))));
2309 TEST(HasBody, FindsBodyOfForWhileDoLoops) {
2310 EXPECT_TRUE(matches("void f() { for(;;) {} }",
2311 forStmt(hasBody(compoundStmt()))));
2312 EXPECT_TRUE(notMatches("void f() { for(;;); }",
2313 forStmt(hasBody(compoundStmt()))));
2314 EXPECT_TRUE(matches("void f() { while(true) {} }",
2315 whileStmt(hasBody(compoundStmt()))));
2316 EXPECT_TRUE(matches("void f() { do {} while(true); }",
2317 doStmt(hasBody(compoundStmt()))));
2318 EXPECT_TRUE(matches("void f() { int p[2]; for (auto x : p) {} }",
2319 cxxForRangeStmt(hasBody(compoundStmt()))));
2322 TEST(HasBody, FindsBodyOfFunctions) {
2323 EXPECT_TRUE(matches("void f() {}", functionDecl(hasBody(compoundStmt()))));
2324 EXPECT_TRUE(notMatches("void f();", functionDecl(hasBody(compoundStmt()))));
2325 EXPECT_TRUE(matchAndVerifyResultTrue(
2326 "void f(); void f() {}",
2327 functionDecl(hasBody(compoundStmt())).bind("func"),
2328 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 1)));
2329 EXPECT_TRUE(matchAndVerifyResultTrue(
2330 "class C { void f(); }; void C::f() {}",
2331 cxxMethodDecl(hasBody(compoundStmt())).bind("met"),
2332 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 1)));
2333 EXPECT_TRUE(matchAndVerifyResultTrue(
2334 "class C { C(); }; C::C() {}",
2335 cxxConstructorDecl(hasBody(compoundStmt())).bind("ctr"),
2336 std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 1)));
2337 EXPECT_TRUE(matchAndVerifyResultTrue(
2338 "class C { ~C(); }; C::~C() {}",
2339 cxxDestructorDecl(hasBody(compoundStmt())).bind("dtr"),
2340 std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 1)));
2343 TEST(HasAnyBody, FindsAnyBodyOfFunctions) {
2344 EXPECT_TRUE(matches("void f() {}", functionDecl(hasAnyBody(compoundStmt()))));
2345 EXPECT_TRUE(notMatches("void f();",
2346 functionDecl(hasAnyBody(compoundStmt()))));
2347 EXPECT_TRUE(matchAndVerifyResultTrue(
2348 "void f(); void f() {}",
2349 functionDecl(hasAnyBody(compoundStmt())).bind("func"),
2350 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("func", 2)));
2351 EXPECT_TRUE(matchAndVerifyResultTrue(
2352 "class C { void f(); }; void C::f() {}",
2353 cxxMethodDecl(hasAnyBody(compoundStmt())).bind("met"),
2354 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("met", 2)));
2355 EXPECT_TRUE(matchAndVerifyResultTrue(
2356 "class C { C(); }; C::C() {}",
2357 cxxConstructorDecl(hasAnyBody(compoundStmt())).bind("ctr"),
2358 std::make_unique<VerifyIdIsBoundTo<CXXConstructorDecl>>("ctr", 2)));
2359 EXPECT_TRUE(matchAndVerifyResultTrue(
2360 "class C { ~C(); }; C::~C() {}",
2361 cxxDestructorDecl(hasAnyBody(compoundStmt())).bind("dtr"),
2362 std::make_unique<VerifyIdIsBoundTo<CXXDestructorDecl>>("dtr", 2)));
2365 TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
2366 // The simplest case: every compound statement is in a function
2367 // definition, and the function body itself must be a compound
2368 // statement.
2369 EXPECT_TRUE(matches("void f() { for (;;); }",
2370 compoundStmt(hasAnySubstatement(forStmt()))));
2373 TEST(HasAnySubstatement, IsNotRecursive) {
2374 // It's really "has any immediate substatement".
2375 EXPECT_TRUE(notMatches("void f() { if (true) for (;;); }",
2376 compoundStmt(hasAnySubstatement(forStmt()))));
2379 TEST(HasAnySubstatement, MatchesInNestedCompoundStatements) {
2380 EXPECT_TRUE(matches("void f() { if (true) { for (;;); } }",
2381 compoundStmt(hasAnySubstatement(forStmt()))));
2384 TEST(HasAnySubstatement, FindsSubstatementBetweenOthers) {
2385 EXPECT_TRUE(matches("void f() { 1; 2; 3; for (;;); 4; 5; 6; }",
2386 compoundStmt(hasAnySubstatement(forStmt()))));
2389 TEST(Member, MatchesMemberAllocationFunction) {
2390 // Fails in C++11 mode
2391 EXPECT_TRUE(matchesConditionally(
2392 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2393 "class X { void *operator new(std::size_t); };",
2394 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2396 EXPECT_TRUE(matches("class X { void operator delete(void*); };",
2397 cxxMethodDecl(ofClass(hasName("X")))));
2399 // Fails in C++11 mode
2400 EXPECT_TRUE(matchesConditionally(
2401 "namespace std { typedef typeof(sizeof(int)) size_t; }"
2402 "class X { void operator delete[](void*, std::size_t); };",
2403 cxxMethodDecl(ofClass(hasName("X"))), true, {"-std=gnu++03"}));
2406 TEST(HasDestinationType, MatchesSimpleCase) {
2407 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
2408 cxxStaticCastExpr(hasDestinationType(
2409 pointsTo(TypeMatcher(anything()))))));
2412 TEST(HasImplicitDestinationType, MatchesSimpleCase) {
2413 // This test creates an implicit const cast.
2414 EXPECT_TRUE(matches(
2415 "int x; const int i = x;",
2416 traverse(TK_AsIs,
2417 implicitCastExpr(hasImplicitDestinationType(isInteger())))));
2418 // This test creates an implicit array-to-pointer cast.
2419 EXPECT_TRUE(
2420 matches("int arr[3]; int *p = arr;",
2421 traverse(TK_AsIs, implicitCastExpr(hasImplicitDestinationType(
2422 pointsTo(TypeMatcher(anything())))))));
2425 TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {
2426 // This test creates an implicit cast from int to char.
2427 EXPECT_TRUE(notMatches("char c = 0;",
2428 implicitCastExpr(hasImplicitDestinationType(
2429 unless(anything())))));
2430 // This test creates an implicit array-to-pointer cast.
2431 EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
2432 implicitCastExpr(hasImplicitDestinationType(
2433 unless(anything())))));
2436 TEST(Matcher, IgnoresElidableConstructors) {
2437 EXPECT_TRUE(
2438 matches("struct H {};"
2439 "template<typename T> H B(T A);"
2440 "void f() {"
2441 " H D1;"
2442 " D1 = B(B(1));"
2443 "}",
2444 cxxOperatorCallExpr(hasArgument(
2445 1, callExpr(hasArgument(
2446 0, ignoringElidableConstructorCall(callExpr()))))),
2447 langCxx11OrLater()));
2448 EXPECT_TRUE(
2449 matches("struct H {};"
2450 "template<typename T> H B(T A);"
2451 "void f() {"
2452 " H D1;"
2453 " D1 = B(1);"
2454 "}",
2455 cxxOperatorCallExpr(hasArgument(
2456 1, callExpr(hasArgument(0, ignoringElidableConstructorCall(
2457 integerLiteral()))))),
2458 langCxx11OrLater()));
2459 EXPECT_TRUE(matches(
2460 "struct H {};"
2461 "H G();"
2462 "void f() {"
2463 " H D = G();"
2464 "}",
2465 varDecl(hasInitializer(anyOf(
2466 ignoringElidableConstructorCall(callExpr()),
2467 exprWithCleanups(has(ignoringElidableConstructorCall(callExpr())))))),
2468 langCxx11OrLater()));
2471 TEST(Matcher, IgnoresElidableInReturn) {
2472 auto matcher = expr(ignoringElidableConstructorCall(declRefExpr()));
2473 EXPECT_TRUE(matches("struct H {};"
2474 "H f() {"
2475 " H g;"
2476 " return g;"
2477 "}",
2478 matcher, langCxx11OrLater()));
2479 EXPECT_TRUE(notMatches("struct H {};"
2480 "H f() {"
2481 " return H();"
2482 "}",
2483 matcher, langCxx11OrLater()));
2486 TEST(Matcher, IgnoreElidableConstructorDoesNotMatchConstructors) {
2487 EXPECT_TRUE(matches("struct H {};"
2488 "void f() {"
2489 " H D;"
2490 "}",
2491 varDecl(hasInitializer(
2492 ignoringElidableConstructorCall(cxxConstructExpr()))),
2493 langCxx11OrLater()));
2496 TEST(Matcher, IgnoresElidableDoesNotPreventMatches) {
2497 EXPECT_TRUE(matches("void f() {"
2498 " int D = 10;"
2499 "}",
2500 expr(ignoringElidableConstructorCall(integerLiteral())),
2501 langCxx11OrLater()));
2504 TEST(Matcher, IgnoresElidableInVarInit) {
2505 auto matcher =
2506 varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())));
2507 EXPECT_TRUE(matches("struct H {};"
2508 "H G();"
2509 "void f(H D = G()) {"
2510 " return;"
2511 "}",
2512 matcher, langCxx11OrLater()));
2513 EXPECT_TRUE(matches("struct H {};"
2514 "H G();"
2515 "void f() {"
2516 " H D = G();"
2517 "}",
2518 matcher, langCxx11OrLater()));
2521 TEST(IgnoringImplicit, MatchesImplicit) {
2522 EXPECT_TRUE(matches("class C {}; C a = C();",
2523 varDecl(has(ignoringImplicit(cxxConstructExpr())))));
2526 TEST(IgnoringImplicit, MatchesNestedImplicit) {
2527 StringRef Code = R"(
2529 struct OtherType;
2531 struct SomeType
2533 SomeType() {}
2534 SomeType(const OtherType&) {}
2535 SomeType& operator=(OtherType const&) { return *this; }
2538 struct OtherType
2540 OtherType() {}
2541 ~OtherType() {}
2544 OtherType something()
2546 return {};
2549 int main()
2551 SomeType i = something();
2554 EXPECT_TRUE(matches(
2555 Code,
2556 traverse(TK_AsIs,
2557 varDecl(hasName("i"),
2558 hasInitializer(exprWithCleanups(has(cxxConstructExpr(
2559 has(expr(ignoringImplicit(cxxConstructExpr(has(
2560 expr(ignoringImplicit(callExpr())))))))))))))));
2563 TEST(IgnoringImplicit, DoesNotMatchIncorrectly) {
2564 EXPECT_TRUE(notMatches("class C {}; C a = C();",
2565 traverse(TK_AsIs, varDecl(has(cxxConstructExpr())))));
2568 TEST(Traversal, traverseMatcher) {
2570 StringRef VarDeclCode = R"cpp(
2571 void foo()
2573 int i = 3.0;
2575 )cpp";
2577 auto Matcher = varDecl(hasInitializer(floatLiteral()));
2579 EXPECT_TRUE(notMatches(VarDeclCode, traverse(TK_AsIs, Matcher)));
2580 EXPECT_TRUE(
2581 matches(VarDeclCode, traverse(TK_IgnoreUnlessSpelledInSource, Matcher)));
2583 auto ParentMatcher = floatLiteral(hasParent(varDecl(hasName("i"))));
2585 EXPECT_TRUE(notMatches(VarDeclCode, traverse(TK_AsIs, ParentMatcher)));
2586 EXPECT_TRUE(matches(VarDeclCode,
2587 traverse(TK_IgnoreUnlessSpelledInSource, ParentMatcher)));
2589 EXPECT_TRUE(matches(
2590 VarDeclCode, decl(traverse(TK_AsIs, anyOf(cxxRecordDecl(), varDecl())))));
2592 EXPECT_TRUE(
2593 matches(VarDeclCode,
2594 floatLiteral(traverse(TK_AsIs, hasParent(implicitCastExpr())))));
2596 EXPECT_TRUE(
2597 matches(VarDeclCode, floatLiteral(traverse(TK_IgnoreUnlessSpelledInSource,
2598 hasParent(varDecl())))));
2600 EXPECT_TRUE(
2601 matches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,
2602 unless(parmVarDecl())))));
2604 EXPECT_TRUE(
2605 notMatches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,
2606 has(implicitCastExpr())))));
2608 EXPECT_TRUE(matches(VarDeclCode,
2609 varDecl(traverse(TK_AsIs, has(implicitCastExpr())))));
2611 EXPECT_TRUE(matches(
2612 VarDeclCode, traverse(TK_IgnoreUnlessSpelledInSource,
2613 // The has() below strips away the ImplicitCastExpr
2614 // before the traverse(AsIs) gets to process it.
2615 varDecl(has(traverse(TK_AsIs, floatLiteral()))))));
2617 EXPECT_TRUE(
2618 matches(VarDeclCode, functionDecl(traverse(TK_AsIs, hasName("foo")))));
2620 EXPECT_TRUE(matches(
2621 VarDeclCode,
2622 functionDecl(traverse(TK_IgnoreUnlessSpelledInSource, hasName("foo")))));
2624 EXPECT_TRUE(matches(
2625 VarDeclCode, functionDecl(traverse(TK_AsIs, hasAnyName("foo", "bar")))));
2627 EXPECT_TRUE(
2628 matches(VarDeclCode, functionDecl(traverse(TK_IgnoreUnlessSpelledInSource,
2629 hasAnyName("foo", "bar")))));
2631 StringRef Code = R"cpp(
2632 void foo(int a)
2634 int i = 3.0 + a;
2636 void bar()
2638 foo(7.0);
2640 )cpp";
2641 EXPECT_TRUE(
2642 matches(Code, callExpr(traverse(TK_IgnoreUnlessSpelledInSource,
2643 hasArgument(0, floatLiteral())))));
2645 EXPECT_TRUE(
2646 matches(Code, callExpr(traverse(TK_IgnoreUnlessSpelledInSource,
2647 hasAnyArgument(floatLiteral())))));
2649 EXPECT_TRUE(matches(
2650 R"cpp(
2651 void takesBool(bool){}
2653 template <typename T>
2654 void neverInstantiatedTemplate() {
2655 takesBool(T{});
2657 )cpp",
2658 traverse(TK_IgnoreUnlessSpelledInSource,
2659 callExpr(unless(callExpr(hasDeclaration(functionDecl())))))));
2661 EXPECT_TRUE(
2662 matches(VarDeclCode, varDecl(traverse(TK_IgnoreUnlessSpelledInSource,
2663 hasType(builtinType())))));
2665 EXPECT_TRUE(
2666 matches(VarDeclCode,
2667 functionDecl(hasName("foo"),
2668 traverse(TK_AsIs, hasDescendant(floatLiteral())))));
2670 EXPECT_TRUE(notMatches(
2671 Code, traverse(TK_AsIs, floatLiteral(hasParent(callExpr(
2672 callee(functionDecl(hasName("foo")))))))));
2673 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
2674 floatLiteral(hasParent(callExpr(callee(
2675 functionDecl(hasName("foo")))))))));
2677 Code = R"cpp(
2678 void foo()
2680 int i = (3);
2682 )cpp";
2683 EXPECT_TRUE(matches(
2684 Code, traverse(TK_IgnoreUnlessSpelledInSource,
2685 varDecl(hasInitializer(integerLiteral(equals(3)))))));
2686 EXPECT_TRUE(matches(
2687 Code,
2688 traverse(TK_IgnoreUnlessSpelledInSource,
2689 integerLiteral(equals(3), hasParent(varDecl(hasName("i")))))));
2691 Code = R"cpp(
2692 const char *SomeString{"str"};
2693 )cpp";
2694 EXPECT_TRUE(
2695 matches(Code, traverse(TK_AsIs, stringLiteral(hasParent(implicitCastExpr(
2696 hasParent(initListExpr())))))));
2697 EXPECT_TRUE(
2698 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
2699 stringLiteral(hasParent(initListExpr())))));
2701 Code = R"cpp(
2702 struct String
2704 String(const char*, int = -1) {}
2707 void stringConstruct()
2709 String s = "foo";
2710 s = "bar";
2712 )cpp";
2713 EXPECT_TRUE(matches(
2714 Code,
2715 traverse(
2716 TK_AsIs,
2717 functionDecl(
2718 hasName("stringConstruct"),
2719 hasDescendant(varDecl(
2720 hasName("s"),
2721 hasInitializer(ignoringImplicit(cxxConstructExpr(hasArgument(
2722 0, ignoringImplicit(cxxConstructExpr(hasArgument(
2723 0, ignoringImplicit(stringLiteral()))))))))))))));
2725 EXPECT_TRUE(matches(
2726 Code,
2727 traverse(
2728 TK_AsIs,
2729 functionDecl(hasName("stringConstruct"),
2730 hasDescendant(cxxOperatorCallExpr(
2731 isAssignmentOperator(),
2732 hasArgument(1, ignoringImplicit(
2733 cxxConstructExpr(hasArgument(
2734 0, ignoringImplicit(stringLiteral())))))
2735 ))))));
2737 EXPECT_TRUE(matches(
2738 Code, traverse(TK_IgnoreUnlessSpelledInSource,
2739 functionDecl(hasName("stringConstruct"),
2740 hasDescendant(varDecl(
2741 hasName("s"),
2742 hasInitializer(stringLiteral())))))));
2744 EXPECT_TRUE(
2745 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
2746 functionDecl(hasName("stringConstruct"),
2747 hasDescendant(cxxOperatorCallExpr(
2748 isAssignmentOperator(),
2749 hasArgument(1, stringLiteral())))))));
2751 Code = R"cpp(
2753 struct C1 {};
2754 struct C2 { operator C1(); };
2756 void conversionOperator()
2758 C2* c2;
2759 C1 c1 = (*c2);
2762 )cpp";
2763 EXPECT_TRUE(matches(
2764 Code,
2765 traverse(
2766 TK_AsIs,
2767 functionDecl(
2768 hasName("conversionOperator"),
2769 hasDescendant(
2770 varDecl(
2771 hasName("c1"),
2772 hasInitializer(
2773 ignoringImplicit(cxxConstructExpr(hasArgument(
2774 0, ignoringImplicit(
2775 cxxMemberCallExpr(onImplicitObjectArgument(
2776 ignoringParenImpCasts(unaryOperator(
2777 hasOperatorName("*")))))))))))
2778 .bind("c1"))))));
2780 EXPECT_TRUE(matches(
2781 Code,
2782 traverse(TK_IgnoreUnlessSpelledInSource,
2783 functionDecl(hasName("conversionOperator"),
2784 hasDescendant(varDecl(
2785 hasName("c1"), hasInitializer(unaryOperator(
2786 hasOperatorName("*")))))))));
2788 Code = R"cpp(
2790 template <unsigned alignment>
2791 void template_test() {
2792 static_assert(alignment, "");
2794 void actual_template_test() {
2795 template_test<4>();
2798 )cpp";
2799 EXPECT_TRUE(matches(
2800 Code,
2801 traverse(TK_AsIs,
2802 staticAssertDecl(has(implicitCastExpr(has(
2803 substNonTypeTemplateParmExpr(has(integerLiteral())))))))));
2804 EXPECT_TRUE(matches(
2805 Code, traverse(TK_IgnoreUnlessSpelledInSource,
2806 staticAssertDecl(has(declRefExpr(
2807 to(nonTypeTemplateParmDecl(hasName("alignment"))),
2808 hasType(asString("unsigned int"))))))));
2810 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, staticAssertDecl(hasDescendant(
2811 integerLiteral())))));
2812 EXPECT_FALSE(matches(
2813 Code, traverse(TK_IgnoreUnlessSpelledInSource,
2814 staticAssertDecl(hasDescendant(integerLiteral())))));
2816 Code = R"cpp(
2818 struct OneParamCtor {
2819 explicit OneParamCtor(int);
2821 struct TwoParamCtor {
2822 explicit TwoParamCtor(int, int);
2825 void varDeclCtors() {
2827 auto var1 = OneParamCtor(5);
2828 auto var2 = TwoParamCtor(6, 7);
2831 OneParamCtor var3(5);
2832 TwoParamCtor var4(6, 7);
2834 int i = 0;
2836 auto var5 = OneParamCtor(i);
2837 auto var6 = TwoParamCtor(i, 7);
2840 OneParamCtor var7(i);
2841 TwoParamCtor var8(i, 7);
2845 )cpp";
2846 EXPECT_TRUE(matches(
2847 Code,
2848 traverse(TK_AsIs, varDecl(hasName("var1"), hasInitializer(hasDescendant(
2849 cxxConstructExpr()))))));
2850 EXPECT_TRUE(matches(
2851 Code,
2852 traverse(TK_AsIs, varDecl(hasName("var2"), hasInitializer(hasDescendant(
2853 cxxConstructExpr()))))));
2854 EXPECT_TRUE(matches(
2855 Code, traverse(TK_AsIs, varDecl(hasName("var3"),
2856 hasInitializer(cxxConstructExpr())))));
2857 EXPECT_TRUE(matches(
2858 Code, traverse(TK_AsIs, varDecl(hasName("var4"),
2859 hasInitializer(cxxConstructExpr())))));
2860 EXPECT_TRUE(matches(
2861 Code,
2862 traverse(TK_AsIs, varDecl(hasName("var5"), hasInitializer(hasDescendant(
2863 cxxConstructExpr()))))));
2864 EXPECT_TRUE(matches(
2865 Code,
2866 traverse(TK_AsIs, varDecl(hasName("var6"), hasInitializer(hasDescendant(
2867 cxxConstructExpr()))))));
2868 EXPECT_TRUE(matches(
2869 Code, traverse(TK_AsIs, varDecl(hasName("var7"),
2870 hasInitializer(cxxConstructExpr())))));
2871 EXPECT_TRUE(matches(
2872 Code, traverse(TK_AsIs, varDecl(hasName("var8"),
2873 hasInitializer(cxxConstructExpr())))));
2875 EXPECT_TRUE(matches(
2876 Code,
2877 traverse(TK_IgnoreUnlessSpelledInSource,
2878 varDecl(hasName("var1"), hasInitializer(cxxConstructExpr())))));
2879 EXPECT_TRUE(matches(
2880 Code,
2881 traverse(TK_IgnoreUnlessSpelledInSource,
2882 varDecl(hasName("var2"), hasInitializer(cxxConstructExpr())))));
2883 EXPECT_TRUE(matches(
2884 Code,
2885 traverse(TK_IgnoreUnlessSpelledInSource,
2886 varDecl(hasName("var3"), hasInitializer(cxxConstructExpr())))));
2887 EXPECT_TRUE(matches(
2888 Code,
2889 traverse(TK_IgnoreUnlessSpelledInSource,
2890 varDecl(hasName("var4"), hasInitializer(cxxConstructExpr())))));
2891 EXPECT_TRUE(matches(
2892 Code,
2893 traverse(TK_IgnoreUnlessSpelledInSource,
2894 varDecl(hasName("var5"), hasInitializer(cxxConstructExpr())))));
2895 EXPECT_TRUE(matches(
2896 Code,
2897 traverse(TK_IgnoreUnlessSpelledInSource,
2898 varDecl(hasName("var6"), hasInitializer(cxxConstructExpr())))));
2899 EXPECT_TRUE(matches(
2900 Code,
2901 traverse(TK_IgnoreUnlessSpelledInSource,
2902 varDecl(hasName("var7"), hasInitializer(cxxConstructExpr())))));
2903 EXPECT_TRUE(matches(
2904 Code,
2905 traverse(TK_IgnoreUnlessSpelledInSource,
2906 varDecl(hasName("var8"), hasInitializer(cxxConstructExpr())))));
2908 Code = R"cpp(
2910 template<typename T>
2911 struct TemplStruct {
2912 TemplStruct() {}
2913 ~TemplStruct() {}
2915 void outOfLine(T);
2917 private:
2918 T m_t;
2921 template<typename T>
2922 void TemplStruct<T>::outOfLine(T)
2927 template<typename T>
2928 T timesTwo(T input)
2930 return input * 2;
2933 void instantiate()
2935 TemplStruct<int> ti;
2936 TemplStruct<double> td;
2937 (void)timesTwo<int>(2);
2938 (void)timesTwo<double>(2);
2941 template class TemplStruct<float>;
2943 extern template class TemplStruct<long>;
2945 template<> class TemplStruct<bool> {
2946 TemplStruct() {}
2947 ~TemplStruct() {}
2949 void boolSpecializationMethodOnly() {}
2950 private:
2951 bool m_t;
2954 template float timesTwo(float);
2955 template<> bool timesTwo<bool>(bool){
2956 return true;
2958 )cpp";
2960 auto M = cxxRecordDecl(hasName("TemplStruct"),
2961 has(fieldDecl(hasType(asString("int")))));
2962 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
2963 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
2966 auto M = cxxRecordDecl(hasName("TemplStruct"),
2967 has(fieldDecl(hasType(asString("double")))));
2968 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
2969 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
2972 auto M =
2973 functionDecl(hasName("timesTwo"),
2974 hasParameter(0, parmVarDecl(hasType(asString("int")))));
2975 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
2976 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
2979 auto M =
2980 functionDecl(hasName("timesTwo"),
2981 hasParameter(0, parmVarDecl(hasType(asString("double")))));
2982 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
2983 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
2986 // Match on the integer literal in the explicit instantiation:
2987 auto MDef =
2988 functionDecl(hasName("timesTwo"),
2989 hasParameter(0, parmVarDecl(hasType(asString("float")))),
2990 hasDescendant(integerLiteral(equals(2))));
2991 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));
2992 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));
2994 auto MTempl =
2995 functionDecl(hasName("timesTwo"),
2996 hasTemplateArgument(0, refersToType(asString("float"))));
2997 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MTempl)));
2998 // TODO: If we could match on explicit instantiations of function templates,
2999 // this would be EXPECT_TRUE. See Sema::ActOnExplicitInstantiation.
3000 EXPECT_FALSE(
3001 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MTempl)));
3004 auto M = functionDecl(hasName("timesTwo"),
3005 hasParameter(0, parmVarDecl(hasType(booleanType()))));
3006 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3007 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3010 // Match on the field within the explicit instantiation:
3011 auto MRecord = cxxRecordDecl(hasName("TemplStruct"),
3012 has(fieldDecl(hasType(asString("float")))));
3013 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MRecord)));
3014 EXPECT_FALSE(
3015 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MRecord)));
3017 // Match on the explicit template instantiation itself:
3018 auto MTempl = classTemplateSpecializationDecl(
3019 hasName("TemplStruct"),
3020 hasTemplateArgument(0,
3021 templateArgument(refersToType(asString("float")))));
3022 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MTempl)));
3023 EXPECT_TRUE(
3024 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MTempl)));
3027 // The template argument is matchable, but the instantiation is not:
3028 auto M = classTemplateSpecializationDecl(
3029 hasName("TemplStruct"),
3030 hasTemplateArgument(0,
3031 templateArgument(refersToType(asString("float")))),
3032 has(cxxConstructorDecl(hasName("TemplStruct"))));
3033 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3034 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3037 // The template argument is matchable, but the instantiation is not:
3038 auto M = classTemplateSpecializationDecl(
3039 hasName("TemplStruct"),
3040 hasTemplateArgument(0,
3041 templateArgument(refersToType(asString("long")))),
3042 has(cxxConstructorDecl(hasName("TemplStruct"))));
3043 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3044 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3047 // Instantiated, out-of-line methods are not matchable.
3048 auto M =
3049 cxxMethodDecl(hasName("outOfLine"), isDefinition(),
3050 hasParameter(0, parmVarDecl(hasType(asString("float")))));
3051 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3052 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3055 // Explicit specialization is written in source and it matches:
3056 auto M = classTemplateSpecializationDecl(
3057 hasName("TemplStruct"),
3058 hasTemplateArgument(0, templateArgument(refersToType(booleanType()))),
3059 has(cxxConstructorDecl(hasName("TemplStruct"))),
3060 has(cxxMethodDecl(hasName("boolSpecializationMethodOnly"))));
3061 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3062 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3065 Code = R"cpp(
3066 struct B {
3067 B(int);
3070 B func1() { return 42; }
3071 )cpp";
3073 auto M = expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit")));
3074 EXPECT_TRUE(matchAndVerifyResultTrue(
3075 Code, traverse(TK_AsIs, M),
3076 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3077 EXPECT_TRUE(matchAndVerifyResultTrue(
3078 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3079 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3082 auto M = expr(unless(integerLiteral(equals(24)))).bind("intLit");
3083 EXPECT_TRUE(matchAndVerifyResultTrue(
3084 Code, traverse(TK_AsIs, M),
3085 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 6),
3086 {"-std=c++11"}));
3088 EXPECT_TRUE(matchAndVerifyResultTrue(
3089 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3090 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1),
3091 {"-std=c++11"}));
3094 auto M =
3095 expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr())));
3096 EXPECT_TRUE(matchAndVerifyResultTrue(
3097 Code, traverse(TK_AsIs, M),
3098 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3099 EXPECT_TRUE(matchAndVerifyResultTrue(
3100 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3101 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3104 auto M = expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr()));
3105 EXPECT_TRUE(matchAndVerifyResultTrue(
3106 Code, traverse(TK_AsIs, M),
3107 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3108 EXPECT_TRUE(matchAndVerifyResultTrue(
3109 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3110 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3113 auto M = expr(integerLiteral(equals(42)).bind("intLit"), expr());
3114 EXPECT_TRUE(matchAndVerifyResultTrue(
3115 Code, traverse(TK_AsIs, M),
3116 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3117 EXPECT_TRUE(matchAndVerifyResultTrue(
3118 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3119 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3122 auto M = expr(optionally(integerLiteral(equals(42)).bind("intLit")));
3123 EXPECT_TRUE(matchAndVerifyResultTrue(
3124 Code, traverse(TK_AsIs, M),
3125 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3126 EXPECT_TRUE(matchAndVerifyResultTrue(
3127 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3128 std::make_unique<VerifyIdIsBoundTo<Expr>>("intLit", 1)));
3131 auto M = expr().bind("allExprs");
3132 EXPECT_TRUE(matchAndVerifyResultTrue(
3133 Code, traverse(TK_AsIs, M),
3134 std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 6),
3135 {"-std=c++11"}));
3136 EXPECT_TRUE(matchAndVerifyResultTrue(
3137 Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3138 std::make_unique<VerifyIdIsBoundTo<Expr>>("allExprs", 1)));
3141 Code = R"cpp(
3142 void foo()
3144 int arr[3];
3145 auto &[f, s, t] = arr;
3147 f = 42;
3149 )cpp";
3151 auto M = bindingDecl(hasName("f"));
3152 EXPECT_TRUE(
3153 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));
3154 EXPECT_TRUE(
3155 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3156 true, {"-std=c++17"}));
3159 auto M = bindingDecl(hasName("f"), has(expr()));
3160 EXPECT_TRUE(
3161 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));
3162 EXPECT_FALSE(
3163 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3164 true, {"-std=c++17"}));
3167 auto M = integerLiteral(hasAncestor(bindingDecl(hasName("f"))));
3168 EXPECT_TRUE(
3169 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));
3170 EXPECT_FALSE(
3171 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3172 true, {"-std=c++17"}));
3175 auto M = declRefExpr(hasAncestor(bindingDecl(hasName("f"))));
3176 EXPECT_TRUE(
3177 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++17"}));
3178 EXPECT_FALSE(
3179 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3180 true, {"-std=c++17"}));
3184 TEST(Traversal, traverseNoImplicit) {
3185 StringRef Code = R"cpp(
3186 struct NonTrivial {
3187 NonTrivial() {}
3188 NonTrivial(const NonTrivial&) {}
3189 NonTrivial& operator=(const NonTrivial&) { return *this; }
3191 ~NonTrivial() {}
3194 struct NoSpecialMethods {
3195 NonTrivial nt;
3198 struct ContainsArray {
3199 NonTrivial arr[2];
3200 ContainsArray& operator=(const ContainsArray &other) = default;
3203 void copyIt()
3205 NoSpecialMethods nc1;
3206 NoSpecialMethods nc2(nc1);
3207 nc2 = nc1;
3209 ContainsArray ca;
3210 ContainsArray ca2;
3211 ca2 = ca;
3214 struct HasCtorInits : NoSpecialMethods, NonTrivial
3216 int m_i;
3217 NonTrivial m_nt;
3218 HasCtorInits() : NoSpecialMethods(), m_i(42) {}
3221 struct CtorInitsNonTrivial : NonTrivial
3223 int m_i;
3224 NonTrivial m_nt;
3225 CtorInitsNonTrivial() : NonTrivial(), m_i(42) {}
3228 )cpp";
3230 auto M = cxxRecordDecl(hasName("NoSpecialMethods"),
3231 has(cxxRecordDecl(hasName("NoSpecialMethods"))));
3232 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3233 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3235 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3236 has(cxxConstructorDecl(isCopyConstructor())));
3237 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3238 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3240 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3241 has(cxxMethodDecl(isCopyAssignmentOperator())));
3242 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3243 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3245 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3246 has(cxxConstructorDecl(isDefaultConstructor())));
3247 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3248 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3250 M = cxxRecordDecl(hasName("NoSpecialMethods"), has(cxxDestructorDecl()));
3251 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3252 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3254 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3255 hasMethod(cxxConstructorDecl(isCopyConstructor())));
3256 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3257 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3259 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3260 hasMethod(cxxMethodDecl(isCopyAssignmentOperator())));
3261 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3262 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3264 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3265 hasMethod(cxxConstructorDecl(isDefaultConstructor())));
3266 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3267 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3269 M = cxxRecordDecl(hasName("NoSpecialMethods"),
3270 hasMethod(cxxDestructorDecl()));
3271 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3272 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3275 // Because the copy-assignment operator is not spelled in the
3276 // source (ie, isImplicit()), we don't match it
3277 auto M =
3278 cxxOperatorCallExpr(hasType(cxxRecordDecl(hasName("NoSpecialMethods"))),
3279 callee(cxxMethodDecl(isCopyAssignmentOperator())));
3280 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3281 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3284 // Compiler generates a forStmt to copy the array
3285 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, forStmt())));
3286 EXPECT_FALSE(
3287 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, forStmt())));
3290 // The defaulted method declaration can be matched, but not its
3291 // definition, in IgnoreUnlessSpelledInSource mode
3292 auto MDecl = cxxMethodDecl(ofClass(cxxRecordDecl(hasName("ContainsArray"))),
3293 isCopyAssignmentOperator(), isDefaulted());
3295 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDecl)));
3296 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDecl)));
3298 auto MDef = cxxMethodDecl(MDecl, has(compoundStmt()));
3300 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MDef)));
3301 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MDef)));
3303 auto MBody = cxxMethodDecl(MDecl, hasBody(compoundStmt()));
3305 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MBody)));
3306 EXPECT_FALSE(
3307 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MBody)));
3309 auto MIsDefn = cxxMethodDecl(MDecl, isDefinition());
3311 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MIsDefn)));
3312 EXPECT_TRUE(
3313 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsDefn)));
3315 auto MIsInline = cxxMethodDecl(MDecl, isInline());
3317 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, MIsInline)));
3318 EXPECT_FALSE(
3319 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MIsInline)));
3321 // The parameter of the defaulted method can still be matched.
3322 auto MParm =
3323 cxxMethodDecl(MDecl, hasParameter(0, parmVarDecl(hasName("other"))));
3325 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, MParm)));
3326 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, MParm)));
3329 auto M =
3330 cxxConstructorDecl(hasName("HasCtorInits"),
3331 has(cxxCtorInitializer(forField(hasName("m_i")))));
3332 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3333 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3336 auto M =
3337 cxxConstructorDecl(hasName("HasCtorInits"),
3338 has(cxxCtorInitializer(forField(hasName("m_nt")))));
3339 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3340 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3343 auto M = cxxConstructorDecl(hasName("HasCtorInits"),
3344 hasAnyConstructorInitializer(cxxCtorInitializer(
3345 forField(hasName("m_nt")))));
3346 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3347 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3350 auto M =
3351 cxxConstructorDecl(hasName("HasCtorInits"),
3352 forEachConstructorInitializer(
3353 cxxCtorInitializer(forField(hasName("m_nt")))));
3354 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3355 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3358 auto M = cxxConstructorDecl(
3359 hasName("CtorInitsNonTrivial"),
3360 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(
3361 hasDeclaration(cxxConstructorDecl(hasName("NonTrivial"))))))));
3362 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3363 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3366 auto M = cxxConstructorDecl(
3367 hasName("HasCtorInits"),
3368 has(cxxCtorInitializer(withInitializer(cxxConstructExpr(hasDeclaration(
3369 cxxConstructorDecl(hasName("NoSpecialMethods"))))))));
3370 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3371 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3374 auto M = cxxCtorInitializer(forField(hasName("m_nt")));
3375 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3376 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3379 Code = R"cpp(
3380 void rangeFor()
3382 int arr[2];
3383 for (auto i : arr)
3385 if (true)
3390 )cpp";
3392 auto M = cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3393 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3394 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3397 auto M =
3398 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3399 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3400 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3403 auto M =
3404 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3405 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3406 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3409 auto M = cxxForRangeStmt(has(declStmt()));
3410 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3411 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3414 auto M =
3415 cxxForRangeStmt(hasLoopVariable(varDecl(hasName("i"))),
3416 hasRangeInit(declRefExpr(to(varDecl(hasName("arr"))))));
3417 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3418 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3421 auto M = cxxForRangeStmt(unless(hasInitStatement(stmt())));
3422 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3423 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3426 auto M = cxxForRangeStmt(hasBody(stmt()));
3427 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3428 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3431 auto M = cxxForRangeStmt(hasDescendant(ifStmt()));
3432 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3433 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3436 EXPECT_TRUE(matches(
3437 Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(
3438 hasSingleDecl(varDecl(hasName("i")))))))));
3439 EXPECT_TRUE(
3440 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
3441 cxxForRangeStmt(has(varDecl(hasName("i")))))));
3444 EXPECT_TRUE(matches(
3445 Code, traverse(TK_AsIs, cxxForRangeStmt(has(declStmt(hasSingleDecl(
3446 varDecl(hasInitializer(declRefExpr(
3447 to(varDecl(hasName("arr")))))))))))));
3448 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
3449 cxxForRangeStmt(has(declRefExpr(
3450 to(varDecl(hasName("arr")))))))));
3453 auto M = cxxForRangeStmt(has(compoundStmt()));
3454 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3455 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3458 auto M = binaryOperator(hasOperatorName("!="));
3459 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3460 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3463 auto M = unaryOperator(hasOperatorName("++"));
3464 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3465 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3468 auto M = declStmt(hasSingleDecl(varDecl(matchesName("__range"))));
3469 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3470 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3473 auto M = declStmt(hasSingleDecl(varDecl(matchesName("__begin"))));
3474 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3475 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3478 auto M = declStmt(hasSingleDecl(varDecl(matchesName("__end"))));
3479 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3480 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3483 auto M = ifStmt(hasParent(compoundStmt(hasParent(cxxForRangeStmt()))));
3484 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3485 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3488 auto M = cxxForRangeStmt(
3489 has(varDecl(hasName("i"), hasParent(cxxForRangeStmt()))));
3490 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));
3491 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3494 auto M = cxxForRangeStmt(hasDescendant(varDecl(
3495 hasName("i"), hasParent(declStmt(hasParent(cxxForRangeStmt()))))));
3496 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3497 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3500 auto M = cxxForRangeStmt(hasRangeInit(declRefExpr(
3501 to(varDecl(hasName("arr"))), hasParent(cxxForRangeStmt()))));
3502 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));
3503 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3507 auto M = cxxForRangeStmt(hasRangeInit(declRefExpr(
3508 to(varDecl(hasName("arr"))), hasParent(varDecl(hasParent(declStmt(
3509 hasParent(cxxForRangeStmt()))))))));
3510 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3511 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3514 Code = R"cpp(
3515 struct Range {
3516 int* begin() const;
3517 int* end() const;
3519 Range getRange(int);
3521 void rangeFor()
3523 for (auto i : getRange(42))
3527 )cpp";
3529 auto M = integerLiteral(equals(42));
3530 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3531 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3534 auto M = callExpr(hasDescendant(integerLiteral(equals(42))));
3535 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3536 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3539 auto M = compoundStmt(hasDescendant(integerLiteral(equals(42))));
3540 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3541 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3544 Code = R"cpp(
3545 void rangeFor()
3547 int arr[2];
3548 for (auto& a = arr; auto i : a)
3553 )cpp";
3555 auto M = cxxForRangeStmt(has(binaryOperator(hasOperatorName("!="))));
3556 EXPECT_TRUE(
3557 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3558 EXPECT_FALSE(
3559 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3560 true, {"-std=c++20"}));
3563 auto M =
3564 cxxForRangeStmt(hasDescendant(binaryOperator(hasOperatorName("+"))));
3565 EXPECT_TRUE(
3566 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3567 EXPECT_FALSE(
3568 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3569 true, {"-std=c++20"}));
3572 auto M =
3573 cxxForRangeStmt(hasDescendant(unaryOperator(hasOperatorName("++"))));
3574 EXPECT_TRUE(
3575 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3576 EXPECT_FALSE(
3577 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3578 true, {"-std=c++20"}));
3581 auto M =
3582 cxxForRangeStmt(has(declStmt(hasSingleDecl(varDecl(hasName("i"))))));
3583 EXPECT_TRUE(
3584 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3585 EXPECT_FALSE(
3586 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3587 true, {"-std=c++20"}));
3590 auto M = cxxForRangeStmt(
3591 hasInitStatement(declStmt(hasSingleDecl(varDecl(
3592 hasName("a"),
3593 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3594 hasLoopVariable(varDecl(hasName("i"))),
3595 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3596 EXPECT_TRUE(
3597 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3598 EXPECT_TRUE(
3599 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3600 true, {"-std=c++20"}));
3603 auto M = cxxForRangeStmt(
3604 has(declStmt(hasSingleDecl(varDecl(
3605 hasName("a"),
3606 hasInitializer(declRefExpr(to(varDecl(hasName("arr"))))))))),
3607 hasLoopVariable(varDecl(hasName("i"))),
3608 hasRangeInit(declRefExpr(to(varDecl(hasName("a"))))));
3609 EXPECT_TRUE(
3610 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3611 EXPECT_TRUE(
3612 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3613 true, {"-std=c++20"}));
3616 auto M = cxxForRangeStmt(hasInitStatement(declStmt(
3617 hasSingleDecl(varDecl(hasName("a"))), hasParent(cxxForRangeStmt()))));
3618 EXPECT_TRUE(
3619 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3620 EXPECT_TRUE(
3621 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3622 true, {"-std=c++20"}));
3625 Code = R"cpp(
3626 struct Range {
3627 int* begin() const;
3628 int* end() const;
3630 Range getRange(int);
3632 int getNum(int);
3634 void rangeFor()
3636 for (auto j = getNum(42); auto i : getRange(j))
3640 )cpp";
3642 auto M = integerLiteral(equals(42));
3643 EXPECT_TRUE(
3644 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3645 EXPECT_TRUE(
3646 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3647 true, {"-std=c++20"}));
3650 auto M = compoundStmt(hasDescendant(integerLiteral(equals(42))));
3651 EXPECT_TRUE(
3652 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
3653 EXPECT_TRUE(
3654 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
3655 true, {"-std=c++20"}));
3658 Code = R"cpp(
3659 void hasDefaultArg(int i, int j = 0)
3662 void callDefaultArg()
3664 hasDefaultArg(42);
3666 )cpp";
3667 auto hasDefaultArgCall = [](auto InnerMatcher) {
3668 return callExpr(callee(functionDecl(hasName("hasDefaultArg"))),
3669 InnerMatcher);
3672 auto M = hasDefaultArgCall(has(integerLiteral(equals(42))));
3673 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3674 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3677 auto M = hasDefaultArgCall(has(cxxDefaultArgExpr()));
3678 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3679 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3682 auto M = hasDefaultArgCall(argumentCountIs(2));
3683 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3684 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3687 auto M = hasDefaultArgCall(argumentCountIs(1));
3688 EXPECT_FALSE(matches(Code, traverse(TK_AsIs, M)));
3689 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3692 auto M = hasDefaultArgCall(hasArgument(1, cxxDefaultArgExpr()));
3693 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3694 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3697 auto M = hasDefaultArgCall(hasAnyArgument(cxxDefaultArgExpr()));
3698 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3699 EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3701 Code = R"cpp(
3702 struct A
3704 ~A();
3705 private:
3706 int i;
3709 A::~A() = default;
3710 )cpp";
3712 auto M = cxxDestructorDecl(isDefaulted(),
3713 ofClass(cxxRecordDecl(has(fieldDecl()))));
3714 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M)));
3715 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M)));
3717 Code = R"cpp(
3718 struct S
3720 static constexpr bool getTrue() { return true; }
3723 struct A
3725 explicit(S::getTrue()) A();
3728 A::A() = default;
3729 )cpp";
3731 EXPECT_TRUE(matchesConditionally(
3732 Code,
3733 traverse(TK_AsIs,
3734 cxxConstructorDecl(
3735 isDefaulted(),
3736 hasExplicitSpecifier(expr(ignoringImplicit(
3737 callExpr(has(ignoringImplicit(declRefExpr())))))))),
3738 true, {"-std=c++20"}));
3739 EXPECT_TRUE(matchesConditionally(
3740 Code,
3741 traverse(TK_IgnoreUnlessSpelledInSource,
3742 cxxConstructorDecl(
3743 isDefaulted(),
3744 hasExplicitSpecifier(callExpr(has(declRefExpr()))))),
3745 true, {"-std=c++20"}));
3749 template <typename MatcherT>
3750 bool matcherTemplateWithBinding(StringRef Code, const MatcherT &M) {
3751 return matchAndVerifyResultTrue(
3752 Code, M.bind("matchedStmt"),
3753 std::make_unique<VerifyIdIsBoundTo<ReturnStmt>>("matchedStmt", 1));
3756 TEST(Traversal, traverseWithBinding) {
3757 // Some existing matcher code expects to take a matcher as a
3758 // template arg and bind to it. Verify that that works.
3760 llvm::StringRef Code = R"cpp(
3761 int foo()
3763 return 42.0;
3765 )cpp";
3766 EXPECT_TRUE(matcherTemplateWithBinding(
3767 Code, traverse(TK_AsIs,
3768 returnStmt(has(implicitCastExpr(has(floatLiteral())))))));
3771 TEST(Traversal, traverseMatcherNesting) {
3773 StringRef Code = R"cpp(
3774 float bar(int i)
3776 return i;
3779 void foo()
3781 bar(bar(3.0));
3783 )cpp";
3785 EXPECT_TRUE(
3786 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
3787 callExpr(has(callExpr(traverse(
3788 TK_AsIs, callExpr(has(implicitCastExpr(
3789 has(floatLiteral())))))))))));
3791 EXPECT_TRUE(matches(
3792 Code,
3793 traverse(TK_IgnoreUnlessSpelledInSource,
3794 traverse(TK_AsIs, implicitCastExpr(has(floatLiteral()))))));
3797 TEST(Traversal, traverseMatcherThroughImplicit) {
3798 StringRef Code = R"cpp(
3799 struct S {
3800 S(int x);
3803 void constructImplicit() {
3804 int a = 8;
3805 S s(a);
3807 )cpp";
3809 auto Matcher = traverse(TK_IgnoreUnlessSpelledInSource, implicitCastExpr());
3811 // Verfiy that it does not segfault
3812 EXPECT_FALSE(matches(Code, Matcher));
3815 TEST(Traversal, traverseMatcherThroughMemoization) {
3817 StringRef Code = R"cpp(
3818 void foo()
3820 int i = 3.0;
3822 )cpp";
3824 auto Matcher = varDecl(hasInitializer(floatLiteral()));
3826 // Matchers such as hasDescendant memoize their result regarding AST
3827 // nodes. In the matcher below, the first use of hasDescendant(Matcher)
3828 // fails, and the use of it inside the traverse() matcher should pass
3829 // causing the overall matcher to be a true match.
3830 // This test verifies that the first false result is not re-used, which
3831 // would cause the overall matcher to be incorrectly false.
3833 EXPECT_TRUE(matches(
3834 Code,
3835 functionDecl(anyOf(hasDescendant(Matcher),
3836 traverse(TK_IgnoreUnlessSpelledInSource,
3837 functionDecl(hasDescendant(Matcher)))))));
3840 TEST(Traversal, traverseUnlessSpelledInSource) {
3842 StringRef Code = R"cpp(
3844 struct A
3848 struct B
3850 B(int);
3851 B(A const& a);
3852 B();
3855 struct C
3857 operator B();
3860 B func1() {
3861 return 42;
3864 B func2() {
3865 return B{42};
3868 B func3() {
3869 return B(42);
3872 B func4() {
3873 return B();
3876 B func5() {
3877 return B{};
3880 B func6() {
3881 return C();
3884 B func7() {
3885 return A();
3888 B func8() {
3889 return C{};
3892 B func9() {
3893 return A{};
3896 B func10() {
3897 A a;
3898 return a;
3901 B func11() {
3902 B b;
3903 return b;
3906 B func12() {
3907 C c;
3908 return c;
3911 void func13() {
3912 int a = 0;
3913 int c = 0;
3915 [a, b = c](int d) { int e = d; };
3918 void func14() {
3919 [] <typename TemplateType> (TemplateType t, TemplateType u) { int e = t + u; };
3920 float i = 42.0;
3923 void func15() {
3924 int count = 0;
3925 auto l = [&] { ++count; };
3926 (void)l;
3929 )cpp";
3931 EXPECT_TRUE(
3932 matches(Code,
3933 traverse(TK_IgnoreUnlessSpelledInSource,
3934 returnStmt(forFunction(functionDecl(hasName("func1"))),
3935 hasReturnValue(integerLiteral(equals(42))))),
3936 langCxx20OrLater()));
3938 EXPECT_TRUE(
3939 matches(Code,
3940 traverse(TK_IgnoreUnlessSpelledInSource,
3941 integerLiteral(equals(42),
3942 hasParent(returnStmt(forFunction(
3943 functionDecl(hasName("func1"))))))),
3944 langCxx20OrLater()));
3946 EXPECT_TRUE(matches(
3947 Code,
3948 traverse(TK_IgnoreUnlessSpelledInSource,
3949 returnStmt(forFunction(functionDecl(hasName("func2"))),
3950 hasReturnValue(cxxTemporaryObjectExpr(
3951 hasArgument(0, integerLiteral(equals(42))))))),
3952 langCxx20OrLater()));
3953 EXPECT_TRUE(matches(
3954 Code,
3955 traverse(
3956 TK_IgnoreUnlessSpelledInSource,
3957 integerLiteral(equals(42),
3958 hasParent(cxxTemporaryObjectExpr(hasParent(returnStmt(
3959 forFunction(functionDecl(hasName("func2"))))))))),
3960 langCxx20OrLater()));
3962 EXPECT_TRUE(
3963 matches(Code,
3964 traverse(TK_IgnoreUnlessSpelledInSource,
3965 returnStmt(forFunction(functionDecl(hasName("func3"))),
3966 hasReturnValue(cxxConstructExpr(hasArgument(
3967 0, integerLiteral(equals(42))))))),
3968 langCxx20OrLater()));
3970 EXPECT_TRUE(matches(
3971 Code,
3972 traverse(
3973 TK_IgnoreUnlessSpelledInSource,
3974 integerLiteral(equals(42),
3975 hasParent(cxxConstructExpr(hasParent(returnStmt(
3976 forFunction(functionDecl(hasName("func3"))))))))),
3977 langCxx20OrLater()));
3979 EXPECT_TRUE(
3980 matches(Code,
3981 traverse(TK_IgnoreUnlessSpelledInSource,
3982 returnStmt(forFunction(functionDecl(hasName("func4"))),
3983 hasReturnValue(cxxTemporaryObjectExpr()))),
3984 langCxx20OrLater()));
3986 EXPECT_TRUE(
3987 matches(Code,
3988 traverse(TK_IgnoreUnlessSpelledInSource,
3989 returnStmt(forFunction(functionDecl(hasName("func5"))),
3990 hasReturnValue(cxxTemporaryObjectExpr()))),
3991 langCxx20OrLater()));
3993 EXPECT_TRUE(
3994 matches(Code,
3995 traverse(TK_IgnoreUnlessSpelledInSource,
3996 returnStmt(forFunction(functionDecl(hasName("func6"))),
3997 hasReturnValue(cxxTemporaryObjectExpr()))),
3998 langCxx20OrLater()));
4000 EXPECT_TRUE(
4001 matches(Code,
4002 traverse(TK_IgnoreUnlessSpelledInSource,
4003 returnStmt(forFunction(functionDecl(hasName("func7"))),
4004 hasReturnValue(cxxTemporaryObjectExpr()))),
4005 langCxx20OrLater()));
4007 EXPECT_TRUE(
4008 matches(Code,
4009 traverse(TK_IgnoreUnlessSpelledInSource,
4010 returnStmt(forFunction(functionDecl(hasName("func8"))),
4011 hasReturnValue(cxxFunctionalCastExpr(
4012 hasSourceExpression(initListExpr()))))),
4013 langCxx20OrLater()));
4015 EXPECT_TRUE(
4016 matches(Code,
4017 traverse(TK_IgnoreUnlessSpelledInSource,
4018 returnStmt(forFunction(functionDecl(hasName("func9"))),
4019 hasReturnValue(cxxFunctionalCastExpr(
4020 hasSourceExpression(initListExpr()))))),
4021 langCxx20OrLater()));
4023 EXPECT_TRUE(matches(
4024 Code,
4025 traverse(
4026 TK_IgnoreUnlessSpelledInSource,
4027 returnStmt(forFunction(functionDecl(hasName("func10"))),
4028 hasReturnValue(declRefExpr(to(varDecl(hasName("a"))))))),
4029 langCxx20OrLater()));
4031 EXPECT_TRUE(
4032 matches(Code,
4033 traverse(TK_IgnoreUnlessSpelledInSource,
4034 declRefExpr(to(varDecl(hasName("a"))),
4035 hasParent(returnStmt(forFunction(
4036 functionDecl(hasName("func10"))))))),
4037 langCxx20OrLater()));
4039 EXPECT_TRUE(matches(
4040 Code,
4041 traverse(
4042 TK_IgnoreUnlessSpelledInSource,
4043 returnStmt(forFunction(functionDecl(hasName("func11"))),
4044 hasReturnValue(declRefExpr(to(varDecl(hasName("b"))))))),
4045 langCxx20OrLater()));
4047 EXPECT_TRUE(
4048 matches(Code,
4049 traverse(TK_IgnoreUnlessSpelledInSource,
4050 declRefExpr(to(varDecl(hasName("b"))),
4051 hasParent(returnStmt(forFunction(
4052 functionDecl(hasName("func11"))))))),
4053 langCxx20OrLater()));
4055 EXPECT_TRUE(matches(
4056 Code,
4057 traverse(
4058 TK_IgnoreUnlessSpelledInSource,
4059 returnStmt(forFunction(functionDecl(hasName("func12"))),
4060 hasReturnValue(declRefExpr(to(varDecl(hasName("c"))))))),
4061 langCxx20OrLater()));
4063 EXPECT_TRUE(
4064 matches(Code,
4065 traverse(TK_IgnoreUnlessSpelledInSource,
4066 declRefExpr(to(varDecl(hasName("c"))),
4067 hasParent(returnStmt(forFunction(
4068 functionDecl(hasName("func12"))))))),
4069 langCxx20OrLater()));
4071 EXPECT_TRUE(matches(
4072 Code,
4073 traverse(
4074 TK_IgnoreUnlessSpelledInSource,
4075 lambdaExpr(forFunction(functionDecl(hasName("func13"))),
4076 has(compoundStmt(hasDescendant(varDecl(hasName("e"))))),
4077 has(declRefExpr(to(varDecl(hasName("a"))))),
4078 has(varDecl(hasName("b"), hasInitializer(declRefExpr(to(
4079 varDecl(hasName("c"))))))),
4080 has(parmVarDecl(hasName("d"))))),
4081 langCxx20OrLater()));
4083 EXPECT_TRUE(
4084 matches(Code,
4085 traverse(TK_IgnoreUnlessSpelledInSource,
4086 declRefExpr(to(varDecl(hasName("a"))),
4087 hasParent(lambdaExpr(forFunction(
4088 functionDecl(hasName("func13"))))))),
4089 langCxx20OrLater()));
4091 EXPECT_TRUE(matches(
4092 Code,
4093 traverse(TK_IgnoreUnlessSpelledInSource,
4094 varDecl(hasName("b"),
4095 hasInitializer(declRefExpr(to(varDecl(hasName("c"))))),
4096 hasParent(lambdaExpr(
4097 forFunction(functionDecl(hasName("func13"))))))),
4098 langCxx20OrLater()));
4100 EXPECT_TRUE(matches(Code,
4101 traverse(TK_IgnoreUnlessSpelledInSource,
4102 compoundStmt(hasParent(lambdaExpr(forFunction(
4103 functionDecl(hasName("func13"))))))),
4104 langCxx20OrLater()));
4106 EXPECT_TRUE(matches(
4107 Code,
4108 traverse(TK_IgnoreUnlessSpelledInSource,
4109 templateTypeParmDecl(hasName("TemplateType"),
4110 hasParent(lambdaExpr(forFunction(
4111 functionDecl(hasName("func14"))))))),
4112 langCxx20OrLater()));
4114 EXPECT_TRUE(matches(
4115 Code,
4116 traverse(TK_IgnoreUnlessSpelledInSource,
4117 lambdaExpr(forFunction(functionDecl(hasName("func14"))),
4118 has(templateTypeParmDecl(hasName("TemplateType"))))),
4119 langCxx20OrLater()));
4121 EXPECT_TRUE(matches(
4122 Code,
4123 traverse(TK_IgnoreUnlessSpelledInSource,
4124 functionDecl(hasName("func14"), hasDescendant(floatLiteral()))),
4125 langCxx20OrLater()));
4127 EXPECT_TRUE(matches(
4128 Code,
4129 traverse(TK_IgnoreUnlessSpelledInSource,
4130 compoundStmt(
4131 hasDescendant(varDecl(hasName("count")).bind("countVar")),
4132 hasDescendant(
4133 declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))),
4134 langCxx20OrLater()));
4136 Code = R"cpp(
4137 void foo() {
4138 int explicit_captured = 0;
4139 int implicit_captured = 0;
4140 auto l = [&, explicit_captured](int i) {
4141 if (i || explicit_captured || implicit_captured) return;
4144 )cpp";
4146 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, ifStmt())));
4147 EXPECT_TRUE(
4148 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, ifStmt())));
4150 auto lambdaExplicitCapture = declRefExpr(
4151 to(varDecl(hasName("explicit_captured"))), unless(hasAncestor(ifStmt())));
4152 auto lambdaImplicitCapture = declRefExpr(
4153 to(varDecl(hasName("implicit_captured"))), unless(hasAncestor(ifStmt())));
4155 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaExplicitCapture)));
4156 EXPECT_TRUE(matches(
4157 Code, traverse(TK_IgnoreUnlessSpelledInSource, lambdaExplicitCapture)));
4159 EXPECT_TRUE(matches(Code, traverse(TK_AsIs, lambdaImplicitCapture)));
4160 EXPECT_FALSE(matches(
4161 Code, traverse(TK_IgnoreUnlessSpelledInSource, lambdaImplicitCapture)));
4163 Code = R"cpp(
4164 struct S {};
4166 struct HasOpEq
4168 bool operator==(const S& other)
4170 return true;
4174 void binop()
4176 HasOpEq s1;
4177 S s2;
4178 if (s1 != s2)
4179 return;
4181 )cpp";
4183 auto M = unaryOperator(
4184 hasOperatorName("!"),
4185 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="))));
4186 EXPECT_TRUE(
4187 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4188 EXPECT_FALSE(
4189 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4190 true, {"-std=c++20"}));
4193 auto M = declRefExpr(to(varDecl(hasName("s1"))));
4194 EXPECT_TRUE(
4195 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4196 EXPECT_TRUE(
4197 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4198 true, {"-std=c++20"}));
4201 auto M = cxxOperatorCallExpr(hasOverloadedOperatorName("=="));
4202 EXPECT_TRUE(
4203 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4204 EXPECT_FALSE(
4205 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4206 true, {"-std=c++20"}));
4209 auto M = cxxOperatorCallExpr(hasOverloadedOperatorName("!="));
4210 EXPECT_FALSE(
4211 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4212 EXPECT_FALSE(
4213 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4214 true, {"-std=c++20"}));
4216 auto withDescendants = [](StringRef lName, StringRef rName) {
4217 return stmt(hasDescendant(declRefExpr(to(varDecl(hasName(lName))))),
4218 hasDescendant(declRefExpr(to(varDecl(hasName(rName))))));
4221 auto M = cxxRewrittenBinaryOperator(withDescendants("s1", "s2"));
4222 EXPECT_TRUE(
4223 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4224 EXPECT_TRUE(
4225 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4226 true, {"-std=c++20"}));
4229 auto M = cxxRewrittenBinaryOperator(
4230 has(declRefExpr(to(varDecl(hasName("s1"))))),
4231 has(declRefExpr(to(varDecl(hasName("s2"))))));
4232 EXPECT_FALSE(
4233 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4234 EXPECT_TRUE(
4235 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4236 true, {"-std=c++20"}));
4239 auto M = cxxRewrittenBinaryOperator(
4240 hasLHS(expr(hasParent(cxxRewrittenBinaryOperator()))),
4241 hasRHS(expr(hasParent(cxxRewrittenBinaryOperator()))));
4242 EXPECT_FALSE(
4243 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4244 EXPECT_TRUE(
4245 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4246 true, {"-std=c++20"}));
4249 EXPECT_TRUE(matchesConditionally(
4250 Code,
4251 traverse(TK_AsIs,
4252 cxxRewrittenBinaryOperator(
4253 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4254 isComparisonOperator(),
4255 hasLHS(ignoringImplicit(
4256 declRefExpr(to(varDecl(hasName("s1")))))),
4257 hasRHS(ignoringImplicit(
4258 declRefExpr(to(varDecl(hasName("s2")))))),
4259 hasEitherOperand(ignoringImplicit(
4260 declRefExpr(to(varDecl(hasName("s2")))))),
4261 hasOperands(ignoringImplicit(
4262 declRefExpr(to(varDecl(hasName("s1"))))),
4263 ignoringImplicit(declRefExpr(
4264 to(varDecl(hasName("s2")))))))),
4265 true, {"-std=c++20"}));
4266 EXPECT_TRUE(matchesConditionally(
4267 Code,
4268 traverse(TK_IgnoreUnlessSpelledInSource,
4269 cxxRewrittenBinaryOperator(
4270 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4271 isComparisonOperator(),
4272 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4273 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4274 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4275 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4276 declRefExpr(to(varDecl(hasName("s2"))))))),
4277 true, {"-std=c++20"}));
4280 Code = R"cpp(
4281 namespace std {
4282 struct strong_ordering {
4283 int n;
4284 constexpr operator int() const { return n; }
4285 static const strong_ordering equal, greater, less;
4287 constexpr strong_ordering strong_ordering::equal = {0};
4288 constexpr strong_ordering strong_ordering::greater = {1};
4289 constexpr strong_ordering strong_ordering::less = {-1};
4292 struct HasSpaceshipMem {
4293 int a;
4294 constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
4297 void binop()
4299 HasSpaceshipMem hs1, hs2;
4300 if (hs1 == hs2)
4301 return;
4303 HasSpaceshipMem hs3, hs4;
4304 if (hs3 != hs4)
4305 return;
4307 HasSpaceshipMem hs5, hs6;
4308 if (hs5 < hs6)
4309 return;
4311 HasSpaceshipMem hs7, hs8;
4312 if (hs7 > hs8)
4313 return;
4315 HasSpaceshipMem hs9, hs10;
4316 if (hs9 <= hs10)
4317 return;
4319 HasSpaceshipMem hs11, hs12;
4320 if (hs11 >= hs12)
4321 return;
4323 )cpp";
4324 auto withArgs = [](StringRef lName, StringRef rName) {
4325 return cxxOperatorCallExpr(
4326 hasArgument(0, declRefExpr(to(varDecl(hasName(lName))))),
4327 hasArgument(1, declRefExpr(to(varDecl(hasName(rName))))));
4330 auto M = ifStmt(hasCondition(cxxOperatorCallExpr(
4331 hasOverloadedOperatorName("=="), withArgs("hs1", "hs2"))));
4332 EXPECT_TRUE(
4333 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4334 EXPECT_TRUE(
4335 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4336 true, {"-std=c++20"}));
4339 auto M =
4340 unaryOperator(hasOperatorName("!"),
4341 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4342 withArgs("hs3", "hs4"))));
4343 EXPECT_TRUE(
4344 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4345 EXPECT_FALSE(
4346 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4347 true, {"-std=c++20"}));
4350 auto M =
4351 unaryOperator(hasOperatorName("!"),
4352 has(cxxOperatorCallExpr(hasOverloadedOperatorName("=="),
4353 withArgs("hs3", "hs4"))));
4354 EXPECT_TRUE(
4355 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4356 EXPECT_FALSE(
4357 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4358 true, {"-std=c++20"}));
4361 auto M = binaryOperator(
4362 hasOperatorName("<"),
4363 hasLHS(hasDescendant(cxxOperatorCallExpr(
4364 hasOverloadedOperatorName("<=>"), withArgs("hs5", "hs6")))),
4365 hasRHS(integerLiteral(equals(0))));
4366 EXPECT_TRUE(
4367 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4368 EXPECT_FALSE(
4369 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4370 true, {"-std=c++20"}));
4373 auto M = cxxRewrittenBinaryOperator(withDescendants("hs3", "hs4"));
4374 EXPECT_TRUE(
4375 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4376 EXPECT_TRUE(
4377 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4378 true, {"-std=c++20"}));
4381 auto M = declRefExpr(to(varDecl(hasName("hs3"))));
4382 EXPECT_TRUE(
4383 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4384 EXPECT_TRUE(
4385 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4386 true, {"-std=c++20"}));
4389 auto M = cxxRewrittenBinaryOperator(has(
4390 unaryOperator(hasOperatorName("!"), withDescendants("hs3", "hs4"))));
4391 EXPECT_TRUE(
4392 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4393 EXPECT_FALSE(
4394 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4395 true, {"-std=c++20"}));
4398 auto M = cxxRewrittenBinaryOperator(
4399 has(declRefExpr(to(varDecl(hasName("hs3"))))),
4400 has(declRefExpr(to(varDecl(hasName("hs4"))))));
4401 EXPECT_FALSE(
4402 matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"}));
4403 EXPECT_TRUE(
4404 matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M),
4405 true, {"-std=c++20"}));
4408 EXPECT_TRUE(matchesConditionally(
4409 Code,
4410 traverse(TK_AsIs,
4411 cxxRewrittenBinaryOperator(
4412 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4413 isComparisonOperator(),
4414 hasLHS(ignoringImplicit(
4415 declRefExpr(to(varDecl(hasName("hs3")))))),
4416 hasRHS(ignoringImplicit(
4417 declRefExpr(to(varDecl(hasName("hs4")))))),
4418 hasEitherOperand(ignoringImplicit(
4419 declRefExpr(to(varDecl(hasName("hs3")))))),
4420 hasOperands(ignoringImplicit(
4421 declRefExpr(to(varDecl(hasName("hs3"))))),
4422 ignoringImplicit(declRefExpr(
4423 to(varDecl(hasName("hs4")))))))),
4424 true, {"-std=c++20"}));
4425 EXPECT_TRUE(matchesConditionally(
4426 Code,
4427 traverse(TK_IgnoreUnlessSpelledInSource,
4428 cxxRewrittenBinaryOperator(
4429 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4430 isComparisonOperator(),
4431 hasLHS(declRefExpr(to(varDecl(hasName("hs3"))))),
4432 hasRHS(declRefExpr(to(varDecl(hasName("hs4"))))),
4433 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs3"))))),
4434 hasOperands(declRefExpr(to(varDecl(hasName("hs3")))),
4435 declRefExpr(to(varDecl(hasName("hs4"))))))),
4436 true, {"-std=c++20"}));
4439 EXPECT_TRUE(matchesConditionally(
4440 Code,
4441 traverse(TK_AsIs,
4442 cxxRewrittenBinaryOperator(
4443 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4444 isComparisonOperator(),
4445 hasLHS(ignoringImplicit(
4446 declRefExpr(to(varDecl(hasName("hs5")))))),
4447 hasRHS(ignoringImplicit(
4448 declRefExpr(to(varDecl(hasName("hs6")))))),
4449 hasEitherOperand(ignoringImplicit(
4450 declRefExpr(to(varDecl(hasName("hs5")))))),
4451 hasOperands(ignoringImplicit(
4452 declRefExpr(to(varDecl(hasName("hs5"))))),
4453 ignoringImplicit(declRefExpr(
4454 to(varDecl(hasName("hs6")))))))),
4455 true, {"-std=c++20"}));
4456 EXPECT_TRUE(matchesConditionally(
4457 Code,
4458 traverse(TK_IgnoreUnlessSpelledInSource,
4459 cxxRewrittenBinaryOperator(
4460 hasOperatorName("<"), hasAnyOperatorName("<", "!="),
4461 isComparisonOperator(),
4462 hasLHS(declRefExpr(to(varDecl(hasName("hs5"))))),
4463 hasRHS(declRefExpr(to(varDecl(hasName("hs6"))))),
4464 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs5"))))),
4465 hasOperands(declRefExpr(to(varDecl(hasName("hs5")))),
4466 declRefExpr(to(varDecl(hasName("hs6"))))))),
4467 true, {"-std=c++20"}));
4470 EXPECT_TRUE(matchesConditionally(
4471 Code,
4472 traverse(TK_AsIs,
4473 cxxRewrittenBinaryOperator(
4474 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4475 isComparisonOperator(),
4476 hasLHS(ignoringImplicit(
4477 declRefExpr(to(varDecl(hasName("hs7")))))),
4478 hasRHS(ignoringImplicit(
4479 declRefExpr(to(varDecl(hasName("hs8")))))),
4480 hasEitherOperand(ignoringImplicit(
4481 declRefExpr(to(varDecl(hasName("hs7")))))),
4482 hasOperands(ignoringImplicit(
4483 declRefExpr(to(varDecl(hasName("hs7"))))),
4484 ignoringImplicit(declRefExpr(
4485 to(varDecl(hasName("hs8")))))))),
4486 true, {"-std=c++20"}));
4487 EXPECT_TRUE(matchesConditionally(
4488 Code,
4489 traverse(TK_IgnoreUnlessSpelledInSource,
4490 cxxRewrittenBinaryOperator(
4491 hasOperatorName(">"), hasAnyOperatorName("<", ">"),
4492 isComparisonOperator(),
4493 hasLHS(declRefExpr(to(varDecl(hasName("hs7"))))),
4494 hasRHS(declRefExpr(to(varDecl(hasName("hs8"))))),
4495 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs7"))))),
4496 hasOperands(declRefExpr(to(varDecl(hasName("hs7")))),
4497 declRefExpr(to(varDecl(hasName("hs8"))))))),
4498 true, {"-std=c++20"}));
4501 EXPECT_TRUE(matchesConditionally(
4502 Code,
4503 traverse(TK_AsIs,
4504 cxxRewrittenBinaryOperator(
4505 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4506 isComparisonOperator(),
4507 hasLHS(ignoringImplicit(
4508 declRefExpr(to(varDecl(hasName("hs9")))))),
4509 hasRHS(ignoringImplicit(
4510 declRefExpr(to(varDecl(hasName("hs10")))))),
4511 hasEitherOperand(ignoringImplicit(
4512 declRefExpr(to(varDecl(hasName("hs9")))))),
4513 hasOperands(ignoringImplicit(
4514 declRefExpr(to(varDecl(hasName("hs9"))))),
4515 ignoringImplicit(declRefExpr(
4516 to(varDecl(hasName("hs10")))))))),
4517 true, {"-std=c++20"}));
4518 EXPECT_TRUE(matchesConditionally(
4519 Code,
4520 traverse(TK_IgnoreUnlessSpelledInSource,
4521 cxxRewrittenBinaryOperator(
4522 hasOperatorName("<="), hasAnyOperatorName("<", "<="),
4523 isComparisonOperator(),
4524 hasLHS(declRefExpr(to(varDecl(hasName("hs9"))))),
4525 hasRHS(declRefExpr(to(varDecl(hasName("hs10"))))),
4526 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs9"))))),
4527 hasOperands(declRefExpr(to(varDecl(hasName("hs9")))),
4528 declRefExpr(to(varDecl(hasName("hs10"))))))),
4529 true, {"-std=c++20"}));
4532 EXPECT_TRUE(matchesConditionally(
4533 Code,
4534 traverse(TK_AsIs,
4535 cxxRewrittenBinaryOperator(
4536 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4537 isComparisonOperator(),
4538 hasLHS(ignoringImplicit(
4539 declRefExpr(to(varDecl(hasName("hs11")))))),
4540 hasRHS(ignoringImplicit(
4541 declRefExpr(to(varDecl(hasName("hs12")))))),
4542 hasEitherOperand(ignoringImplicit(
4543 declRefExpr(to(varDecl(hasName("hs11")))))),
4544 hasOperands(ignoringImplicit(
4545 declRefExpr(to(varDecl(hasName("hs11"))))),
4546 ignoringImplicit(declRefExpr(
4547 to(varDecl(hasName("hs12")))))))),
4548 true, {"-std=c++20"}));
4549 EXPECT_TRUE(matchesConditionally(
4550 Code,
4551 traverse(
4552 TK_IgnoreUnlessSpelledInSource,
4553 cxxRewrittenBinaryOperator(
4554 hasOperatorName(">="), hasAnyOperatorName("<", ">="),
4555 isComparisonOperator(),
4556 hasLHS(declRefExpr(to(varDecl(hasName("hs11"))))),
4557 hasRHS(declRefExpr(to(varDecl(hasName("hs12"))))),
4558 hasEitherOperand(declRefExpr(to(varDecl(hasName("hs11"))))),
4559 hasOperands(declRefExpr(to(varDecl(hasName("hs11")))),
4560 declRefExpr(to(varDecl(hasName("hs12"))))))),
4561 true, {"-std=c++20"}));
4564 Code = R"cpp(
4565 struct S {};
4567 struct HasOpEq
4569 bool operator==(const S& other) const
4571 return true;
4575 struct HasOpEqMem {
4576 bool operator==(const HasOpEqMem&) const { return true; }
4579 struct HasOpEqFree {
4581 bool operator==(const HasOpEqFree&, const HasOpEqFree&) { return true; }
4583 void binop()
4586 HasOpEq s1;
4587 S s2;
4588 if (s1 != s2)
4589 return;
4593 int i1;
4594 int i2;
4595 if (i1 != i2)
4596 return;
4600 HasOpEqMem M1;
4601 HasOpEqMem M2;
4602 if (M1 == M2)
4603 return;
4607 HasOpEqFree F1;
4608 HasOpEqFree F2;
4609 if (F1 == F2)
4610 return;
4613 )cpp";
4615 EXPECT_TRUE(matchesConditionally(
4616 Code,
4617 traverse(TK_AsIs,
4618 binaryOperation(
4619 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4620 isComparisonOperator(),
4621 hasLHS(ignoringImplicit(
4622 declRefExpr(to(varDecl(hasName("s1")))))),
4623 hasRHS(ignoringImplicit(
4624 declRefExpr(to(varDecl(hasName("s2")))))),
4625 hasEitherOperand(ignoringImplicit(
4626 declRefExpr(to(varDecl(hasName("s2")))))),
4627 hasOperands(ignoringImplicit(
4628 declRefExpr(to(varDecl(hasName("s1"))))),
4629 ignoringImplicit(declRefExpr(
4630 to(varDecl(hasName("s2")))))))),
4631 true, {"-std=c++20"}));
4632 EXPECT_TRUE(matchesConditionally(
4633 Code,
4634 traverse(TK_AsIs, binaryOperation(hasOperatorName("!="),
4635 hasLHS(ignoringImplicit(declRefExpr(
4636 to(varDecl(hasName("i1")))))),
4637 hasRHS(ignoringImplicit(declRefExpr(
4638 to(varDecl(hasName("i2")))))))),
4639 true, {"-std=c++20"}));
4640 EXPECT_TRUE(matchesConditionally(
4641 Code,
4642 traverse(TK_AsIs, binaryOperation(hasOperatorName("=="),
4643 hasLHS(ignoringImplicit(declRefExpr(
4644 to(varDecl(hasName("M1")))))),
4645 hasRHS(ignoringImplicit(declRefExpr(
4646 to(varDecl(hasName("M2")))))))),
4647 true, {"-std=c++20"}));
4648 EXPECT_TRUE(matchesConditionally(
4649 Code,
4650 traverse(TK_AsIs, binaryOperation(hasOperatorName("=="),
4651 hasLHS(ignoringImplicit(declRefExpr(
4652 to(varDecl(hasName("F1")))))),
4653 hasRHS(ignoringImplicit(declRefExpr(
4654 to(varDecl(hasName("F2")))))))),
4655 true, {"-std=c++20"}));
4656 EXPECT_TRUE(matchesConditionally(
4657 Code,
4658 traverse(TK_IgnoreUnlessSpelledInSource,
4659 binaryOperation(
4660 hasOperatorName("!="), hasAnyOperatorName("<", "!="),
4661 isComparisonOperator(),
4662 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
4663 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))),
4664 hasEitherOperand(declRefExpr(to(varDecl(hasName("s2"))))),
4665 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
4666 declRefExpr(to(varDecl(hasName("s2"))))))),
4667 true, {"-std=c++20"}));
4668 EXPECT_TRUE(matchesConditionally(
4669 Code,
4670 traverse(
4671 TK_IgnoreUnlessSpelledInSource,
4672 binaryOperation(hasOperatorName("!="),
4673 hasLHS(declRefExpr(to(varDecl(hasName("i1"))))),
4674 hasRHS(declRefExpr(to(varDecl(hasName("i2"))))))),
4675 true, {"-std=c++20"}));
4676 EXPECT_TRUE(matchesConditionally(
4677 Code,
4678 traverse(
4679 TK_IgnoreUnlessSpelledInSource,
4680 binaryOperation(hasOperatorName("=="),
4681 hasLHS(declRefExpr(to(varDecl(hasName("M1"))))),
4682 hasRHS(declRefExpr(to(varDecl(hasName("M2"))))))),
4683 true, {"-std=c++20"}));
4684 EXPECT_TRUE(matchesConditionally(
4685 Code,
4686 traverse(
4687 TK_IgnoreUnlessSpelledInSource,
4688 binaryOperation(hasOperatorName("=="),
4689 hasLHS(declRefExpr(to(varDecl(hasName("F1"))))),
4690 hasRHS(declRefExpr(to(varDecl(hasName("F2"))))))),
4691 true, {"-std=c++20"}));
4695 TEST(IgnoringImpCasts, PathologicalLambda) {
4697 // Test that deeply nested lambdas are not a performance penalty
4698 StringRef Code = R"cpp(
4699 void f() {
4700 [] {
4701 [] {
4702 [] {
4703 [] {
4704 [] {
4705 [] {
4706 [] {
4707 [] {
4708 [] {
4709 [] {
4710 [] {
4711 [] {
4712 [] {
4713 [] {
4714 [] {
4715 [] {
4716 [] {
4717 [] {
4718 [] {
4719 [] {
4720 [] {
4721 [] {
4722 [] {
4723 [] {
4724 [] {
4725 [] {
4726 [] {
4727 [] {
4728 [] {
4729 int i = 42;
4730 (void)i;
4731 }();
4732 }();
4733 }();
4734 }();
4735 }();
4736 }();
4737 }();
4738 }();
4739 }();
4740 }();
4741 }();
4742 }();
4743 }();
4744 }();
4745 }();
4746 }();
4747 }();
4748 }();
4749 }();
4750 }();
4751 }();
4752 }();
4753 }();
4754 }();
4755 }();
4756 }();
4757 }();
4758 }();
4759 }();
4761 )cpp";
4763 EXPECT_TRUE(matches(Code, integerLiteral(equals(42))));
4764 EXPECT_TRUE(matches(Code, functionDecl(hasDescendant(integerLiteral(equals(42))))));
4767 TEST(IgnoringImpCasts, MatchesImpCasts) {
4768 // This test checks that ignoringImpCasts matches when implicit casts are
4769 // present and its inner matcher alone does not match.
4770 // Note that this test creates an implicit const cast.
4771 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4772 varDecl(hasInitializer(ignoringImpCasts(
4773 declRefExpr(to(varDecl(hasName("x")))))))));
4774 // This test creates an implict cast from int to char.
4775 EXPECT_TRUE(matches("char x = 0;",
4776 varDecl(hasInitializer(ignoringImpCasts(
4777 integerLiteral(equals(0)))))));
4780 TEST(IgnoringImpCasts, DoesNotMatchIncorrectly) {
4781 // These tests verify that ignoringImpCasts does not match if the inner
4782 // matcher does not match.
4783 // Note that the first test creates an implicit const cast.
4784 EXPECT_TRUE(notMatches("int x; const int y = x;",
4785 varDecl(hasInitializer(ignoringImpCasts(
4786 unless(anything()))))));
4787 EXPECT_TRUE(notMatches("int x; int y = x;",
4788 varDecl(hasInitializer(ignoringImpCasts(
4789 unless(anything()))))));
4791 // These tests verify that ignoringImplictCasts does not look through explicit
4792 // casts or parentheses.
4793 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4794 varDecl(hasInitializer(ignoringImpCasts(
4795 integerLiteral())))));
4796 EXPECT_TRUE(notMatches(
4797 "int i = (0);",
4798 traverse(TK_AsIs,
4799 varDecl(hasInitializer(ignoringImpCasts(integerLiteral()))))));
4800 EXPECT_TRUE(notMatches("float i = (float)0;",
4801 varDecl(hasInitializer(ignoringImpCasts(
4802 integerLiteral())))));
4803 EXPECT_TRUE(notMatches("float i = float(0);",
4804 varDecl(hasInitializer(ignoringImpCasts(
4805 integerLiteral())))));
4808 TEST(IgnoringImpCasts, MatchesWithoutImpCasts) {
4809 // This test verifies that expressions that do not have implicit casts
4810 // still match the inner matcher.
4811 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4812 varDecl(hasInitializer(ignoringImpCasts(
4813 declRefExpr(to(varDecl(hasName("x")))))))));
4816 TEST(IgnoringParenCasts, MatchesParenCasts) {
4817 // This test checks that ignoringParenCasts matches when parentheses and/or
4818 // casts are present and its inner matcher alone does not match.
4819 EXPECT_TRUE(matches("int x = (0);",
4820 varDecl(hasInitializer(ignoringParenCasts(
4821 integerLiteral(equals(0)))))));
4822 EXPECT_TRUE(matches("int x = (((((0)))));",
4823 varDecl(hasInitializer(ignoringParenCasts(
4824 integerLiteral(equals(0)))))));
4826 // This test creates an implict cast from int to char in addition to the
4827 // parentheses.
4828 EXPECT_TRUE(matches("char x = (0);",
4829 varDecl(hasInitializer(ignoringParenCasts(
4830 integerLiteral(equals(0)))))));
4832 EXPECT_TRUE(matches("char x = (char)0;",
4833 varDecl(hasInitializer(ignoringParenCasts(
4834 integerLiteral(equals(0)))))));
4835 EXPECT_TRUE(matches("char* p = static_cast<char*>(0);",
4836 varDecl(hasInitializer(ignoringParenCasts(
4837 integerLiteral(equals(0)))))));
4840 TEST(IgnoringParenCasts, MatchesWithoutParenCasts) {
4841 // This test verifies that expressions that do not have any casts still match.
4842 EXPECT_TRUE(matches("int x = 0;",
4843 varDecl(hasInitializer(ignoringParenCasts(
4844 integerLiteral(equals(0)))))));
4847 TEST(IgnoringParenCasts, DoesNotMatchIncorrectly) {
4848 // These tests verify that ignoringImpCasts does not match if the inner
4849 // matcher does not match.
4850 EXPECT_TRUE(notMatches("int x = ((0));",
4851 varDecl(hasInitializer(ignoringParenCasts(
4852 unless(anything()))))));
4854 // This test creates an implicit cast from int to char in addition to the
4855 // parentheses.
4856 EXPECT_TRUE(notMatches("char x = ((0));",
4857 varDecl(hasInitializer(ignoringParenCasts(
4858 unless(anything()))))));
4860 EXPECT_TRUE(notMatches("char *x = static_cast<char *>((0));",
4861 varDecl(hasInitializer(ignoringParenCasts(
4862 unless(anything()))))));
4865 TEST(IgnoringParenAndImpCasts, MatchesParenImpCasts) {
4866 // This test checks that ignoringParenAndImpCasts matches when
4867 // parentheses and/or implicit casts are present and its inner matcher alone
4868 // does not match.
4869 // Note that this test creates an implicit const cast.
4870 EXPECT_TRUE(matches("int x = 0; const int y = x;",
4871 varDecl(hasInitializer(ignoringParenImpCasts(
4872 declRefExpr(to(varDecl(hasName("x")))))))));
4873 // This test creates an implicit cast from int to char.
4874 EXPECT_TRUE(matches("const char x = (0);",
4875 varDecl(hasInitializer(ignoringParenImpCasts(
4876 integerLiteral(equals(0)))))));
4879 TEST(IgnoringParenAndImpCasts, MatchesWithoutParenImpCasts) {
4880 // This test verifies that expressions that do not have parentheses or
4881 // implicit casts still match.
4882 EXPECT_TRUE(matches("int x = 0; int &y = x;",
4883 varDecl(hasInitializer(ignoringParenImpCasts(
4884 declRefExpr(to(varDecl(hasName("x")))))))));
4885 EXPECT_TRUE(matches("int x = 0;",
4886 varDecl(hasInitializer(ignoringParenImpCasts(
4887 integerLiteral(equals(0)))))));
4890 TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {
4891 // These tests verify that ignoringParenImpCasts does not match if
4892 // the inner matcher does not match.
4893 // This test creates an implicit cast.
4894 EXPECT_TRUE(notMatches("char c = ((3));",
4895 varDecl(hasInitializer(ignoringParenImpCasts(
4896 unless(anything()))))));
4897 // These tests verify that ignoringParenAndImplictCasts does not look
4898 // through explicit casts.
4899 EXPECT_TRUE(notMatches("float y = (float(0));",
4900 varDecl(hasInitializer(ignoringParenImpCasts(
4901 integerLiteral())))));
4902 EXPECT_TRUE(notMatches("float y = (float)0;",
4903 varDecl(hasInitializer(ignoringParenImpCasts(
4904 integerLiteral())))));
4905 EXPECT_TRUE(notMatches("char* p = static_cast<char*>(0);",
4906 varDecl(hasInitializer(ignoringParenImpCasts(
4907 integerLiteral())))));
4910 TEST(HasSourceExpression, MatchesImplicitCasts) {
4911 EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
4912 "void r() {string a_string; URL url = a_string; }",
4913 traverse(TK_AsIs, implicitCastExpr(hasSourceExpression(
4914 cxxConstructExpr())))));
4917 TEST(HasSourceExpression, MatchesExplicitCasts) {
4918 EXPECT_TRUE(
4919 matches("float x = static_cast<float>(42);",
4920 traverse(TK_AsIs, explicitCastExpr(hasSourceExpression(
4921 hasDescendant(expr(integerLiteral())))))));
4924 TEST(UsingDeclaration, MatchesSpecificTarget) {
4925 EXPECT_TRUE(matches("namespace f { int a; void b(); } using f::b;",
4926 usingDecl(hasAnyUsingShadowDecl(
4927 hasTargetDecl(functionDecl())))));
4928 EXPECT_TRUE(notMatches("namespace f { int a; void b(); } using f::a;",
4929 usingDecl(hasAnyUsingShadowDecl(
4930 hasTargetDecl(functionDecl())))));
4933 TEST(UsingDeclaration, ThroughUsingDeclaration) {
4934 EXPECT_TRUE(matches(
4935 "namespace a { void f(); } using a::f; void g() { f(); }",
4936 declRefExpr(throughUsingDecl(anything()))));
4937 EXPECT_TRUE(notMatches(
4938 "namespace a { void f(); } using a::f; void g() { a::f(); }",
4939 declRefExpr(throughUsingDecl(anything()))));
4942 TEST(SingleDecl, IsSingleDecl) {
4943 StatementMatcher SingleDeclStmt =
4944 declStmt(hasSingleDecl(varDecl(hasInitializer(anything()))));
4945 EXPECT_TRUE(matches("void f() {int a = 4;}", SingleDeclStmt));
4946 EXPECT_TRUE(notMatches("void f() {int a;}", SingleDeclStmt));
4947 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4948 SingleDeclStmt));
4951 TEST(DeclStmt, ContainsDeclaration) {
4952 DeclarationMatcher MatchesInit = varDecl(hasInitializer(anything()));
4954 EXPECT_TRUE(matches("void f() {int a = 4;}",
4955 declStmt(containsDeclaration(0, MatchesInit))));
4956 EXPECT_TRUE(matches("void f() {int a = 4, b = 3;}",
4957 declStmt(containsDeclaration(0, MatchesInit),
4958 containsDeclaration(1, MatchesInit))));
4959 unsigned WrongIndex = 42;
4960 EXPECT_TRUE(notMatches("void f() {int a = 4, b = 3;}",
4961 declStmt(containsDeclaration(WrongIndex,
4962 MatchesInit))));
4965 TEST(SwitchCase, MatchesEachCase) {
4966 EXPECT_TRUE(notMatches("void x() { switch(42); }",
4967 switchStmt(forEachSwitchCase(caseStmt()))));
4968 EXPECT_TRUE(matches("void x() { switch(42) case 42:; }",
4969 switchStmt(forEachSwitchCase(caseStmt()))));
4970 EXPECT_TRUE(matches("void x() { switch(42) { case 42:; } }",
4971 switchStmt(forEachSwitchCase(caseStmt()))));
4972 EXPECT_TRUE(notMatches(
4973 "void x() { if (1) switch(42) { case 42: switch (42) { default:; } } }",
4974 ifStmt(has(switchStmt(forEachSwitchCase(defaultStmt()))))));
4975 EXPECT_TRUE(matches(
4976 "void x() { switch(42) { case 1+1: case 4:; } }",
4977 traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4978 constantExpr(has(integerLiteral())))))))));
4979 EXPECT_TRUE(notMatches(
4980 "void x() { switch(42) { case 1+1: case 2+2:; } }",
4981 traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4982 constantExpr(has(integerLiteral())))))))));
4983 EXPECT_TRUE(notMatches(
4984 "void x() { switch(42) { case 1 ... 2:; } }",
4985 traverse(TK_AsIs, switchStmt(forEachSwitchCase(caseStmt(hasCaseConstant(
4986 constantExpr(has(integerLiteral())))))))));
4987 EXPECT_TRUE(matchAndVerifyResultTrue(
4988 "void x() { switch (42) { case 1: case 2: case 3: default:; } }",
4989 switchStmt(forEachSwitchCase(caseStmt().bind("x"))),
4990 std::make_unique<VerifyIdIsBoundTo<CaseStmt>>("x", 3)));
4993 TEST(Declaration, HasExplicitSpecifier) {
4995 EXPECT_TRUE(notMatches("void f();",
4996 functionDecl(hasExplicitSpecifier(constantExpr())),
4997 langCxx20OrLater()));
4998 EXPECT_TRUE(
4999 notMatches("template<bool b> struct S { explicit operator int(); };",
5000 cxxConversionDecl(
5001 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
5002 langCxx20OrLater()));
5003 EXPECT_TRUE(
5004 notMatches("template<bool b> struct S { explicit(b) operator int(); };",
5005 cxxConversionDecl(
5006 hasExplicitSpecifier(constantExpr(has(cxxBoolLiteral())))),
5007 langCxx20OrLater()));
5008 EXPECT_TRUE(
5009 matches("struct S { explicit(true) operator int(); };",
5010 traverse(TK_AsIs, cxxConversionDecl(hasExplicitSpecifier(
5011 constantExpr(has(cxxBoolLiteral()))))),
5012 langCxx20OrLater()));
5013 EXPECT_TRUE(
5014 matches("struct S { explicit(false) operator int(); };",
5015 traverse(TK_AsIs, cxxConversionDecl(hasExplicitSpecifier(
5016 constantExpr(has(cxxBoolLiteral()))))),
5017 langCxx20OrLater()));
5018 EXPECT_TRUE(
5019 notMatches("template<bool b> struct S { explicit(b) S(int); };",
5020 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(
5021 constantExpr(has(cxxBoolLiteral()))))),
5022 langCxx20OrLater()));
5023 EXPECT_TRUE(
5024 matches("struct S { explicit(true) S(int); };",
5025 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(
5026 constantExpr(has(cxxBoolLiteral()))))),
5027 langCxx20OrLater()));
5028 EXPECT_TRUE(
5029 matches("struct S { explicit(false) S(int); };",
5030 traverse(TK_AsIs, cxxConstructorDecl(hasExplicitSpecifier(
5031 constantExpr(has(cxxBoolLiteral()))))),
5032 langCxx20OrLater()));
5033 EXPECT_TRUE(
5034 notMatches("template<typename T> struct S { S(int); };"
5035 "template<bool b = true> explicit(b) S(int) -> S<int>;",
5036 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(
5037 constantExpr(has(cxxBoolLiteral()))))),
5038 langCxx20OrLater()));
5039 EXPECT_TRUE(
5040 matches("template<typename T> struct S { S(int); };"
5041 "explicit(true) S(int) -> S<int>;",
5042 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(
5043 constantExpr(has(cxxBoolLiteral()))))),
5044 langCxx20OrLater()));
5045 EXPECT_TRUE(
5046 matches("template<typename T> struct S { S(int); };"
5047 "explicit(false) S(int) -> S<int>;",
5048 traverse(TK_AsIs, cxxDeductionGuideDecl(hasExplicitSpecifier(
5049 constantExpr(has(cxxBoolLiteral()))))),
5050 langCxx20OrLater()));
5053 TEST(ForEachConstructorInitializer, MatchesInitializers) {
5054 EXPECT_TRUE(matches(
5055 "struct X { X() : i(42), j(42) {} int i, j; };",
5056 cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer()))));
5059 TEST(LambdaCapture, InvalidLambdaCapture) {
5060 // not crash
5061 EXPECT_FALSE(matches(
5062 R"(int main() {
5063 struct A { A()=default; A(A const&)=delete; };
5064 A a; [a]() -> void {}();
5065 return 0;
5066 })",
5067 traverse(TK_IgnoreUnlessSpelledInSource,
5068 lambdaExpr(has(lambdaCapture()))),
5069 langCxx11OrLater()));
5072 TEST(ForEachLambdaCapture, MatchesCaptures) {
5073 EXPECT_TRUE(matches(
5074 "int main() { int x, y; auto f = [x, y]() { return x + y; }; }",
5075 lambdaExpr(forEachLambdaCapture(lambdaCapture())), langCxx11OrLater()));
5076 auto matcher = lambdaExpr(forEachLambdaCapture(
5077 lambdaCapture(capturesVar(varDecl(hasType(isInteger())))).bind("LC")));
5078 EXPECT_TRUE(matchAndVerifyResultTrue(
5079 "int main() { int x, y; float z; auto f = [=]() { return x + y + z; }; }",
5080 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));
5081 EXPECT_TRUE(matchAndVerifyResultTrue(
5082 "int main() { int x, y; float z; auto f = [x, y, z]() { return x + y + "
5083 "z; }; }",
5084 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));
5087 TEST(ForEachLambdaCapture, IgnoreUnlessSpelledInSource) {
5088 auto matcher =
5089 traverse(TK_IgnoreUnlessSpelledInSource,
5090 lambdaExpr(forEachLambdaCapture(
5091 lambdaCapture(capturesVar(varDecl(hasType(isInteger()))))
5092 .bind("LC"))));
5093 EXPECT_TRUE(
5094 notMatches("int main() { int x, y; auto f = [=]() { return x + y; }; }",
5095 matcher, langCxx11OrLater()));
5096 EXPECT_TRUE(
5097 notMatches("int main() { int x, y; auto f = [&]() { return x + y; }; }",
5098 matcher, langCxx11OrLater()));
5099 EXPECT_TRUE(matchAndVerifyResultTrue(
5100 R"cc(
5101 int main() {
5102 int x, y;
5103 float z;
5104 auto f = [=, &y]() { return x + y + z; };
5106 )cc",
5107 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));
5110 TEST(ForEachLambdaCapture, MatchImplicitCapturesOnly) {
5111 auto matcher =
5112 lambdaExpr(forEachLambdaCapture(lambdaCapture(isImplicit()).bind("LC")));
5113 EXPECT_TRUE(matchAndVerifyResultTrue(
5114 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
5115 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));
5116 EXPECT_TRUE(matchAndVerifyResultTrue(
5117 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
5118 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 2)));
5121 TEST(ForEachLambdaCapture, MatchExplicitCapturesOnly) {
5122 auto matcher = lambdaExpr(
5123 forEachLambdaCapture(lambdaCapture(unless(isImplicit())).bind("LC")));
5124 EXPECT_TRUE(matchAndVerifyResultTrue(
5125 "int main() { int x, y, z; auto f = [=, &z]() { return x + y + z; }; }",
5126 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));
5127 EXPECT_TRUE(matchAndVerifyResultTrue(
5128 "int main() { int x, y, z; auto f = [&, z]() { return x + y + z; }; }",
5129 matcher, std::make_unique<VerifyIdIsBoundTo<LambdaCapture>>("LC", 1)));
5132 TEST(HasConditionVariableStatement, DoesNotMatchCondition) {
5133 EXPECT_TRUE(notMatches(
5134 "void x() { if(true) {} }",
5135 ifStmt(hasConditionVariableStatement(declStmt()))));
5136 EXPECT_TRUE(notMatches(
5137 "void x() { int x; if((x = 42)) {} }",
5138 ifStmt(hasConditionVariableStatement(declStmt()))));
5141 TEST(HasConditionVariableStatement, MatchesConditionVariables) {
5142 EXPECT_TRUE(matches(
5143 "void x() { if(int* a = 0) {} }",
5144 ifStmt(hasConditionVariableStatement(declStmt()))));
5147 TEST(ForEach, BindsOneNode) {
5148 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; };",
5149 recordDecl(hasName("C"), forEach(fieldDecl(hasName("x")).bind("x"))),
5150 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("x", 1)));
5153 TEST(ForEach, BindsMultipleNodes) {
5154 EXPECT_TRUE(matchAndVerifyResultTrue("class C { int x; int y; int z; };",
5155 recordDecl(hasName("C"), forEach(fieldDecl().bind("f"))),
5156 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 3)));
5159 TEST(ForEach, BindsRecursiveCombinations) {
5160 EXPECT_TRUE(matchAndVerifyResultTrue(
5161 "class C { class D { int x; int y; }; class E { int y; int z; }; };",
5162 recordDecl(hasName("C"),
5163 forEach(recordDecl(forEach(fieldDecl().bind("f"))))),
5164 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 4)));
5167 TEST(ForEach, DoesNotIgnoreImplicit) {
5168 StringRef Code = R"cpp(
5169 void foo()
5171 int i = 0;
5172 int b = 4;
5173 i < b;
5175 )cpp";
5176 EXPECT_TRUE(matchAndVerifyResultFalse(
5177 Code, binaryOperator(forEach(declRefExpr().bind("dre"))),
5178 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 0)));
5180 EXPECT_TRUE(matchAndVerifyResultTrue(
5181 Code,
5182 binaryOperator(forEach(
5183 implicitCastExpr(hasSourceExpression(declRefExpr().bind("dre"))))),
5184 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));
5186 EXPECT_TRUE(matchAndVerifyResultTrue(
5187 Code,
5188 binaryOperator(
5189 forEach(expr(ignoringImplicit(declRefExpr().bind("dre"))))),
5190 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));
5192 EXPECT_TRUE(matchAndVerifyResultTrue(
5193 Code,
5194 traverse(TK_IgnoreUnlessSpelledInSource,
5195 binaryOperator(forEach(declRefExpr().bind("dre")))),
5196 std::make_unique<VerifyIdIsBoundTo<DeclRefExpr>>("dre", 2)));
5199 TEST(ForEachDescendant, BindsOneNode) {
5200 EXPECT_TRUE(matchAndVerifyResultTrue("class C { class D { int x; }; };",
5201 recordDecl(hasName("C"),
5202 forEachDescendant(fieldDecl(hasName("x")).bind("x"))),
5203 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("x", 1)));
5206 TEST(ForEachDescendant, NestedForEachDescendant) {
5207 DeclarationMatcher m = recordDecl(
5208 isDefinition(), decl().bind("x"), hasName("C"));
5209 EXPECT_TRUE(matchAndVerifyResultTrue(
5210 "class A { class B { class C {}; }; };",
5211 recordDecl(hasName("A"), anyOf(m, forEachDescendant(m))),
5212 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", "C")));
5214 // Check that a partial match of 'm' that binds 'x' in the
5215 // first part of anyOf(m, anything()) will not overwrite the
5216 // binding created by the earlier binding in the hasDescendant.
5217 EXPECT_TRUE(matchAndVerifyResultTrue(
5218 "class A { class B { class C {}; }; };",
5219 recordDecl(hasName("A"), allOf(hasDescendant(m), anyOf(m, anything()))),
5220 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", "C")));
5223 TEST(ForEachDescendant, BindsMultipleNodes) {
5224 EXPECT_TRUE(matchAndVerifyResultTrue(
5225 "class C { class D { int x; int y; }; "
5226 " class E { class F { int y; int z; }; }; };",
5227 recordDecl(hasName("C"), forEachDescendant(fieldDecl().bind("f"))),
5228 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 4)));
5231 TEST(ForEachDescendant, BindsRecursiveCombinations) {
5232 EXPECT_TRUE(matchAndVerifyResultTrue(
5233 "class C { class D { "
5234 " class E { class F { class G { int y; int z; }; }; }; }; };",
5235 recordDecl(hasName("C"), forEachDescendant(recordDecl(
5236 forEachDescendant(fieldDecl().bind("f"))))),
5237 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("f", 8)));
5240 TEST(ForEachDescendant, BindsCombinations) {
5241 EXPECT_TRUE(matchAndVerifyResultTrue(
5242 "void f() { if(true) {} if (true) {} while (true) {} if (true) {} while "
5243 "(true) {} }",
5244 compoundStmt(forEachDescendant(ifStmt().bind("if")),
5245 forEachDescendant(whileStmt().bind("while"))),
5246 std::make_unique<VerifyIdIsBoundTo<IfStmt>>("if", 6)));
5249 TEST(ForEachTemplateArgument, OnFunctionDecl) {
5250 const std::string Code = R"(
5251 template <typename T, typename U> void f(T, U) {}
5252 void test() {
5253 int I = 1;
5254 bool B = false;
5255 f(I, B);
5256 })";
5257 EXPECT_TRUE(matches(
5258 Code, functionDecl(forEachTemplateArgument(refersToType(builtinType()))),
5259 langCxx11OrLater()));
5260 auto matcher =
5261 functionDecl(forEachTemplateArgument(
5262 templateArgument(refersToType(builtinType().bind("BT")))
5263 .bind("TA")))
5264 .bind("FN");
5266 EXPECT_TRUE(matchAndVerifyResultTrue(
5267 Code, matcher,
5268 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("FN", 2)));
5269 EXPECT_TRUE(matchAndVerifyResultTrue(
5270 Code, matcher,
5271 std::make_unique<VerifyIdIsBoundTo<TemplateArgument>>("TA", 2)));
5272 EXPECT_TRUE(matchAndVerifyResultTrue(
5273 Code, matcher,
5274 std::make_unique<VerifyIdIsBoundTo<BuiltinType>>("BT", 2)));
5277 TEST(ForEachTemplateArgument, OnClassTemplateSpecialization) {
5278 const std::string Code = R"(
5279 template <typename T, unsigned N, unsigned M>
5280 struct Matrix {};
5282 static constexpr unsigned R = 2;
5284 Matrix<int, R * 2, R * 4> M;
5286 EXPECT_TRUE(matches(
5287 Code, templateSpecializationType(forEachTemplateArgument(isExpr(expr()))),
5288 langCxx11OrLater()));
5289 auto matcher = templateSpecializationType(
5290 forEachTemplateArgument(
5291 templateArgument(isExpr(expr().bind("E"))).bind("TA")))
5292 .bind("TST");
5294 EXPECT_TRUE(matchAndVerifyResultTrue(
5295 Code, matcher,
5296 std::make_unique<VerifyIdIsBoundTo<TemplateSpecializationType>>("TST",
5297 2)));
5298 EXPECT_TRUE(matchAndVerifyResultTrue(
5299 Code, matcher,
5300 std::make_unique<VerifyIdIsBoundTo<TemplateArgument>>("TA", 2)));
5301 EXPECT_TRUE(matchAndVerifyResultTrue(
5302 Code, matcher, std::make_unique<VerifyIdIsBoundTo<Expr>>("E", 2)));
5305 TEST(Has, DoesNotDeleteBindings) {
5306 EXPECT_TRUE(matchAndVerifyResultTrue(
5307 "class X { int a; };", recordDecl(decl().bind("x"), has(fieldDecl())),
5308 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5311 TEST(TemplateArgumentLoc, Matches) {
5312 EXPECT_TRUE(matchAndVerifyResultTrue(
5313 R"cpp(
5314 template <typename A, int B, template <typename> class C> class X {};
5315 class A {};
5316 const int B = 42;
5317 template <typename> class C {};
5318 X<A, B, C> x;
5319 )cpp",
5320 templateArgumentLoc().bind("x"),
5321 std::make_unique<VerifyIdIsBoundTo<TemplateArgumentLoc>>("x", 3)));
5324 TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
5325 // Those matchers cover all the cases where an inner matcher is called
5326 // and there is not a 1:1 relationship between the match of the outer
5327 // matcher and the match of the inner matcher.
5328 // The pattern to look for is:
5329 // ... return InnerMatcher.matches(...); ...
5330 // In which case no special handling is needed.
5332 // On the other hand, if there are multiple alternative matches
5333 // (for example forEach*) or matches might be discarded (for example has*)
5334 // the implementation must make sure that the discarded matches do not
5335 // affect the bindings.
5336 // When new such matchers are added, add a test here that:
5337 // - matches a simple node, and binds it as the first thing in the matcher:
5338 // recordDecl(decl().bind("x"), hasName("X")))
5339 // - uses the matcher under test afterwards in a way that not the first
5340 // alternative is matched; for anyOf, that means the first branch
5341 // would need to return false; for hasAncestor, it means that not
5342 // the direct parent matches the inner matcher.
5344 EXPECT_TRUE(matchAndVerifyResultTrue(
5345 "class X { int y; };",
5346 recordDecl(
5347 recordDecl().bind("x"), hasName("::X"),
5348 anyOf(forEachDescendant(recordDecl(hasName("Y"))), anything())),
5349 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));
5350 EXPECT_TRUE(matchAndVerifyResultTrue(
5351 "class X {};", recordDecl(recordDecl().bind("x"), hasName("::X"),
5352 anyOf(unless(anything()), anything())),
5353 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x", 1)));
5354 EXPECT_TRUE(matchAndVerifyResultTrue(
5355 "template<typename T1, typename T2> class X {}; X<float, int> x;",
5356 classTemplateSpecializationDecl(
5357 decl().bind("x"),
5358 hasAnyTemplateArgument(refersToType(asString("int")))),
5359 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5360 EXPECT_TRUE(matchAndVerifyResultTrue(
5361 "class X { void f(); void g(); };",
5362 cxxRecordDecl(decl().bind("x"), hasMethod(hasName("g"))),
5363 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5364 EXPECT_TRUE(matchAndVerifyResultTrue(
5365 "class X { X() : a(1), b(2) {} double a; int b; };",
5366 recordDecl(decl().bind("x"),
5367 has(cxxConstructorDecl(
5368 hasAnyConstructorInitializer(forField(hasName("b")))))),
5369 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5370 EXPECT_TRUE(matchAndVerifyResultTrue(
5371 "void x(int, int) { x(0, 42); }",
5372 callExpr(expr().bind("x"), hasAnyArgument(integerLiteral(equals(42)))),
5373 std::make_unique<VerifyIdIsBoundTo<Expr>>("x", 1)));
5374 EXPECT_TRUE(matchAndVerifyResultTrue(
5375 "void x(int, int y) {}",
5376 functionDecl(decl().bind("x"), hasAnyParameter(hasName("y"))),
5377 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5378 EXPECT_TRUE(matchAndVerifyResultTrue(
5379 "void x() { return; if (true) {} }",
5380 functionDecl(decl().bind("x"),
5381 has(compoundStmt(hasAnySubstatement(ifStmt())))),
5382 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5383 EXPECT_TRUE(matchAndVerifyResultTrue(
5384 "namespace X { void b(int); void b(); }"
5385 "using X::b;",
5386 usingDecl(decl().bind("x"), hasAnyUsingShadowDecl(hasTargetDecl(
5387 functionDecl(parameterCountIs(1))))),
5388 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5389 EXPECT_TRUE(matchAndVerifyResultTrue(
5390 "class A{}; class B{}; class C : B, A {};",
5391 cxxRecordDecl(decl().bind("x"), isDerivedFrom("::A")),
5392 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5393 EXPECT_TRUE(matchAndVerifyResultTrue(
5394 "class A{}; typedef A B; typedef A C; typedef A D;"
5395 "class E : A {};",
5396 cxxRecordDecl(decl().bind("x"), isDerivedFrom("C")),
5397 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5398 EXPECT_TRUE(matchAndVerifyResultTrue(
5399 "class A { class B { void f() {} }; };",
5400 functionDecl(decl().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5401 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5402 EXPECT_TRUE(matchAndVerifyResultTrue(
5403 "template <typename T> struct A { struct B {"
5404 " void f() { if(true) {} }"
5405 "}; };"
5406 "void t() { A<int>::B b; b.f(); }",
5407 ifStmt(stmt().bind("x"), hasAncestor(recordDecl(hasName("::A")))),
5408 std::make_unique<VerifyIdIsBoundTo<Stmt>>("x", 2)));
5409 EXPECT_TRUE(matchAndVerifyResultTrue(
5410 "class A {};",
5411 recordDecl(hasName("::A"), decl().bind("x"), unless(hasName("fooble"))),
5412 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5413 EXPECT_TRUE(matchAndVerifyResultTrue(
5414 "class A { A() : s(), i(42) {} const char *s; int i; };",
5415 cxxConstructorDecl(hasName("::A::A"), decl().bind("x"),
5416 forEachConstructorInitializer(forField(hasName("i")))),
5417 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
5420 TEST(ForEachDescendant, BindsCorrectNodes) {
5421 EXPECT_TRUE(matchAndVerifyResultTrue(
5422 "class C { void f(); int i; };",
5423 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5424 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("decl", 1)));
5425 EXPECT_TRUE(matchAndVerifyResultTrue(
5426 "class C { void f() {} int i; };",
5427 recordDecl(hasName("C"), forEachDescendant(decl().bind("decl"))),
5428 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("decl", 1)));
5431 TEST(FindAll, BindsNodeOnMatch) {
5432 EXPECT_TRUE(matchAndVerifyResultTrue(
5433 "class A {};",
5434 recordDecl(hasName("::A"), findAll(recordDecl(hasName("::A")).bind("v"))),
5435 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("v", 1)));
5438 TEST(FindAll, BindsDescendantNodeOnMatch) {
5439 EXPECT_TRUE(matchAndVerifyResultTrue(
5440 "class A { int a; int b; };",
5441 recordDecl(hasName("::A"), findAll(fieldDecl().bind("v"))),
5442 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 2)));
5445 TEST(FindAll, BindsNodeAndDescendantNodesOnOneMatch) {
5446 EXPECT_TRUE(matchAndVerifyResultTrue(
5447 "class A { int a; int b; };",
5448 recordDecl(hasName("::A"),
5449 findAll(decl(anyOf(recordDecl(hasName("::A")).bind("v"),
5450 fieldDecl().bind("v"))))),
5451 std::make_unique<VerifyIdIsBoundTo<Decl>>("v", 3)));
5453 EXPECT_TRUE(matchAndVerifyResultTrue(
5454 "class A { class B {}; class C {}; };",
5455 recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("v"))),
5456 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("v", 3)));
5459 TEST(HasAncenstor, MatchesDeclarationAncestors) {
5460 EXPECT_TRUE(matches(
5461 "class A { class B { class C {}; }; };",
5462 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("A"))))));
5465 TEST(HasAncenstor, FailsIfNoAncestorMatches) {
5466 EXPECT_TRUE(notMatches(
5467 "class A { class B { class C {}; }; };",
5468 recordDecl(hasName("C"), hasAncestor(recordDecl(hasName("X"))))));
5471 TEST(HasAncestor, MatchesDeclarationsThatGetVisitedLater) {
5472 EXPECT_TRUE(matches(
5473 "class A { class B { void f() { C c; } class C {}; }; };",
5474 varDecl(hasName("c"), hasType(recordDecl(hasName("C"),
5475 hasAncestor(recordDecl(hasName("A"))))))));
5478 TEST(HasAncenstor, MatchesStatementAncestors) {
5479 EXPECT_TRUE(matches(
5480 "void f() { if (true) { while (false) { 42; } } }",
5481 integerLiteral(equals(42), hasAncestor(ifStmt()))));
5484 TEST(HasAncestor, DrillsThroughDifferentHierarchies) {
5485 EXPECT_TRUE(matches(
5486 "void f() { if (true) { int x = 42; } }",
5487 integerLiteral(equals(42), hasAncestor(functionDecl(hasName("f"))))));
5490 TEST(HasAncestor, BindsRecursiveCombinations) {
5491 EXPECT_TRUE(matchAndVerifyResultTrue(
5492 "class C { class D { class E { class F { int y; }; }; }; };",
5493 fieldDecl(hasAncestor(recordDecl(hasAncestor(recordDecl().bind("r"))))),
5494 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("r", 1)));
5497 TEST(HasAncestor, BindsCombinationsWithHasDescendant) {
5498 EXPECT_TRUE(matchAndVerifyResultTrue(
5499 "class C { class D { class E { class F { int y; }; }; }; };",
5500 fieldDecl(hasAncestor(
5501 decl(
5502 hasDescendant(recordDecl(isDefinition(),
5503 hasAncestor(recordDecl())))
5504 ).bind("d")
5506 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("d", "E")));
5509 TEST(HasAncestor, MatchesClosestAncestor) {
5510 EXPECT_TRUE(matchAndVerifyResultTrue(
5511 "template <typename T> struct C {"
5512 " void f(int) {"
5513 " struct I { void g(T) { int x; } } i; i.g(42);"
5514 " }"
5515 "};"
5516 "template struct C<int>;",
5517 varDecl(hasName("x"),
5518 hasAncestor(functionDecl(hasParameter(
5519 0, varDecl(hasType(asString("int"))))).bind("f"))).bind("v"),
5520 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("f", "g", 2)));
5523 TEST(HasAncestor, MatchesInTemplateInstantiations) {
5524 EXPECT_TRUE(matches(
5525 "template <typename T> struct A { struct B { struct C { T t; }; }; }; "
5526 "A<int>::B::C a;",
5527 fieldDecl(hasType(asString("int")),
5528 hasAncestor(recordDecl(hasName("A"))))));
5531 TEST(HasAncestor, MatchesInImplicitCode) {
5532 EXPECT_TRUE(matches(
5533 "struct X {}; struct A { A() {} X x; };",
5534 cxxConstructorDecl(
5535 hasAnyConstructorInitializer(withInitializer(expr(
5536 hasAncestor(recordDecl(hasName("A")))))))));
5539 TEST(HasParent, MatchesOnlyParent) {
5540 EXPECT_TRUE(matches(
5541 "void f() { if (true) { int x = 42; } }",
5542 compoundStmt(hasParent(ifStmt()))));
5543 EXPECT_TRUE(notMatches(
5544 "void f() { for (;;) { int x = 42; } }",
5545 compoundStmt(hasParent(ifStmt()))));
5546 EXPECT_TRUE(notMatches(
5547 "void f() { if (true) for (;;) { int x = 42; } }",
5548 compoundStmt(hasParent(ifStmt()))));
5551 TEST(MatcherMemoize, HasParentDiffersFromHas) {
5552 // Test introduced after detecting a bug in memoization
5553 constexpr auto code = "void f() { throw 1; }";
5554 EXPECT_TRUE(notMatches(
5555 code,
5556 cxxThrowExpr(hasParent(expr()))));
5557 EXPECT_TRUE(matches(
5558 code,
5559 cxxThrowExpr(has(expr()))));
5560 EXPECT_TRUE(matches(
5561 code,
5562 cxxThrowExpr(anyOf(hasParent(expr()), has(expr())))));
5565 TEST(MatcherMemoize, HasDiffersFromHasDescendant) {
5566 // Test introduced after detecting a bug in memoization
5567 constexpr auto code = "void f() { throw 1+1; }";
5568 EXPECT_TRUE(notMatches(
5569 code,
5570 cxxThrowExpr(has(integerLiteral()))));
5571 EXPECT_TRUE(matches(
5572 code,
5573 cxxThrowExpr(hasDescendant(integerLiteral()))));
5574 EXPECT_TRUE(
5575 notMatches(code, cxxThrowExpr(allOf(hasDescendant(integerLiteral()),
5576 has(integerLiteral())))));
5578 TEST(HasAncestor, MatchesAllAncestors) {
5579 EXPECT_TRUE(matches(
5580 "template <typename T> struct C { static void f() { 42; } };"
5581 "void t() { C<int>::f(); }",
5582 integerLiteral(
5583 equals(42),
5584 allOf(
5585 hasAncestor(cxxRecordDecl(isTemplateInstantiation())),
5586 hasAncestor(cxxRecordDecl(unless(isTemplateInstantiation())))))));
5589 TEST(HasAncestor, ImplicitArrayCopyCtorDeclRefExpr) {
5590 EXPECT_TRUE(matches("struct MyClass {\n"
5591 " int c[1];\n"
5592 " static MyClass Create() { return MyClass(); }\n"
5593 "};",
5594 declRefExpr(to(decl(hasAncestor(decl()))))));
5597 TEST(HasAncestor, AnonymousUnionMemberExpr) {
5598 EXPECT_TRUE(matches("int F() {\n"
5599 " union { int i; };\n"
5600 " return i;\n"
5601 "}\n",
5602 memberExpr(member(hasAncestor(decl())))));
5603 EXPECT_TRUE(matches("void f() {\n"
5604 " struct {\n"
5605 " struct { int a; int b; };\n"
5606 " } s;\n"
5607 " s.a = 4;\n"
5608 "}\n",
5609 memberExpr(member(hasAncestor(decl())))));
5610 EXPECT_TRUE(matches("void f() {\n"
5611 " struct {\n"
5612 " struct { int a; int b; };\n"
5613 " } s;\n"
5614 " s.a = 4;\n"
5615 "}\n",
5616 declRefExpr(to(decl(hasAncestor(decl()))))));
5618 TEST(HasAncestor, NonParmDependentTemplateParmVarDeclRefExpr) {
5619 EXPECT_TRUE(matches("struct PartitionAllocator {\n"
5620 " template<typename T>\n"
5621 " static int quantizedSize(int count) {\n"
5622 " return count;\n"
5623 " }\n"
5624 " void f() { quantizedSize<int>(10); }\n"
5625 "};",
5626 declRefExpr(to(decl(hasAncestor(decl()))))));
5629 TEST(HasAncestor, AddressOfExplicitSpecializationFunction) {
5630 EXPECT_TRUE(matches("template <class T> void f();\n"
5631 "template <> void f<int>();\n"
5632 "void (*get_f())() { return f<int>; }\n",
5633 declRefExpr(to(decl(hasAncestor(decl()))))));
5636 TEST(HasParent, MatchesAllParents) {
5637 EXPECT_TRUE(matches(
5638 "template <typename T> struct C { static void f() { 42; } };"
5639 "void t() { C<int>::f(); }",
5640 integerLiteral(
5641 equals(42),
5642 hasParent(compoundStmt(hasParent(functionDecl(
5643 hasParent(cxxRecordDecl(isTemplateInstantiation())))))))));
5644 EXPECT_TRUE(
5645 matches("template <typename T> struct C { static void f() { 42; } };"
5646 "void t() { C<int>::f(); }",
5647 integerLiteral(
5648 equals(42),
5649 hasParent(compoundStmt(hasParent(functionDecl(hasParent(
5650 cxxRecordDecl(unless(isTemplateInstantiation()))))))))));
5651 EXPECT_TRUE(matches(
5652 "template <typename T> struct C { static void f() { 42; } };"
5653 "void t() { C<int>::f(); }",
5654 integerLiteral(equals(42),
5655 hasParent(compoundStmt(
5656 allOf(hasParent(functionDecl(hasParent(
5657 cxxRecordDecl(isTemplateInstantiation())))),
5658 hasParent(functionDecl(hasParent(cxxRecordDecl(
5659 unless(isTemplateInstantiation())))))))))));
5660 EXPECT_TRUE(
5661 notMatches("template <typename T> struct C { static void f() {} };"
5662 "void t() { C<int>::f(); }",
5663 compoundStmt(hasParent(recordDecl()))));
5666 TEST(HasParent, NoDuplicateParents) {
5667 class HasDuplicateParents : public BoundNodesCallback {
5668 public:
5669 bool run(const BoundNodes *Nodes, ASTContext *Context) override {
5670 const Stmt *Node = Nodes->getNodeAs<Stmt>("node");
5671 std::set<const void *> Parents;
5672 for (const auto &Parent : Context->getParents(*Node)) {
5673 if (!Parents.insert(Parent.getMemoizationData()).second) {
5674 return true;
5677 return false;
5680 EXPECT_FALSE(matchAndVerifyResultTrue(
5681 "template <typename T> int Foo() { return 1 + 2; }\n"
5682 "int x = Foo<int>() + Foo<unsigned>();",
5683 stmt().bind("node"), std::make_unique<HasDuplicateParents>()));
5686 TEST(HasAnyBase, BindsInnerBoundNodes) {
5687 EXPECT_TRUE(matchAndVerifyResultTrue(
5688 "struct Inner {}; struct Proxy : Inner {}; struct Main : public "
5689 "Proxy {};",
5690 cxxRecordDecl(hasName("Main"),
5691 hasAnyBase(cxxBaseSpecifier(hasType(
5692 cxxRecordDecl(hasName("Inner")).bind("base-class")))))
5693 .bind("class"),
5694 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("base-class",
5695 "Inner")));
5698 TEST(TypeMatching, PointeeTypes) {
5699 EXPECT_TRUE(matches("int b; int &a = b;",
5700 referenceType(pointee(builtinType()))));
5701 EXPECT_TRUE(matches("int *a;", pointerType(pointee(builtinType()))));
5703 EXPECT_TRUE(matches("int *a;",
5704 loc(pointerType(pointee(builtinType())))));
5706 EXPECT_TRUE(matches(
5707 "int const *A;",
5708 pointerType(pointee(isConstQualified(), builtinType()))));
5709 EXPECT_TRUE(notMatches(
5710 "int *A;",
5711 pointerType(pointee(isConstQualified(), builtinType()))));
5714 TEST(ElaboratedTypeNarrowing, hasQualifier) {
5715 EXPECT_TRUE(matches(
5716 "namespace N {"
5717 " namespace M {"
5718 " class D {};"
5719 " }"
5721 "N::M::D d;",
5722 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5723 EXPECT_TRUE(notMatches(
5724 "namespace M {"
5725 " class D {};"
5727 "M::D d;",
5728 elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
5729 EXPECT_TRUE(notMatches(
5730 "struct D {"
5731 "} d;",
5732 elaboratedType(hasQualifier(nestedNameSpecifier()))));
5735 TEST(ElaboratedTypeNarrowing, namesType) {
5736 EXPECT_TRUE(matches(
5737 "namespace N {"
5738 " namespace M {"
5739 " class D {};"
5740 " }"
5742 "N::M::D d;",
5743 elaboratedType(elaboratedType(namesType(recordType(
5744 hasDeclaration(namedDecl(hasName("D")))))))));
5745 EXPECT_TRUE(notMatches(
5746 "namespace M {"
5747 " class D {};"
5749 "M::D d;",
5750 elaboratedType(elaboratedType(namesType(typedefType())))));
5753 TEST(NNS, BindsNestedNameSpecifiers) {
5754 EXPECT_TRUE(matchAndVerifyResultTrue(
5755 "namespace ns { struct E { struct B {}; }; } ns::E::B b;",
5756 nestedNameSpecifier(specifiesType(asString("struct ns::E"))).bind("nns"),
5757 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>(
5758 "nns", "ns::struct E::")));
5761 TEST(NNS, BindsNestedNameSpecifierLocs) {
5762 EXPECT_TRUE(matchAndVerifyResultTrue(
5763 "namespace ns { struct B {}; } ns::B b;",
5764 loc(nestedNameSpecifier()).bind("loc"),
5765 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("loc", 1)));
5768 TEST(NNS, DescendantsOfNestedNameSpecifiers) {
5769 StringRef Fragment =
5770 "namespace a { struct A { struct B { struct C {}; }; }; };"
5771 "void f() { a::A::B::C c; }";
5772 EXPECT_TRUE(matches(
5773 Fragment,
5774 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5775 hasDescendant(nestedNameSpecifier(
5776 specifiesNamespace(hasName("a")))))));
5777 EXPECT_TRUE(notMatches(
5778 Fragment,
5779 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5780 has(nestedNameSpecifier(
5781 specifiesNamespace(hasName("a")))))));
5782 EXPECT_TRUE(matches(
5783 Fragment,
5784 nestedNameSpecifier(specifiesType(asString("struct a::A")),
5785 has(nestedNameSpecifier(
5786 specifiesNamespace(hasName("a")))))));
5788 // Not really useful because a NestedNameSpecifier can af at most one child,
5789 // but to complete the interface.
5790 EXPECT_TRUE(matchAndVerifyResultTrue(
5791 Fragment,
5792 nestedNameSpecifier(specifiesType(asString("struct a::A::B")),
5793 forEach(nestedNameSpecifier().bind("x"))),
5794 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 1)));
5797 TEST(NNS, NestedNameSpecifiersAsDescendants) {
5798 StringRef Fragment =
5799 "namespace a { struct A { struct B { struct C {}; }; }; };"
5800 "void f() { a::A::B::C c; }";
5801 EXPECT_TRUE(matches(
5802 Fragment,
5803 decl(hasDescendant(nestedNameSpecifier(specifiesType(
5804 asString("struct a::A")))))));
5805 EXPECT_TRUE(matchAndVerifyResultTrue(
5806 Fragment,
5807 functionDecl(hasName("f"),
5808 forEachDescendant(nestedNameSpecifier().bind("x"))),
5809 // Nested names: a, a::A and a::A::B.
5810 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifier>>("x", 3)));
5813 TEST(NNSLoc, DescendantsOfNestedNameSpecifierLocs) {
5814 StringRef Fragment =
5815 "namespace a { struct A { struct B { struct C {}; }; }; };"
5816 "void f() { a::A::B::C c; }";
5817 EXPECT_TRUE(matches(
5818 Fragment,
5819 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5820 hasDescendant(loc(nestedNameSpecifier(
5821 specifiesNamespace(hasName("a"))))))));
5822 EXPECT_TRUE(notMatches(
5823 Fragment,
5824 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5825 has(loc(nestedNameSpecifier(
5826 specifiesNamespace(hasName("a"))))))));
5827 EXPECT_TRUE(matches(
5828 Fragment,
5829 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A"))),
5830 has(loc(nestedNameSpecifier(
5831 specifiesNamespace(hasName("a"))))))));
5833 EXPECT_TRUE(matchAndVerifyResultTrue(
5834 Fragment,
5835 nestedNameSpecifierLoc(loc(specifiesType(asString("struct a::A::B"))),
5836 forEach(nestedNameSpecifierLoc().bind("x"))),
5837 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 1)));
5840 TEST(NNSLoc, NestedNameSpecifierLocsAsDescendants) {
5841 StringRef Fragment =
5842 "namespace a { struct A { struct B { struct C {}; }; }; };"
5843 "void f() { a::A::B::C c; }";
5844 EXPECT_TRUE(matches(
5845 Fragment,
5846 decl(hasDescendant(loc(nestedNameSpecifier(specifiesType(
5847 asString("struct a::A"))))))));
5848 EXPECT_TRUE(matchAndVerifyResultTrue(
5849 Fragment,
5850 functionDecl(hasName("f"),
5851 forEachDescendant(nestedNameSpecifierLoc().bind("x"))),
5852 // Nested names: a, a::A and a::A::B.
5853 std::make_unique<VerifyIdIsBoundTo<NestedNameSpecifierLoc>>("x", 3)));
5856 TEST(Attr, AttrsAsDescendants) {
5857 StringRef Fragment = "namespace a { struct [[clang::warn_unused_result]] "
5858 "F{}; [[noreturn]] void foo(); }";
5859 EXPECT_TRUE(matches(Fragment, namespaceDecl(hasDescendant(attr()))));
5860 EXPECT_TRUE(matchAndVerifyResultTrue(
5861 Fragment,
5862 namespaceDecl(hasName("a"),
5863 forEachDescendant(attr(unless(isImplicit())).bind("x"))),
5864 std::make_unique<VerifyIdIsBoundTo<Attr>>("x", 2)));
5867 TEST(Attr, ParentsOfAttrs) {
5868 StringRef Fragment =
5869 "namespace a { struct [[clang::warn_unused_result]] F{}; }";
5870 EXPECT_TRUE(matches(Fragment, attr(hasAncestor(namespaceDecl()))));
5873 template <typename T> class VerifyMatchOnNode : public BoundNodesCallback {
5874 public:
5875 VerifyMatchOnNode(StringRef Id, const internal::Matcher<T> &InnerMatcher,
5876 StringRef InnerId)
5877 : Id(Id), InnerMatcher(InnerMatcher), InnerId(InnerId) {}
5879 bool run(const BoundNodes *Nodes, ASTContext *Context) override {
5880 const T *Node = Nodes->getNodeAs<T>(Id);
5881 return selectFirst<T>(InnerId, match(InnerMatcher, *Node, *Context)) !=
5882 nullptr;
5885 private:
5886 std::string Id;
5887 internal::Matcher<T> InnerMatcher;
5888 std::string InnerId;
5891 TEST(MatchFinder, CanMatchDeclarationsRecursively) {
5892 EXPECT_TRUE(matchAndVerifyResultTrue(
5893 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5894 std::make_unique<VerifyMatchOnNode<Decl>>(
5895 "X", decl(hasDescendant(recordDecl(hasName("X::Y")).bind("Y"))),
5896 "Y")));
5897 EXPECT_TRUE(matchAndVerifyResultFalse(
5898 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5899 std::make_unique<VerifyMatchOnNode<Decl>>(
5900 "X", decl(hasDescendant(recordDecl(hasName("X::Z")).bind("Z"))),
5901 "Z")));
5904 TEST(MatchFinder, CanMatchStatementsRecursively) {
5905 EXPECT_TRUE(matchAndVerifyResultTrue(
5906 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5907 std::make_unique<VerifyMatchOnNode<Stmt>>(
5908 "if", stmt(hasDescendant(forStmt().bind("for"))), "for")));
5909 EXPECT_TRUE(matchAndVerifyResultFalse(
5910 "void f() { if (1) { for (;;) { } } }", ifStmt().bind("if"),
5911 std::make_unique<VerifyMatchOnNode<Stmt>>(
5912 "if", stmt(hasDescendant(declStmt().bind("decl"))), "decl")));
5915 TEST(MatchFinder, CanMatchSingleNodesRecursively) {
5916 EXPECT_TRUE(matchAndVerifyResultTrue(
5917 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5918 std::make_unique<VerifyMatchOnNode<Decl>>(
5919 "X", recordDecl(has(recordDecl(hasName("X::Y")).bind("Y"))), "Y")));
5920 EXPECT_TRUE(matchAndVerifyResultFalse(
5921 "class X { class Y {}; };", recordDecl(hasName("::X")).bind("X"),
5922 std::make_unique<VerifyMatchOnNode<Decl>>(
5923 "X", recordDecl(has(recordDecl(hasName("X::Z")).bind("Z"))), "Z")));
5926 TEST(StatementMatcher, HasReturnValue) {
5927 StatementMatcher RetVal = returnStmt(hasReturnValue(binaryOperator()));
5928 EXPECT_TRUE(matches("int F() { int a, b; return a + b; }", RetVal));
5929 EXPECT_FALSE(matches("int F() { int a; return a; }", RetVal));
5930 EXPECT_FALSE(matches("void F() { return; }", RetVal));
5933 TEST(StatementMatcher, ForFunction) {
5934 StringRef CppString1 = "struct PosVec {"
5935 " PosVec& operator=(const PosVec&) {"
5936 " auto x = [] { return 1; };"
5937 " return *this;"
5938 " }"
5939 "};";
5940 StringRef CppString2 = "void F() {"
5941 " struct S {"
5942 " void F2() {"
5943 " return;"
5944 " }"
5945 " };"
5946 "}";
5947 EXPECT_TRUE(
5948 matches(
5949 CppString1,
5950 returnStmt(forFunction(hasName("operator=")),
5951 has(unaryOperator(hasOperatorName("*"))))));
5952 EXPECT_TRUE(
5953 notMatches(
5954 CppString1,
5955 returnStmt(forFunction(hasName("operator=")),
5956 has(integerLiteral()))));
5957 EXPECT_TRUE(
5958 matches(
5959 CppString1,
5960 returnStmt(forFunction(hasName("operator()")),
5961 has(integerLiteral()))));
5962 EXPECT_TRUE(matches(CppString2, returnStmt(forFunction(hasName("F2")))));
5963 EXPECT_TRUE(notMatches(CppString2, returnStmt(forFunction(hasName("F")))));
5966 TEST(StatementMatcher, ForCallable) {
5967 // These tests are copied over from the forFunction() test above.
5968 StringRef CppString1 = "struct PosVec {"
5969 " PosVec& operator=(const PosVec&) {"
5970 " auto x = [] { return 1; };"
5971 " return *this;"
5972 " }"
5973 "};";
5974 StringRef CppString2 = "void F() {"
5975 " struct S {"
5976 " void F2() {"
5977 " return;"
5978 " }"
5979 " };"
5980 "}";
5982 EXPECT_TRUE(
5983 matches(
5984 CppString1,
5985 returnStmt(forCallable(functionDecl(hasName("operator="))),
5986 has(unaryOperator(hasOperatorName("*"))))));
5987 EXPECT_TRUE(
5988 notMatches(
5989 CppString1,
5990 returnStmt(forCallable(functionDecl(hasName("operator="))),
5991 has(integerLiteral()))));
5992 EXPECT_TRUE(
5993 matches(
5994 CppString1,
5995 returnStmt(forCallable(functionDecl(hasName("operator()"))),
5996 has(integerLiteral()))));
5997 EXPECT_TRUE(matches(CppString2,
5998 returnStmt(forCallable(functionDecl(hasName("F2"))))));
5999 EXPECT_TRUE(notMatches(CppString2,
6000 returnStmt(forCallable(functionDecl(hasName("F"))))));
6002 StringRef CodeWithDeepCallExpr = R"cpp(
6003 void Other();
6004 void Function() {
6007 Other()
6011 )cpp";
6012 auto ForCallableFirst =
6013 callExpr(forCallable(functionDecl(hasName("Function"))),
6014 callee(functionDecl(hasName("Other")).bind("callee")))
6015 .bind("call");
6016 auto ForCallableSecond =
6017 callExpr(callee(functionDecl(hasName("Other")).bind("callee")),
6018 forCallable(functionDecl(hasName("Function"))))
6019 .bind("call");
6020 EXPECT_TRUE(matchAndVerifyResultTrue(
6021 CodeWithDeepCallExpr, ForCallableFirst,
6022 std::make_unique<VerifyIdIsBoundTo<CallExpr>>("call")));
6023 EXPECT_TRUE(matchAndVerifyResultTrue(
6024 CodeWithDeepCallExpr, ForCallableFirst,
6025 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("callee")));
6026 EXPECT_TRUE(matchAndVerifyResultTrue(
6027 CodeWithDeepCallExpr, ForCallableSecond,
6028 std::make_unique<VerifyIdIsBoundTo<CallExpr>>("call")));
6029 EXPECT_TRUE(matchAndVerifyResultTrue(
6030 CodeWithDeepCallExpr, ForCallableSecond,
6031 std::make_unique<VerifyIdIsBoundTo<FunctionDecl>>("callee")));
6033 // These tests are specific to forCallable().
6034 StringRef ObjCString1 = "@interface I"
6035 "-(void) foo;"
6036 "@end"
6037 "@implementation I"
6038 "-(void) foo {"
6039 " void (^block)() = ^{ 0x2b | ~0x2b; };"
6041 "@end";
6043 EXPECT_TRUE(
6044 matchesObjC(
6045 ObjCString1,
6046 binaryOperator(forCallable(blockDecl()))));
6048 EXPECT_TRUE(
6049 notMatchesObjC(
6050 ObjCString1,
6051 binaryOperator(forCallable(objcMethodDecl()))));
6053 StringRef ObjCString2 = "@interface I"
6054 "-(void) foo;"
6055 "@end"
6056 "@implementation I"
6057 "-(void) foo {"
6058 " 0x2b | ~0x2b;"
6059 " void (^block)() = ^{};"
6061 "@end";
6063 EXPECT_TRUE(
6064 matchesObjC(
6065 ObjCString2,
6066 binaryOperator(forCallable(objcMethodDecl()))));
6068 EXPECT_TRUE(
6069 notMatchesObjC(
6070 ObjCString2,
6071 binaryOperator(forCallable(blockDecl()))));
6074 namespace {
6075 class ForCallablePreservesBindingWithMultipleParentsTestCallback
6076 : public BoundNodesCallback {
6077 public:
6078 bool run(const BoundNodes *BoundNodes, ASTContext *Context) override {
6079 FunctionDecl const *FunDecl =
6080 BoundNodes->getNodeAs<FunctionDecl>("funDecl");
6081 // Validate test assumptions. This would be expressed as ASSERT_* in
6082 // a TEST().
6083 if (!FunDecl) {
6084 EXPECT_TRUE(false && "Incorrect test setup");
6085 return false;
6087 auto const *FunDef = FunDecl->getDefinition();
6088 if (!FunDef || !FunDef->getBody() ||
6089 FunDef->getNameAsString() != "Function") {
6090 EXPECT_TRUE(false && "Incorrect test setup");
6091 return false;
6094 ExpectCorrectResult(
6095 "Baseline",
6096 callExpr(callee(cxxMethodDecl().bind("callee"))).bind("call"), //
6097 FunDecl);
6099 ExpectCorrectResult("ForCallable first",
6100 callExpr(forCallable(equalsNode(FunDecl)),
6101 callee(cxxMethodDecl().bind("callee")))
6102 .bind("call"),
6103 FunDecl);
6105 ExpectCorrectResult("ForCallable second",
6106 callExpr(callee(cxxMethodDecl().bind("callee")),
6107 forCallable(equalsNode(FunDecl)))
6108 .bind("call"),
6109 FunDecl);
6111 // This value does not really matter: the EXPECT_* will set the exit code.
6112 return true;
6115 private:
6116 void ExpectCorrectResult(StringRef LogInfo,
6117 ArrayRef<BoundNodes> Results) const {
6118 EXPECT_EQ(Results.size(), 1u) << LogInfo;
6119 if (Results.empty())
6120 return;
6121 auto const &R = Results.front();
6122 EXPECT_TRUE(R.getNodeAs<CallExpr>("call")) << LogInfo;
6123 EXPECT_TRUE(R.getNodeAs<CXXMethodDecl>("callee")) << LogInfo;
6126 template <typename MatcherT>
6127 void ExpectCorrectResult(StringRef LogInfo, MatcherT Matcher,
6128 FunctionDecl const *FunDef) const {
6129 auto &Context = FunDef->getASTContext();
6130 auto const &Results = match(findAll(Matcher), *FunDef->getBody(), Context);
6131 ExpectCorrectResult(LogInfo, Results);
6134 } // namespace
6136 TEST(StatementMatcher, ForCallablePreservesBindingWithMultipleParents) {
6137 // Tests in this file are fairly simple and therefore can rely on matches,
6138 // matchAndVerifyResultTrue, etc. This test, however, needs a FunctionDecl* in
6139 // order to call equalsNode in order to reproduce the observed issue (bindings
6140 // being removed despite forCallable matching the node).
6142 // Because of this and because the machinery to compile the code into an
6143 // ASTUnit is not exposed outside matchAndVerifyResultConditionally, it is
6144 // cheaper to have a custom BoundNodesCallback for the purpose of this test.
6145 StringRef codeWithTemplateFunction = R"cpp(
6146 struct Klass {
6147 void Method();
6148 template <typename T>
6149 void Function(T t); // Declaration
6152 void Instantiate(Klass k) {
6153 k.Function(0);
6156 template <typename T>
6157 void Klass::Function(T t) { // Definition
6158 // Compound statement has two parents: the declaration and the definition.
6159 Method();
6161 )cpp";
6162 EXPECT_TRUE(matchAndVerifyResultTrue(
6163 codeWithTemplateFunction,
6164 callExpr(callee(functionDecl(hasName("Function")).bind("funDecl"))),
6165 std::make_unique<
6166 ForCallablePreservesBindingWithMultipleParentsTestCallback>()));
6169 TEST(Matcher, ForEachOverriden) {
6170 const auto ForEachOverriddenInClass = [](const char *ClassName) {
6171 return cxxMethodDecl(ofClass(hasName(ClassName)), isVirtual(),
6172 forEachOverridden(cxxMethodDecl().bind("overridden")))
6173 .bind("override");
6175 static const char Code1[] = "class A { virtual void f(); };"
6176 "class B : public A { void f(); };"
6177 "class C : public B { void f(); };";
6178 // C::f overrides A::f.
6179 EXPECT_TRUE(matchAndVerifyResultTrue(
6180 Code1, ForEachOverriddenInClass("C"),
6181 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));
6182 EXPECT_TRUE(matchAndVerifyResultTrue(
6183 Code1, ForEachOverriddenInClass("C"),
6184 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",
6185 1)));
6186 // B::f overrides A::f.
6187 EXPECT_TRUE(matchAndVerifyResultTrue(
6188 Code1, ForEachOverriddenInClass("B"),
6189 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 1)));
6190 EXPECT_TRUE(matchAndVerifyResultTrue(
6191 Code1, ForEachOverriddenInClass("B"),
6192 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",
6193 1)));
6194 // A::f overrides nothing.
6195 EXPECT_TRUE(notMatches(Code1, ForEachOverriddenInClass("A")));
6197 static const char Code2[] =
6198 "class A1 { virtual void f(); };"
6199 "class A2 { virtual void f(); };"
6200 "class B : public A1, public A2 { void f(); };";
6201 // B::f overrides A1::f and A2::f. This produces two matches.
6202 EXPECT_TRUE(matchAndVerifyResultTrue(
6203 Code2, ForEachOverriddenInClass("B"),
6204 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("override", "f", 2)));
6205 EXPECT_TRUE(matchAndVerifyResultTrue(
6206 Code2, ForEachOverriddenInClass("B"),
6207 std::make_unique<VerifyIdIsBoundTo<CXXMethodDecl>>("overridden", "f",
6208 2)));
6209 // A1::f overrides nothing.
6210 EXPECT_TRUE(notMatches(Code2, ForEachOverriddenInClass("A1")));
6213 TEST(Matcher, HasAnyDeclaration) {
6214 StringRef Fragment = "void foo(int p1);"
6215 "void foo(int *p2);"
6216 "void bar(int p3);"
6217 "template <typename T> void baz(T t) { foo(t); }";
6219 EXPECT_TRUE(
6220 matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6221 hasParameter(0, parmVarDecl(hasName("p1"))))))));
6222 EXPECT_TRUE(
6223 matches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6224 hasParameter(0, parmVarDecl(hasName("p2"))))))));
6225 EXPECT_TRUE(
6226 notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(functionDecl(
6227 hasParameter(0, parmVarDecl(hasName("p3"))))))));
6228 EXPECT_TRUE(notMatches(Fragment, unresolvedLookupExpr(hasAnyDeclaration(
6229 functionDecl(hasName("bar"))))));
6232 TEST(SubstTemplateTypeParmType, HasReplacementType) {
6233 StringRef Fragment = "template<typename T>"
6234 "double F(T t);"
6235 "int i;"
6236 "double j = F(i);";
6237 EXPECT_TRUE(matches(Fragment, substTemplateTypeParmType(hasReplacementType(
6238 qualType(asString("int"))))));
6239 EXPECT_TRUE(notMatches(Fragment, substTemplateTypeParmType(hasReplacementType(
6240 qualType(asString("double"))))));
6241 EXPECT_TRUE(
6242 notMatches("template<int N>"
6243 "double F();"
6244 "double j = F<5>();",
6245 substTemplateTypeParmType(hasReplacementType(qualType()))));
6248 TEST(ClassTemplateSpecializationDecl, HasSpecializedTemplate) {
6249 auto Matcher = classTemplateSpecializationDecl(
6250 hasSpecializedTemplate(classTemplateDecl()));
6251 EXPECT_TRUE(
6252 matches("template<typename T> class A {}; typedef A<int> B;", Matcher));
6253 EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher));
6256 TEST(CXXNewExpr, Array) {
6257 StatementMatcher NewArray = cxxNewExpr(isArray());
6259 EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray));
6260 EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray));
6262 StatementMatcher NewArraySize10 =
6263 cxxNewExpr(hasArraySize(integerLiteral(equals(10))));
6264 EXPECT_TRUE(
6265 matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10));
6266 EXPECT_TRUE(
6267 notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10));
6270 TEST(CXXNewExpr, PlacementArgs) {
6271 StatementMatcher IsPlacementNew = cxxNewExpr(hasAnyPlacementArg(anything()));
6273 EXPECT_TRUE(matches(R"(
6274 void* operator new(decltype(sizeof(void*)), void*);
6275 int *foo(void* Storage) {
6276 return new (Storage) int;
6277 })",
6278 IsPlacementNew));
6280 EXPECT_TRUE(matches(R"(
6281 void* operator new(decltype(sizeof(void*)), void*, unsigned);
6282 int *foo(void* Storage) {
6283 return new (Storage, 16) int;
6284 })",
6285 cxxNewExpr(hasPlacementArg(
6286 1, ignoringImpCasts(integerLiteral(equals(16)))))));
6288 EXPECT_TRUE(notMatches(R"(
6289 void* operator new(decltype(sizeof(void*)), void*);
6290 int *foo(void* Storage) {
6291 return new int;
6292 })",
6293 IsPlacementNew));
6296 TEST(HasUnqualifiedLoc, BindsToConstIntVarDecl) {
6297 EXPECT_TRUE(matches(
6298 "const int x = 0;",
6299 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6300 hasUnqualifiedLoc(loc(asString("int"))))))));
6303 TEST(HasUnqualifiedLoc, BindsToVolatileIntVarDecl) {
6304 EXPECT_TRUE(matches(
6305 "volatile int x = 0;",
6306 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6307 hasUnqualifiedLoc(loc(asString("int"))))))));
6310 TEST(HasUnqualifiedLoc, BindsToConstVolatileIntVarDecl) {
6311 EXPECT_TRUE(matches(
6312 "const volatile int x = 0;",
6313 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6314 hasUnqualifiedLoc(loc(asString("int"))))))));
6317 TEST(HasUnqualifiedLoc, BindsToConstPointerVarDecl) {
6318 auto matcher = varDecl(
6319 hasName("x"),
6320 hasTypeLoc(qualifiedTypeLoc(hasUnqualifiedLoc(pointerTypeLoc()))));
6321 EXPECT_TRUE(matches("int* const x = 0;", matcher));
6322 EXPECT_TRUE(notMatches("int const x = 0;", matcher));
6325 TEST(HasUnqualifiedLoc, BindsToPointerToConstVolatileIntVarDecl) {
6326 EXPECT_TRUE(
6327 matches("const volatile int* x = 0;",
6328 varDecl(hasName("x"),
6329 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(qualifiedTypeLoc(
6330 hasUnqualifiedLoc(loc(asString("int"))))))))));
6333 TEST(HasUnqualifiedLoc, BindsToConstIntFunctionDecl) {
6334 EXPECT_TRUE(
6335 matches("const int f() { return 5; }",
6336 functionDecl(hasName("f"),
6337 hasReturnTypeLoc(qualifiedTypeLoc(
6338 hasUnqualifiedLoc(loc(asString("int"))))))));
6341 TEST(HasUnqualifiedLoc, FloatBindsToConstFloatVarDecl) {
6342 EXPECT_TRUE(matches(
6343 "const float x = 0;",
6344 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6345 hasUnqualifiedLoc(loc(asString("float"))))))));
6348 TEST(HasUnqualifiedLoc, FloatDoesNotBindToIntVarDecl) {
6349 EXPECT_TRUE(notMatches(
6350 "int x = 0;",
6351 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6352 hasUnqualifiedLoc(loc(asString("float"))))))));
6355 TEST(HasUnqualifiedLoc, FloatDoesNotBindToConstIntVarDecl) {
6356 EXPECT_TRUE(notMatches(
6357 "const int x = 0;",
6358 varDecl(hasName("x"), hasTypeLoc(qualifiedTypeLoc(
6359 hasUnqualifiedLoc(loc(asString("float"))))))));
6362 TEST(HasReturnTypeLoc, BindsToIntReturnTypeLoc) {
6363 EXPECT_TRUE(matches(
6364 "int f() { return 5; }",
6365 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6368 TEST(HasReturnTypeLoc, BindsToFloatReturnTypeLoc) {
6369 EXPECT_TRUE(matches(
6370 "float f() { return 5.0; }",
6371 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6374 TEST(HasReturnTypeLoc, BindsToVoidReturnTypeLoc) {
6375 EXPECT_TRUE(matches(
6376 "void f() {}",
6377 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("void"))))));
6380 TEST(HasReturnTypeLoc, FloatDoesNotBindToIntReturnTypeLoc) {
6381 EXPECT_TRUE(notMatches(
6382 "int f() { return 5; }",
6383 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("float"))))));
6386 TEST(HasReturnTypeLoc, IntDoesNotBindToFloatReturnTypeLoc) {
6387 EXPECT_TRUE(notMatches(
6388 "float f() { return 5.0; }",
6389 functionDecl(hasName("f"), hasReturnTypeLoc(loc(asString("int"))))));
6392 TEST(HasPointeeLoc, BindsToAnyPointeeTypeLoc) {
6393 auto matcher = varDecl(hasName("x"),
6394 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6395 EXPECT_TRUE(matches("int* x;", matcher));
6396 EXPECT_TRUE(matches("float* x;", matcher));
6397 EXPECT_TRUE(matches("char* x;", matcher));
6398 EXPECT_TRUE(matches("void* x;", matcher));
6401 TEST(HasPointeeLoc, DoesNotBindToTypeLocWithoutPointee) {
6402 auto matcher = varDecl(hasName("x"),
6403 hasTypeLoc(pointerTypeLoc(hasPointeeLoc(typeLoc()))));
6404 EXPECT_TRUE(notMatches("int x;", matcher));
6405 EXPECT_TRUE(notMatches("float x;", matcher));
6406 EXPECT_TRUE(notMatches("char x;", matcher));
6409 TEST(HasPointeeLoc, BindsToTypeLocPointingToInt) {
6410 EXPECT_TRUE(
6411 matches("int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6414 TEST(HasPointeeLoc, BindsToTypeLocPointingToIntPointer) {
6415 EXPECT_TRUE(matches("int** x;",
6416 pointerTypeLoc(hasPointeeLoc(loc(asString("int *"))))));
6419 TEST(HasPointeeLoc, BindsToTypeLocPointingToTypeLocPointingToInt) {
6420 EXPECT_TRUE(matches("int** x;", pointerTypeLoc(hasPointeeLoc(pointerTypeLoc(
6421 hasPointeeLoc(loc(asString("int"))))))));
6424 TEST(HasPointeeLoc, BindsToTypeLocPointingToFloat) {
6425 EXPECT_TRUE(matches("float* x;",
6426 pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6429 TEST(HasPointeeLoc, IntPointeeDoesNotBindToTypeLocPointingToFloat) {
6430 EXPECT_TRUE(notMatches("float* x;",
6431 pointerTypeLoc(hasPointeeLoc(loc(asString("int"))))));
6434 TEST(HasPointeeLoc, FloatPointeeDoesNotBindToTypeLocPointingToInt) {
6435 EXPECT_TRUE(notMatches(
6436 "int* x;", pointerTypeLoc(hasPointeeLoc(loc(asString("float"))))));
6439 TEST(HasReferentLoc, BindsToAnyReferentTypeLoc) {
6440 auto matcher = varDecl(
6441 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6442 EXPECT_TRUE(matches("int rr = 3; int& r = rr;", matcher));
6443 EXPECT_TRUE(matches("int rr = 3; auto& r = rr;", matcher));
6444 EXPECT_TRUE(matches("int rr = 3; const int& r = rr;", matcher));
6445 EXPECT_TRUE(matches("float rr = 3.0; float& r = rr;", matcher));
6446 EXPECT_TRUE(matches("char rr = 'a'; char& r = rr;", matcher));
6449 TEST(HasReferentLoc, DoesNotBindToTypeLocWithoutReferent) {
6450 auto matcher = varDecl(
6451 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6452 EXPECT_TRUE(notMatches("int r;", matcher));
6453 EXPECT_TRUE(notMatches("int r = 3;", matcher));
6454 EXPECT_TRUE(notMatches("const int r = 3;", matcher));
6455 EXPECT_TRUE(notMatches("int* r;", matcher));
6456 EXPECT_TRUE(notMatches("float r;", matcher));
6457 EXPECT_TRUE(notMatches("char r;", matcher));
6460 TEST(HasReferentLoc, BindsToAnyRvalueReference) {
6461 auto matcher = varDecl(
6462 hasName("r"), hasTypeLoc(referenceTypeLoc(hasReferentLoc(typeLoc()))));
6463 EXPECT_TRUE(matches("int&& r = 3;", matcher));
6464 EXPECT_TRUE(matches("auto&& r = 3;", matcher));
6465 EXPECT_TRUE(matches("float&& r = 3.0;", matcher));
6468 TEST(HasReferentLoc, BindsToIntReferenceTypeLoc) {
6469 EXPECT_TRUE(matches("int rr = 3; int& r = rr;",
6470 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6473 TEST(HasReferentLoc, BindsToIntRvalueReferenceTypeLoc) {
6474 EXPECT_TRUE(matches("int&& r = 3;",
6475 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6478 TEST(HasReferentLoc, BindsToFloatReferenceTypeLoc) {
6479 EXPECT_TRUE(
6480 matches("float rr = 3.0; float& r = rr;",
6481 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6484 TEST(HasReferentLoc, BindsToParameterWithIntReferenceTypeLoc) {
6485 EXPECT_TRUE(matches(
6486 "int f(int& r) { return r; }",
6487 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6488 hasReferentLoc(loc(asString("int"))))))));
6491 TEST(HasReferentLoc, IntReferenceDoesNotBindToFloatReferenceTypeLoc) {
6492 EXPECT_TRUE(
6493 notMatches("float rr = 3.0; float& r = rr;",
6494 referenceTypeLoc(hasReferentLoc(loc(asString("int"))))));
6497 TEST(HasReferentLoc, FloatReferenceDoesNotBindToIntReferenceTypeLoc) {
6498 EXPECT_TRUE(
6499 notMatches("int rr = 3; int& r = rr;",
6500 referenceTypeLoc(hasReferentLoc(loc(asString("float"))))));
6503 TEST(HasReferentLoc, DoesNotBindToParameterWithoutIntReferenceTypeLoc) {
6504 EXPECT_TRUE(notMatches(
6505 "int f(int r) { return r; }",
6506 parmVarDecl(hasName("r"), hasTypeLoc(referenceTypeLoc(
6507 hasReferentLoc(loc(asString("int"))))))));
6510 TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
6511 EXPECT_TRUE(matches(
6512 "template<typename T> class A {}; A<int> a;",
6513 varDecl(hasName("a"),
6514 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6515 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6516 hasTypeLoc(loc(asString("int")))))))))));
6519 TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
6520 EXPECT_TRUE(matches(
6521 "template<typename T> class A {}; A<double> a;",
6522 varDecl(hasName("a"),
6523 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6524 templateSpecializationTypeLoc(hasAnyTemplateArgumentLoc(
6525 hasTypeLoc(loc(asString("double")))))))))));
6528 TEST(HasAnyTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
6529 EXPECT_TRUE(matches(
6530 "template<typename T> class A {}; template<> class A<int> {};",
6531 classTemplateSpecializationDecl(
6532 hasName("A"),
6533 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
6536 TEST(HasAnyTemplateArgumentLoc,
6537 BindsToExplicitSpecializationWithDoubleArgument) {
6538 EXPECT_TRUE(matches(
6539 "template<typename T> class A {}; template<> class A<double> {};",
6540 classTemplateSpecializationDecl(
6541 hasName("A"),
6542 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
6545 TEST(HasAnyTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
6546 auto code = R"(
6547 template<typename T, typename U> class A {};
6548 template<> class A<double, int> {};
6550 EXPECT_TRUE(
6551 matches(code, classTemplateSpecializationDecl(
6552 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
6553 loc(asString("double")))))));
6555 EXPECT_TRUE(matches(
6556 code, classTemplateSpecializationDecl(
6557 hasName("A"),
6558 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("int")))))));
6561 TEST(HasAnyTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
6562 EXPECT_TRUE(notMatches("template<typename T> class A {}; A<int> a;",
6563 classTemplateSpecializationDecl(
6564 hasName("A"), hasAnyTemplateArgumentLoc(hasTypeLoc(
6565 loc(asString("double")))))));
6568 TEST(HasAnyTemplateArgumentLoc,
6569 DoesNotBindToExplicitSpecializationWithIntArgument) {
6570 EXPECT_TRUE(notMatches(
6571 "template<typename T> class A {}; template<> class A<int> {};",
6572 classTemplateSpecializationDecl(
6573 hasName("A"),
6574 hasAnyTemplateArgumentLoc(hasTypeLoc(loc(asString("double")))))));
6577 TEST(HasTemplateArgumentLoc, BindsToSpecializationWithIntArgument) {
6578 EXPECT_TRUE(
6579 matches("template<typename T> class A {}; A<int> a;",
6580 varDecl(hasName("a"),
6581 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6582 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6583 0, hasTypeLoc(loc(asString("int")))))))))));
6586 TEST(HasTemplateArgumentLoc, BindsToSpecializationWithDoubleArgument) {
6587 EXPECT_TRUE(
6588 matches("template<typename T> class A {}; A<double> a;",
6589 varDecl(hasName("a"),
6590 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6591 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6592 0, hasTypeLoc(loc(asString("double")))))))))));
6595 TEST(HasTemplateArgumentLoc, DoesNotBindToSpecializationWithIntArgument) {
6596 EXPECT_TRUE(notMatches(
6597 "template<typename T> class A {}; A<int> a;",
6598 varDecl(hasName("a"),
6599 hasTypeLoc(elaboratedTypeLoc(hasNamedTypeLoc(
6600 templateSpecializationTypeLoc(hasTemplateArgumentLoc(
6601 0, hasTypeLoc(loc(asString("double")))))))))));
6604 TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithIntArgument) {
6605 EXPECT_TRUE(matches(
6606 "template<typename T> class A {}; template<> class A<int> {};",
6607 classTemplateSpecializationDecl(
6608 hasName("A"),
6609 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6612 TEST(HasTemplateArgumentLoc, BindsToExplicitSpecializationWithDoubleArgument) {
6613 EXPECT_TRUE(matches(
6614 "template<typename T> class A {}; template<> class A<double> {};",
6615 classTemplateSpecializationDecl(
6616 hasName("A"),
6617 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6620 TEST(HasTemplateArgumentLoc, BindsToSpecializationWithMultipleArguments) {
6621 auto code = R"(
6622 template<typename T, typename U> class A {};
6623 template<> class A<double, int> {};
6625 EXPECT_TRUE(matches(
6626 code, classTemplateSpecializationDecl(
6627 hasName("A"), hasTemplateArgumentLoc(
6628 0, hasTypeLoc(loc(asString("double")))))));
6629 EXPECT_TRUE(matches(
6630 code, classTemplateSpecializationDecl(
6631 hasName("A"),
6632 hasTemplateArgumentLoc(1, hasTypeLoc(loc(asString("int")))))));
6635 TEST(HasTemplateArgumentLoc,
6636 DoesNotBindToExplicitSpecializationWithIntArgument) {
6637 EXPECT_TRUE(notMatches(
6638 "template<typename T> class A {}; template<> class A<int> {};",
6639 classTemplateSpecializationDecl(
6640 hasName("A"),
6641 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6644 TEST(HasTemplateArgumentLoc,
6645 DoesNotBindToSpecializationWithMisplacedArguments) {
6646 auto code = R"(
6647 template<typename T, typename U> class A {};
6648 template<> class A<double, int> {};
6650 EXPECT_TRUE(notMatches(
6651 code, classTemplateSpecializationDecl(
6652 hasName("A"), hasTemplateArgumentLoc(
6653 1, hasTypeLoc(loc(asString("double")))))));
6654 EXPECT_TRUE(notMatches(
6655 code, classTemplateSpecializationDecl(
6656 hasName("A"),
6657 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6660 TEST(HasTemplateArgumentLoc, DoesNotBindWithBadIndex) {
6661 auto code = R"(
6662 template<typename T, typename U> class A {};
6663 template<> class A<double, int> {};
6665 EXPECT_TRUE(notMatches(
6666 code, classTemplateSpecializationDecl(
6667 hasName("A"), hasTemplateArgumentLoc(
6668 -1, hasTypeLoc(loc(asString("double")))))));
6669 EXPECT_TRUE(notMatches(
6670 code, classTemplateSpecializationDecl(
6671 hasName("A"), hasTemplateArgumentLoc(
6672 100, hasTypeLoc(loc(asString("int")))))));
6675 TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithIntArgument) {
6676 EXPECT_TRUE(matches(R"(
6677 template<typename T> T f(T t) { return t; }
6678 int g() { int i = f<int>(3); return i; }
6680 declRefExpr(to(functionDecl(hasName("f"))),
6681 hasTemplateArgumentLoc(
6682 0, hasTypeLoc(loc(asString("int")))))));
6685 TEST(HasTemplateArgumentLoc, BindsToDeclRefExprWithDoubleArgument) {
6686 EXPECT_TRUE(matches(
6688 template<typename T> T f(T t) { return t; }
6689 double g() { double i = f<double>(3.0); return i; }
6691 declRefExpr(
6692 to(functionDecl(hasName("f"))),
6693 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("double")))))));
6696 TEST(HasTemplateArgumentLoc, DoesNotBindToDeclRefExprWithDoubleArgument) {
6697 EXPECT_TRUE(notMatches(
6699 template<typename T> T f(T t) { return t; }
6700 double g() { double i = f<double>(3.0); return i; }
6702 declRefExpr(
6703 to(functionDecl(hasName("f"))),
6704 hasTemplateArgumentLoc(0, hasTypeLoc(loc(asString("int")))))));
6707 TEST(HasNamedTypeLoc, BindsToElaboratedObjectDeclaration) {
6708 EXPECT_TRUE(matches(
6710 template <typename T>
6711 class C {};
6712 class C<int> c;
6714 varDecl(hasName("c"),
6715 hasTypeLoc(elaboratedTypeLoc(
6716 hasNamedTypeLoc(templateSpecializationTypeLoc(
6717 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6720 TEST(HasNamedTypeLoc, DoesNotBindToNonElaboratedObjectDeclaration) {
6721 EXPECT_TRUE(matches(
6723 template <typename T>
6724 class C {};
6725 C<int> c;
6727 varDecl(hasName("c"),
6728 hasTypeLoc(elaboratedTypeLoc(
6729 hasNamedTypeLoc(templateSpecializationTypeLoc(
6730 hasAnyTemplateArgumentLoc(templateArgumentLoc()))))))));
6733 } // namespace ast_matchers
6734 } // namespace clang