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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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