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

source code of clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp