1// unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp - AST matcher 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/PrettyPrinter.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/ASTMatchers/ASTMatchers.h"
13#include "clang/Tooling/Tooling.h"
14#include "llvm/TargetParser/Host.h"
15#include "llvm/TargetParser/Triple.h"
16#include "gtest/gtest.h"
17
18namespace clang {
19namespace ast_matchers {
20
21TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesInFile) {
22 StringRef input = R"cc(
23#define MY_MACRO(a) (4 + (a))
24 void Test() { MY_MACRO(4); }
25 )cc";
26 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO"))));
27}
28
29TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesNested) {
30 StringRef input = R"cc(
31#define MY_MACRO(a) (4 + (a))
32#define WRAPPER(a) MY_MACRO(a)
33 void Test() { WRAPPER(4); }
34 )cc";
35 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO"))));
36}
37
38TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesIntermediate) {
39 StringRef input = R"cc(
40#define IMPL(a) (4 + (a))
41#define MY_MACRO(a) IMPL(a)
42#define WRAPPER(a) MY_MACRO(a)
43 void Test() { WRAPPER(4); }
44 )cc";
45 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO"))));
46}
47
48TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesTransitive) {
49 StringRef input = R"cc(
50#define MY_MACRO(a) (4 + (a))
51#define WRAPPER(a) MY_MACRO(a)
52 void Test() { WRAPPER(4); }
53 )cc";
54 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("WRAPPER"))));
55}
56
57TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesArgument) {
58 StringRef input = R"cc(
59#define MY_MACRO(a) (4 + (a))
60 void Test() {
61 int x = 5;
62 MY_MACRO(x);
63 }
64 )cc";
65 EXPECT_TRUE(matches(input, declRefExpr(isExpandedFromMacro("MY_MACRO"))));
66}
67
68// Like IsExpandedFromMacro_MatchesArgument, but the argument is itself a
69// macro.
70TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesArgumentMacroExpansion) {
71 StringRef input = R"cc(
72#define MY_MACRO(a) (4 + (a))
73#define IDENTITY(a) (a)
74 void Test() {
75 IDENTITY(MY_MACRO(2));
76 }
77 )cc";
78 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("IDENTITY"))));
79}
80
81TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesWhenInArgument) {
82 StringRef input = R"cc(
83#define MY_MACRO(a) (4 + (a))
84#define IDENTITY(a) (a)
85 void Test() {
86 IDENTITY(MY_MACRO(2));
87 }
88 )cc";
89 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("MY_MACRO"))));
90}
91
92TEST_P(ASTMatchersTest, IsExpandedFromMacro_MatchesObjectMacro) {
93 StringRef input = R"cc(
94#define PLUS (2 + 2)
95 void Test() {
96 PLUS;
97 }
98 )cc";
99 EXPECT_TRUE(matches(input, binaryOperator(isExpandedFromMacro("PLUS"))));
100}
101
102TEST(IsExpandedFromMacro, MatchesFromCommandLine) {
103 StringRef input = R"cc(
104 void Test() { FOUR_PLUS_FOUR; }
105 )cc";
106 EXPECT_TRUE(matchesConditionally(
107 input, binaryOperator(isExpandedFromMacro("FOUR_PLUS_FOUR")), true,
108 {"-std=c++11", "-DFOUR_PLUS_FOUR=4+4"}));
109}
110
111TEST_P(ASTMatchersTest, IsExpandedFromMacro_NotMatchesBeginOnly) {
112 StringRef input = R"cc(
113#define ONE_PLUS 1+
114 void Test() { ONE_PLUS 4; }
115 )cc";
116 EXPECT_TRUE(
117 notMatches(input, binaryOperator(isExpandedFromMacro("ONE_PLUS"))));
118}
119
120TEST_P(ASTMatchersTest, IsExpandedFromMacro_NotMatchesEndOnly) {
121 StringRef input = R"cc(
122#define PLUS_ONE +1
123 void Test() { 4 PLUS_ONE; }
124 )cc";
125 EXPECT_TRUE(
126 notMatches(input, binaryOperator(isExpandedFromMacro("PLUS_ONE"))));
127}
128
129TEST_P(ASTMatchersTest, IsExpandedFromMacro_NotMatchesDifferentMacro) {
130 StringRef input = R"cc(
131#define MY_MACRO(a) (4 + (a))
132 void Test() { MY_MACRO(4); }
133 )cc";
134 EXPECT_TRUE(notMatches(input, binaryOperator(isExpandedFromMacro("OTHER"))));
135}
136
137TEST_P(ASTMatchersTest, IsExpandedFromMacro_NotMatchesDifferentInstances) {
138 StringRef input = R"cc(
139#define FOUR 4
140 void Test() { FOUR + FOUR; }
141 )cc";
142 EXPECT_TRUE(notMatches(input, binaryOperator(isExpandedFromMacro("FOUR"))));
143}
144
145TEST(IsExpandedFromMacro, IsExpandedFromMacro_MatchesDecls) {
146 StringRef input = R"cc(
147#define MY_MACRO(a) int i = a;
148 void Test() { MY_MACRO(4); }
149 )cc";
150 EXPECT_TRUE(matches(input, varDecl(isExpandedFromMacro("MY_MACRO"))));
151}
152
153TEST(IsExpandedFromMacro, IsExpandedFromMacro_MatchesTypelocs) {
154 StringRef input = R"cc(
155#define MY_TYPE int
156 void Test() { MY_TYPE i = 4; }
157 )cc";
158 EXPECT_TRUE(matches(input, typeLoc(isExpandedFromMacro("MY_TYPE"))));
159}
160
161TEST_P(ASTMatchersTest, AllOf) {
162 const char Program[] = "struct T { };"
163 "int f(int, struct T*, int, int);"
164 "void g(int x) { struct T t; f(x, &t, 3, 4); }";
165 EXPECT_TRUE(matches(
166 Program, callExpr(allOf(callee(functionDecl(hasName("f"))),
167 hasArgument(0, declRefExpr(to(varDecl())))))));
168 EXPECT_TRUE(matches(
169 Program,
170 callExpr(
171 allOf(callee(functionDecl(hasName("f"))),
172 hasArgument(0, declRefExpr(to(varDecl()))),
173 hasArgument(1, hasType(pointsTo(recordDecl(hasName("T")))))))));
174 EXPECT_TRUE(matches(
175 Program, callExpr(allOf(
176 callee(functionDecl(hasName("f"))),
177 hasArgument(0, declRefExpr(to(varDecl()))),
178 hasArgument(1, hasType(pointsTo(recordDecl(hasName("T"))))),
179 hasArgument(2, integerLiteral(equals(3)))))));
180 EXPECT_TRUE(matches(
181 Program, callExpr(allOf(
182 callee(functionDecl(hasName("f"))),
183 hasArgument(0, declRefExpr(to(varDecl()))),
184 hasArgument(1, hasType(pointsTo(recordDecl(hasName("T"))))),
185 hasArgument(2, integerLiteral(equals(3))),
186 hasArgument(3, integerLiteral(equals(4)))))));
187}
188
189TEST_P(ASTMatchersTest, Has) {
190 if (!GetParam().isCXX()) {
191 // FIXME: Add a test for `has()` that does not depend on C++.
192 return;
193 }
194
195 DeclarationMatcher HasClassX = recordDecl(has(recordDecl(hasName(Name: "X"))));
196 EXPECT_TRUE(matches("class Y { class X {}; };", HasClassX));
197 EXPECT_TRUE(matches("class X {};", HasClassX));
198
199 DeclarationMatcher YHasClassX =
200 recordDecl(hasName(Name: "Y"), has(recordDecl(hasName(Name: "X"))));
201 EXPECT_TRUE(matches("class Y { class X {}; };", YHasClassX));
202 EXPECT_TRUE(notMatches("class X {};", YHasClassX));
203 EXPECT_TRUE(notMatches("class Y { class Z { class X {}; }; };", YHasClassX));
204}
205
206TEST_P(ASTMatchersTest, Has_RecursiveAllOf) {
207 if (!GetParam().isCXX()) {
208 return;
209 }
210
211 DeclarationMatcher Recursive =
212 recordDecl(has(recordDecl(has(recordDecl(hasName(Name: "X"))),
213 has(recordDecl(hasName(Name: "Y"))), hasName(Name: "Z"))),
214 has(recordDecl(has(recordDecl(hasName(Name: "A"))),
215 has(recordDecl(hasName(Name: "B"))), hasName(Name: "C"))),
216 hasName(Name: "F"));
217
218 EXPECT_TRUE(matches("class F {"
219 " class Z {"
220 " class X {};"
221 " class Y {};"
222 " };"
223 " class C {"
224 " class A {};"
225 " class B {};"
226 " };"
227 "};",
228 Recursive));
229
230 EXPECT_TRUE(matches("class F {"
231 " class Z {"
232 " class A {};"
233 " class X {};"
234 " class Y {};"
235 " };"
236 " class C {"
237 " class X {};"
238 " class A {};"
239 " class B {};"
240 " };"
241 "};",
242 Recursive));
243
244 EXPECT_TRUE(matches("class O1 {"
245 " class O2 {"
246 " class F {"
247 " class Z {"
248 " class A {};"
249 " class X {};"
250 " class Y {};"
251 " };"
252 " class C {"
253 " class X {};"
254 " class A {};"
255 " class B {};"
256 " };"
257 " };"
258 " };"
259 "};",
260 Recursive));
261}
262
263TEST_P(ASTMatchersTest, Has_RecursiveAnyOf) {
264 if (!GetParam().isCXX()) {
265 return;
266 }
267
268 DeclarationMatcher Recursive = recordDecl(
269 anyOf(has(recordDecl(anyOf(has(recordDecl(hasName(Name: "X"))),
270 has(recordDecl(hasName(Name: "Y"))), hasName(Name: "Z")))),
271 has(recordDecl(anyOf(hasName(Name: "C"), has(recordDecl(hasName(Name: "A"))),
272 has(recordDecl(hasName(Name: "B")))))),
273 hasName(Name: "F")));
274
275 EXPECT_TRUE(matches("class F {};", Recursive));
276 EXPECT_TRUE(matches("class Z {};", Recursive));
277 EXPECT_TRUE(matches("class C {};", Recursive));
278 EXPECT_TRUE(matches("class M { class N { class X {}; }; };", Recursive));
279 EXPECT_TRUE(matches("class M { class N { class B {}; }; };", Recursive));
280 EXPECT_TRUE(matches("class O1 { class O2 {"
281 " class M { class N { class B {}; }; }; "
282 "}; };",
283 Recursive));
284}
285
286TEST_P(ASTMatchersTest, Unless) {
287 if (!GetParam().isCXX()) {
288 // FIXME: Add a test for `unless()` that does not depend on C++.
289 return;
290 }
291
292 DeclarationMatcher NotClassX =
293 cxxRecordDecl(isDerivedFrom(BaseName: "Y"), unless(hasName(Name: "X")));
294 EXPECT_TRUE(notMatches("", NotClassX));
295 EXPECT_TRUE(notMatches("class Y {};", NotClassX));
296 EXPECT_TRUE(matches("class Y {}; class Z : public Y {};", NotClassX));
297 EXPECT_TRUE(notMatches("class Y {}; class X : public Y {};", NotClassX));
298 EXPECT_TRUE(
299 notMatches("class Y {}; class Z {}; class X : public Y {};", NotClassX));
300
301 DeclarationMatcher ClassXHasNotClassY =
302 recordDecl(hasName(Name: "X"), has(recordDecl(hasName(Name: "Z"))),
303 unless(has(recordDecl(hasName(Name: "Y")))));
304 EXPECT_TRUE(matches("class X { class Z {}; };", ClassXHasNotClassY));
305 EXPECT_TRUE(
306 notMatches("class X { class Y {}; class Z {}; };", ClassXHasNotClassY));
307
308 DeclarationMatcher NamedNotRecord =
309 namedDecl(hasName(Name: "Foo"), unless(recordDecl()));
310 EXPECT_TRUE(matches("void Foo(){}", NamedNotRecord));
311 EXPECT_TRUE(notMatches("struct Foo {};", NamedNotRecord));
312}
313
314TEST_P(ASTMatchersTest, HasCastKind) {
315 EXPECT_TRUE(
316 matches("char *p = 0;",
317 traverse(TK_AsIs,
318 varDecl(has(castExpr(hasCastKind(CK_NullToPointer)))))));
319 EXPECT_TRUE(notMatches(
320 "char *p = 0;",
321 traverse(TK_AsIs,
322 varDecl(has(castExpr(hasCastKind(CK_DerivedToBase)))))));
323 EXPECT_TRUE(matches("char *p = 0;",
324 traverse(TK_AsIs, varDecl(has(implicitCastExpr(
325 hasCastKind(CK_NullToPointer)))))));
326}
327
328TEST_P(ASTMatchersTest, HasDescendant) {
329 if (!GetParam().isCXX()) {
330 // FIXME: Add a test for `hasDescendant()` that does not depend on C++.
331 return;
332 }
333
334 DeclarationMatcher ZDescendantClassX =
335 recordDecl(hasDescendant(recordDecl(hasName(Name: "X"))), hasName(Name: "Z"));
336 EXPECT_TRUE(matches("class Z { class X {}; };", ZDescendantClassX));
337 EXPECT_TRUE(
338 matches("class Z { class Y { class X {}; }; };", ZDescendantClassX));
339 EXPECT_TRUE(matches("class Z { class A { class Y { class X {}; }; }; };",
340 ZDescendantClassX));
341 EXPECT_TRUE(
342 matches("class Z { class A { class B { class Y { class X {}; }; }; }; };",
343 ZDescendantClassX));
344 EXPECT_TRUE(notMatches("class Z {};", ZDescendantClassX));
345
346 DeclarationMatcher ZDescendantClassXHasClassY = recordDecl(
347 hasDescendant(recordDecl(has(recordDecl(hasName(Name: "Y"))), hasName(Name: "X"))),
348 hasName(Name: "Z"));
349 EXPECT_TRUE(matches("class Z { class X { class Y {}; }; };",
350 ZDescendantClassXHasClassY));
351 EXPECT_TRUE(
352 matches("class Z { class A { class B { class X { class Y {}; }; }; }; };",
353 ZDescendantClassXHasClassY));
354 EXPECT_TRUE(notMatches("class Z {"
355 " class A {"
356 " class B {"
357 " class X {"
358 " class C {"
359 " class Y {};"
360 " };"
361 " };"
362 " }; "
363 " };"
364 "};",
365 ZDescendantClassXHasClassY));
366
367 DeclarationMatcher ZDescendantClassXDescendantClassY =
368 recordDecl(hasDescendant(recordDecl(
369 hasDescendant(recordDecl(hasName(Name: "Y"))), hasName(Name: "X"))),
370 hasName(Name: "Z"));
371 EXPECT_TRUE(
372 matches("class Z { class A { class X { class B { class Y {}; }; }; }; };",
373 ZDescendantClassXDescendantClassY));
374 EXPECT_TRUE(matches("class Z {"
375 " class A {"
376 " class X {"
377 " class B {"
378 " class Y {};"
379 " };"
380 " class Y {};"
381 " };"
382 " };"
383 "};",
384 ZDescendantClassXDescendantClassY));
385}
386
387TEST_P(ASTMatchersTest, HasDescendant_Memoization) {
388 DeclarationMatcher CannotMemoize =
389 decl(hasDescendant(typeLoc().bind(ID: "x")), has(decl()));
390 EXPECT_TRUE(matches("void f() { int i; }", CannotMemoize));
391}
392
393TEST_P(ASTMatchersTest, HasDescendant_MemoizationUsesRestrictKind) {
394 auto Name = hasName(Name: "i");
395 auto VD = internal::Matcher<VarDecl>(Name).dynCastTo<Decl>();
396 auto RD = internal::Matcher<RecordDecl>(Name).dynCastTo<Decl>();
397 // Matching VD first should not make a cache hit for RD.
398 EXPECT_TRUE(notMatches("void f() { int i; }",
399 decl(hasDescendant(VD), hasDescendant(RD))));
400 EXPECT_TRUE(notMatches("void f() { int i; }",
401 decl(hasDescendant(RD), hasDescendant(VD))));
402 // Not matching RD first should not make a cache hit for VD either.
403 EXPECT_TRUE(matches("void f() { int i; }",
404 decl(anyOf(hasDescendant(RD), hasDescendant(VD)))));
405}
406
407TEST_P(ASTMatchersTest, HasAncestor_Memoization) {
408 if (!GetParam().isCXX()) {
409 return;
410 }
411
412 // This triggers an hasAncestor with a TemplateArgument in the bound nodes.
413 // That node can't be memoized so we have to check for it before trying to put
414 // it on the cache.
415 DeclarationMatcher CannotMemoize = classTemplateSpecializationDecl(
416 hasAnyTemplateArgument(InnerMatcher: templateArgument().bind(ID: "targ")),
417 forEach(fieldDecl(hasAncestor(forStmt()))));
418
419 EXPECT_TRUE(notMatches("template <typename T> struct S;"
420 "template <> struct S<int>{ int i; int j; };",
421 CannotMemoize));
422}
423
424TEST_P(ASTMatchersTest, HasAttr) {
425 EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};",
426 decl(hasAttr(clang::attr::WarnUnused))));
427 EXPECT_FALSE(matches("struct X {};", decl(hasAttr(clang::attr::WarnUnused))));
428}
429
430TEST_P(ASTMatchersTest, AnyOf) {
431 if (!GetParam().isCXX()) {
432 // FIXME: Add a test for `anyOf()` that does not depend on C++.
433 return;
434 }
435
436 DeclarationMatcher YOrZDerivedFromX = cxxRecordDecl(
437 anyOf(hasName(Name: "Y"), allOf(isDerivedFrom(BaseName: "X"), hasName(Name: "Z"))));
438 EXPECT_TRUE(matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
439 EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
440 EXPECT_TRUE(
441 notMatches("class X {}; class W : public X {};", YOrZDerivedFromX));
442 EXPECT_TRUE(notMatches("class Z {};", YOrZDerivedFromX));
443
444 DeclarationMatcher XOrYOrZOrU =
445 recordDecl(anyOf(hasName(Name: "X"), hasName(Name: "Y"), hasName(Name: "Z"), hasName(Name: "U")));
446 EXPECT_TRUE(matches("class X {};", XOrYOrZOrU));
447 EXPECT_TRUE(notMatches("class V {};", XOrYOrZOrU));
448
449 DeclarationMatcher XOrYOrZOrUOrV = recordDecl(anyOf(
450 hasName(Name: "X"), hasName(Name: "Y"), hasName(Name: "Z"), hasName(Name: "U"), hasName(Name: "V")));
451 EXPECT_TRUE(matches("class X {};", XOrYOrZOrUOrV));
452 EXPECT_TRUE(matches("class Y {};", XOrYOrZOrUOrV));
453 EXPECT_TRUE(matches("class Z {};", XOrYOrZOrUOrV));
454 EXPECT_TRUE(matches("class U {};", XOrYOrZOrUOrV));
455 EXPECT_TRUE(matches("class V {};", XOrYOrZOrUOrV));
456 EXPECT_TRUE(notMatches("class A {};", XOrYOrZOrUOrV));
457
458 StatementMatcher MixedTypes = stmt(anyOf(ifStmt(), binaryOperator()));
459 EXPECT_TRUE(matches("int F() { return 1 + 2; }", MixedTypes));
460 EXPECT_TRUE(matches("int F() { if (true) return 1; }", MixedTypes));
461 EXPECT_TRUE(notMatches("int F() { return 1; }", MixedTypes));
462
463 EXPECT_TRUE(
464 matches("void f() try { } catch (int) { } catch (...) { }",
465 cxxCatchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
466}
467
468TEST_P(ASTMatchersTest, MapAnyOf) {
469 if (!GetParam().isCXX()) {
470 return;
471 }
472
473 if (GetParam().hasDelayedTemplateParsing()) {
474 return;
475 }
476
477 StringRef Code = R"cpp(
478void F() {
479 if (true) {}
480 for ( ; false; ) {}
481}
482)cpp";
483
484 auto trueExpr = cxxBoolLiteral(equals(Value: true));
485 auto falseExpr = cxxBoolLiteral(equals(Value: false));
486
487 EXPECT_TRUE(matches(
488 Code, traverse(TK_IgnoreUnlessSpelledInSource,
489 mapAnyOf(ifStmt, forStmt).with(hasCondition(trueExpr)))));
490 EXPECT_TRUE(matches(
491 Code, traverse(TK_IgnoreUnlessSpelledInSource,
492 mapAnyOf(ifStmt, forStmt).with(hasCondition(falseExpr)))));
493
494 EXPECT_TRUE(
495 matches(Code, cxxBoolLiteral(equals(true),
496 hasAncestor(mapAnyOf(ifStmt, forStmt)))));
497
498 EXPECT_TRUE(
499 matches(Code, cxxBoolLiteral(equals(false),
500 hasAncestor(mapAnyOf(ifStmt, forStmt)))));
501
502 EXPECT_TRUE(
503 notMatches(Code, floatLiteral(hasAncestor(mapAnyOf(ifStmt, forStmt)))));
504
505 Code = R"cpp(
506void func(bool b) {}
507struct S {
508 S(bool b) {}
509};
510void F() {
511 func(false);
512 S s(true);
513}
514)cpp";
515 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
516 mapAnyOf(callExpr, cxxConstructExpr)
517 .with(hasArgument(0, trueExpr)))));
518 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
519 mapAnyOf(callExpr, cxxConstructExpr)
520 .with(hasArgument(0, falseExpr)))));
521
522 EXPECT_TRUE(
523 matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
524 mapAnyOf(callExpr, cxxConstructExpr)
525 .with(hasArgument(0, expr()),
526 hasDeclaration(functionDecl())))));
527
528 EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource,
529 mapAnyOf(callExpr, cxxConstructExpr))));
530
531 EXPECT_TRUE(matches(
532 Code, traverse(TK_IgnoreUnlessSpelledInSource,
533 mapAnyOf(callExpr, cxxConstructExpr).bind("call"))));
534
535 Code = R"cpp(
536struct HasOpNeqMem
537{
538 bool operator!=(const HasOpNeqMem& other) const
539 {
540 return true;
541 }
542};
543struct HasOpFree
544{
545};
546bool operator!=(const HasOpFree& lhs, const HasOpFree& rhs)
547{
548 return true;
549}
550
551void binop()
552{
553 int s1;
554 int s2;
555 if (s1 != s2)
556 return;
557}
558
559void opMem()
560{
561 HasOpNeqMem s1;
562 HasOpNeqMem s2;
563 if (s1 != s2)
564 return;
565}
566
567void opFree()
568{
569 HasOpFree s1;
570 HasOpFree s2;
571 if (s1 != s2)
572 return;
573}
574
575template<typename T>
576void templ()
577{
578 T s1;
579 T s2;
580 if (s1 != s2)
581 return;
582}
583)cpp";
584
585 EXPECT_TRUE(matches(
586 Code,
587 traverse(TK_IgnoreUnlessSpelledInSource,
588 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
589 .with(hasOperatorName("!="),
590 forFunction(functionDecl(hasName("binop"))),
591 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
592 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
593
594 EXPECT_TRUE(matches(
595 Code,
596 traverse(TK_IgnoreUnlessSpelledInSource,
597 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
598 .with(hasOperatorName("!="),
599 forFunction(functionDecl(hasName("opMem"))),
600 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
601 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
602
603 EXPECT_TRUE(matches(
604 Code,
605 traverse(TK_IgnoreUnlessSpelledInSource,
606 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
607 .with(hasOperatorName("!="),
608 forFunction(functionDecl(hasName("opFree"))),
609 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
610 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
611
612 EXPECT_TRUE(matches(
613 Code, traverse(TK_IgnoreUnlessSpelledInSource,
614 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
615 .with(hasOperatorName("!="),
616 forFunction(functionDecl(hasName("binop"))),
617 hasEitherOperand(
618 declRefExpr(to(varDecl(hasName("s1"))))),
619 hasEitherOperand(
620 declRefExpr(to(varDecl(hasName("s2")))))))));
621
622 EXPECT_TRUE(matches(
623 Code, traverse(TK_IgnoreUnlessSpelledInSource,
624 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
625 .with(hasOperatorName("!="),
626 forFunction(functionDecl(hasName("opMem"))),
627 hasEitherOperand(
628 declRefExpr(to(varDecl(hasName("s1"))))),
629 hasEitherOperand(
630 declRefExpr(to(varDecl(hasName("s2")))))))));
631
632 EXPECT_TRUE(matches(
633 Code, traverse(TK_IgnoreUnlessSpelledInSource,
634 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
635 .with(hasOperatorName("!="),
636 forFunction(functionDecl(hasName("opFree"))),
637 hasEitherOperand(
638 declRefExpr(to(varDecl(hasName("s1"))))),
639 hasEitherOperand(
640 declRefExpr(to(varDecl(hasName("s2")))))))));
641
642 EXPECT_TRUE(matches(
643 Code,
644 traverse(
645 TK_IgnoreUnlessSpelledInSource,
646 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
647 .with(hasOperatorName("!="),
648 forFunction(functionDecl(hasName("binop"))),
649 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
650 declRefExpr(to(varDecl(hasName("s2"))))),
651 hasOperands(declRefExpr(to(varDecl(hasName("s2")))),
652 declRefExpr(to(varDecl(hasName("s1")))))))));
653
654 EXPECT_TRUE(matches(
655 Code,
656 traverse(
657 TK_IgnoreUnlessSpelledInSource,
658 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
659 .with(hasOperatorName("!="),
660 forFunction(functionDecl(hasName("opMem"))),
661 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
662 declRefExpr(to(varDecl(hasName("s2"))))),
663 hasOperands(declRefExpr(to(varDecl(hasName("s2")))),
664 declRefExpr(to(varDecl(hasName("s1")))))))));
665
666 EXPECT_TRUE(matches(
667 Code,
668 traverse(
669 TK_IgnoreUnlessSpelledInSource,
670 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
671 .with(hasOperatorName("!="),
672 forFunction(functionDecl(hasName("opFree"))),
673 hasOperands(declRefExpr(to(varDecl(hasName("s1")))),
674 declRefExpr(to(varDecl(hasName("s2"))))),
675 hasOperands(declRefExpr(to(varDecl(hasName("s2")))),
676 declRefExpr(to(varDecl(hasName("s1")))))))));
677
678 EXPECT_TRUE(matches(
679 Code, traverse(TK_IgnoreUnlessSpelledInSource,
680 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
681 .with(hasAnyOperatorName("==", "!="),
682 forFunction(functionDecl(hasName("binop")))))));
683
684 EXPECT_TRUE(matches(
685 Code, traverse(TK_IgnoreUnlessSpelledInSource,
686 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
687 .with(hasAnyOperatorName("==", "!="),
688 forFunction(functionDecl(hasName("opMem")))))));
689
690 EXPECT_TRUE(matches(
691 Code, traverse(TK_IgnoreUnlessSpelledInSource,
692 mapAnyOf(binaryOperator, cxxOperatorCallExpr)
693 .with(hasAnyOperatorName("==", "!="),
694 forFunction(functionDecl(hasName("opFree")))))));
695
696 EXPECT_TRUE(matches(
697 Code, traverse(TK_IgnoreUnlessSpelledInSource,
698 binaryOperation(
699 hasOperatorName("!="),
700 forFunction(functionDecl(hasName("binop"))),
701 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
702 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
703
704 EXPECT_TRUE(matches(
705 Code, traverse(TK_IgnoreUnlessSpelledInSource,
706 binaryOperation(
707 hasOperatorName("!="),
708 forFunction(functionDecl(hasName("opMem"))),
709 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
710 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
711
712 EXPECT_TRUE(matches(
713 Code, traverse(TK_IgnoreUnlessSpelledInSource,
714 binaryOperation(
715 hasOperatorName("!="),
716 forFunction(functionDecl(hasName("opFree"))),
717 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
718 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
719
720 EXPECT_TRUE(matches(
721 Code, traverse(TK_IgnoreUnlessSpelledInSource,
722 binaryOperation(
723 hasOperatorName("!="),
724 forFunction(functionDecl(hasName("templ"))),
725 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
726 hasRHS(declRefExpr(to(varDecl(hasName("s2")))))))));
727
728 Code = R"cpp(
729struct HasOpEq
730{
731 bool operator==(const HasOpEq &) const;
732};
733
734void inverse()
735{
736 HasOpEq s1;
737 HasOpEq s2;
738 if (s1 != s2)
739 return;
740}
741
742namespace std {
743struct strong_ordering {
744 int n;
745 constexpr operator int() const { return n; }
746 static const strong_ordering equal, greater, less;
747};
748constexpr strong_ordering strong_ordering::equal = {0};
749constexpr strong_ordering strong_ordering::greater = {1};
750constexpr strong_ordering strong_ordering::less = {-1};
751}
752
753struct HasSpaceshipMem {
754 int a;
755 constexpr auto operator<=>(const HasSpaceshipMem&) const = default;
756};
757
758void rewritten()
759{
760 HasSpaceshipMem s1;
761 HasSpaceshipMem s2;
762 if (s1 != s2)
763 return;
764}
765)cpp";
766
767 EXPECT_TRUE(matchesConditionally(
768 Code,
769 traverse(
770 TK_IgnoreUnlessSpelledInSource,
771 binaryOperation(hasOperatorName("!="),
772 forFunction(functionDecl(hasName("inverse"))),
773 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
774 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))))),
775 true, {"-std=c++20"}));
776
777 EXPECT_TRUE(matchesConditionally(
778 Code,
779 traverse(
780 TK_IgnoreUnlessSpelledInSource,
781 binaryOperation(hasOperatorName("!="),
782 forFunction(functionDecl(hasName("rewritten"))),
783 hasLHS(declRefExpr(to(varDecl(hasName("s1"))))),
784 hasRHS(declRefExpr(to(varDecl(hasName("s2"))))))),
785 true, {"-std=c++20"}));
786
787 Code = R"cpp(
788struct HasOpBangMem
789{
790 bool operator!() const
791 {
792 return false;
793 }
794};
795struct HasOpBangFree
796{
797};
798bool operator!(HasOpBangFree const&)
799{
800 return false;
801}
802
803void unop()
804{
805 int s1;
806 if (!s1)
807 return;
808}
809
810void opMem()
811{
812 HasOpBangMem s1;
813 if (!s1)
814 return;
815}
816
817void opFree()
818{
819 HasOpBangFree s1;
820 if (!s1)
821 return;
822}
823)cpp";
824
825 EXPECT_TRUE(matches(
826 Code, traverse(TK_IgnoreUnlessSpelledInSource,
827 mapAnyOf(unaryOperator, cxxOperatorCallExpr)
828 .with(hasOperatorName("!"),
829 forFunction(functionDecl(hasName("unop"))),
830 hasUnaryOperand(
831 declRefExpr(to(varDecl(hasName("s1")))))))));
832
833 EXPECT_TRUE(matches(
834 Code, traverse(TK_IgnoreUnlessSpelledInSource,
835 mapAnyOf(unaryOperator, cxxOperatorCallExpr)
836 .with(hasOperatorName("!"),
837 forFunction(functionDecl(hasName("opMem"))),
838 hasUnaryOperand(
839 declRefExpr(to(varDecl(hasName("s1")))))))));
840
841 EXPECT_TRUE(matches(
842 Code, traverse(TK_IgnoreUnlessSpelledInSource,
843 mapAnyOf(unaryOperator, cxxOperatorCallExpr)
844 .with(hasOperatorName("!"),
845 forFunction(functionDecl(hasName("opFree"))),
846 hasUnaryOperand(
847 declRefExpr(to(varDecl(hasName("s1")))))))));
848
849 EXPECT_TRUE(matches(
850 Code, traverse(TK_IgnoreUnlessSpelledInSource,
851 mapAnyOf(unaryOperator, cxxOperatorCallExpr)
852 .with(hasAnyOperatorName("+", "!"),
853 forFunction(functionDecl(hasName("unop")))))));
854
855 EXPECT_TRUE(matches(
856 Code, traverse(TK_IgnoreUnlessSpelledInSource,
857 mapAnyOf(unaryOperator, cxxOperatorCallExpr)
858 .with(hasAnyOperatorName("+", "!"),
859 forFunction(functionDecl(hasName("opMem")))))));
860
861 EXPECT_TRUE(matches(
862 Code, traverse(TK_IgnoreUnlessSpelledInSource,
863 mapAnyOf(unaryOperator, cxxOperatorCallExpr)
864 .with(hasAnyOperatorName("+", "!"),
865 forFunction(functionDecl(hasName("opFree")))))));
866
867 Code = R"cpp(
868struct ConstructorTakesInt
869{
870 ConstructorTakesInt(int i) {}
871};
872
873void callTakesInt(int i)
874{
875
876}
877
878void doCall()
879{
880 callTakesInt(42);
881}
882
883void doConstruct()
884{
885 ConstructorTakesInt cti(42);
886}
887)cpp";
888
889 EXPECT_TRUE(matches(
890 Code, traverse(TK_IgnoreUnlessSpelledInSource,
891 invocation(forFunction(functionDecl(hasName("doCall"))),
892 hasArgument(0, integerLiteral(equals(42))),
893 hasAnyArgument(integerLiteral(equals(42))),
894 forEachArgumentWithParam(
895 integerLiteral(equals(42)),
896 parmVarDecl(hasName("i")))))));
897
898 EXPECT_TRUE(matches(
899 Code,
900 traverse(
901 TK_IgnoreUnlessSpelledInSource,
902 invocation(forFunction(functionDecl(hasName("doConstruct"))),
903 hasArgument(0, integerLiteral(equals(42))),
904 hasAnyArgument(integerLiteral(equals(42))),
905 forEachArgumentWithParam(integerLiteral(equals(42)),
906 parmVarDecl(hasName("i")))))));
907}
908
909TEST_P(ASTMatchersTest, IsDerivedFrom) {
910 if (!GetParam().isCXX()) {
911 return;
912 }
913
914 DeclarationMatcher IsDerivedFromX = cxxRecordDecl(isDerivedFrom(BaseName: "X"));
915
916 EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX));
917 EXPECT_TRUE(notMatches("class X {};", IsDerivedFromX));
918 EXPECT_TRUE(notMatches("class X;", IsDerivedFromX));
919 EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
920 EXPECT_TRUE(notMatches("", IsDerivedFromX));
921 EXPECT_TRUE(matches("class X {}; template<int N> class Y : Y<N-1>, X {};",
922 IsDerivedFromX));
923 EXPECT_TRUE(matches("class X {}; template<int N> class Y : X, Y<N-1> {};",
924 IsDerivedFromX));
925
926 DeclarationMatcher IsZDerivedFromX =
927 cxxRecordDecl(hasName(Name: "Z"), isDerivedFrom(BaseName: "X"));
928 EXPECT_TRUE(matches("class X {};"
929 "template<int N> class Y : Y<N-1> {};"
930 "template<> class Y<0> : X {};"
931 "class Z : Y<1> {};",
932 IsZDerivedFromX));
933
934 DeclarationMatcher IsDirectlyDerivedFromX =
935 cxxRecordDecl(isDirectlyDerivedFrom(BaseName: "X"));
936
937 EXPECT_TRUE(
938 matches("class X {}; class Y : public X {};", IsDirectlyDerivedFromX));
939 EXPECT_TRUE(notMatches("class X {};", IsDirectlyDerivedFromX));
940 EXPECT_TRUE(notMatches("class X;", IsDirectlyDerivedFromX));
941 EXPECT_TRUE(notMatches("class Y;", IsDirectlyDerivedFromX));
942 EXPECT_TRUE(notMatches("", IsDirectlyDerivedFromX));
943
944 DeclarationMatcher IsAX = cxxRecordDecl(isSameOrDerivedFrom(BaseName: "X"));
945
946 EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsAX));
947 EXPECT_TRUE(matches("class X {};", IsAX));
948 EXPECT_TRUE(matches("class X;", IsAX));
949 EXPECT_TRUE(notMatches("class Y;", IsAX));
950 EXPECT_TRUE(notMatches("", IsAX));
951
952 DeclarationMatcher ZIsDerivedFromX =
953 cxxRecordDecl(hasName(Name: "Z"), isDerivedFrom(BaseName: "X"));
954 DeclarationMatcher ZIsDirectlyDerivedFromX =
955 cxxRecordDecl(hasName(Name: "Z"), isDirectlyDerivedFrom(BaseName: "X"));
956 EXPECT_TRUE(
957 matches("class X {}; class Y : public X {}; class Z : public Y {};",
958 ZIsDerivedFromX));
959 EXPECT_TRUE(
960 notMatches("class X {}; class Y : public X {}; class Z : public Y {};",
961 ZIsDirectlyDerivedFromX));
962 EXPECT_TRUE(matches("class X {};"
963 "template<class T> class Y : public X {};"
964 "class Z : public Y<int> {};",
965 ZIsDerivedFromX));
966 EXPECT_TRUE(notMatches("class X {};"
967 "template<class T> class Y : public X {};"
968 "class Z : public Y<int> {};",
969 ZIsDirectlyDerivedFromX));
970 EXPECT_TRUE(matches("class X {}; template<class T> class Z : public X {};",
971 ZIsDerivedFromX));
972 EXPECT_TRUE(matches("template<class T> class X {}; "
973 "template<class T> class Z : public X<T> {};",
974 ZIsDerivedFromX));
975 EXPECT_TRUE(matches("template<class T, class U=T> class X {}; "
976 "template<class T> class Z : public X<T> {};",
977 ZIsDerivedFromX));
978 EXPECT_TRUE(
979 notMatches("template<class X> class A { class Z : public X {}; };",
980 ZIsDerivedFromX));
981 EXPECT_TRUE(
982 matches("template<class X> class A { public: class Z : public X {}; }; "
983 "class X{}; void y() { A<X>::Z z; }",
984 ZIsDerivedFromX));
985 EXPECT_TRUE(
986 matches("template <class T> class X {}; "
987 "template<class Y> class A { class Z : public X<Y> {}; };",
988 ZIsDerivedFromX));
989 EXPECT_TRUE(notMatches("template<template<class T> class X> class A { "
990 " class Z : public X<int> {}; };",
991 ZIsDerivedFromX));
992 EXPECT_TRUE(matches("template<template<class T> class X> class A { "
993 " public: class Z : public X<int> {}; }; "
994 "template<class T> class X {}; void y() { A<X>::Z z; }",
995 ZIsDerivedFromX));
996 EXPECT_TRUE(
997 notMatches("template<class X> class A { class Z : public X::D {}; };",
998 ZIsDerivedFromX));
999 EXPECT_TRUE(matches("template<class X> class A { public: "
1000 " class Z : public X::D {}; }; "
1001 "class Y { public: class X {}; typedef X D; }; "
1002 "void y() { A<Y>::Z z; }",
1003 ZIsDerivedFromX));
1004 EXPECT_TRUE(matches("class X {}; typedef X Y; class Z : public Y {};",
1005 ZIsDerivedFromX));
1006 EXPECT_TRUE(matches("template<class T> class Y { typedef typename T::U X; "
1007 " class Z : public X {}; };",
1008 ZIsDerivedFromX));
1009 EXPECT_TRUE(matches("class X {}; class Z : public ::X {};", ZIsDerivedFromX));
1010 EXPECT_TRUE(
1011 notMatches("template<class T> class X {}; "
1012 "template<class T> class A { class Z : public X<T>::D {}; };",
1013 ZIsDerivedFromX));
1014 EXPECT_TRUE(
1015 matches("template<class T> class X { public: typedef X<T> D; }; "
1016 "template<class T> class A { public: "
1017 " class Z : public X<T>::D {}; }; void y() { A<int>::Z z; }",
1018 ZIsDerivedFromX));
1019 EXPECT_TRUE(
1020 notMatches("template<class X> class A { class Z : public X::D::E {}; };",
1021 ZIsDerivedFromX));
1022 EXPECT_TRUE(
1023 matches("class X {}; typedef X V; typedef V W; class Z : public W {};",
1024 ZIsDerivedFromX));
1025 EXPECT_TRUE(matches("class X {}; class Y : public X {}; "
1026 "typedef Y V; typedef V W; class Z : public W {};",
1027 ZIsDerivedFromX));
1028 EXPECT_TRUE(notMatches("class X {}; class Y : public X {}; "
1029 "typedef Y V; typedef V W; class Z : public W {};",
1030 ZIsDirectlyDerivedFromX));
1031 EXPECT_TRUE(
1032 matches("template<class T, class U> class X {}; "
1033 "template<class T> class A { class Z : public X<T, int> {}; };",
1034 ZIsDerivedFromX));
1035 EXPECT_TRUE(
1036 notMatches("template<class X> class D { typedef X A; typedef A B; "
1037 " typedef B C; class Z : public C {}; };",
1038 ZIsDerivedFromX));
1039 EXPECT_TRUE(matches("class X {}; typedef X A; typedef A B; "
1040 "class Z : public B {};",
1041 ZIsDerivedFromX));
1042 EXPECT_TRUE(matches("class X {}; typedef X A; typedef A B; typedef B C; "
1043 "class Z : public C {};",
1044 ZIsDerivedFromX));
1045 EXPECT_TRUE(matches("class U {}; typedef U X; typedef X V; "
1046 "class Z : public V {};",
1047 ZIsDerivedFromX));
1048 EXPECT_TRUE(matches("class Base {}; typedef Base X; "
1049 "class Z : public Base {};",
1050 ZIsDerivedFromX));
1051 EXPECT_TRUE(matches("class Base {}; typedef Base Base2; typedef Base2 X; "
1052 "class Z : public Base {};",
1053 ZIsDerivedFromX));
1054 EXPECT_TRUE(notMatches("class Base {}; class Base2 {}; typedef Base2 X; "
1055 "class Z : public Base {};",
1056 ZIsDerivedFromX));
1057 EXPECT_TRUE(matches("class A {}; typedef A X; typedef A Y; "
1058 "class Z : public Y {};",
1059 ZIsDerivedFromX));
1060 EXPECT_TRUE(notMatches("template <typename T> class Z;"
1061 "template <> class Z<void> {};"
1062 "template <typename T> class Z : public Z<void> {};",
1063 IsDerivedFromX));
1064 EXPECT_TRUE(matches("template <typename T> class X;"
1065 "template <> class X<void> {};"
1066 "template <typename T> class X : public X<void> {};",
1067 IsDerivedFromX));
1068 EXPECT_TRUE(
1069 matches("class X {};"
1070 "template <typename T> class Z;"
1071 "template <> class Z<void> {};"
1072 "template <typename T> class Z : public Z<void>, public X {};",
1073 ZIsDerivedFromX));
1074 EXPECT_TRUE(
1075 notMatches("template<int> struct X;"
1076 "template<int i> struct X : public X<i-1> {};",
1077 cxxRecordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
1078 EXPECT_TRUE(matches(
1079 "struct A {};"
1080 "template<int> struct X;"
1081 "template<int i> struct X : public X<i-1> {};"
1082 "template<> struct X<0> : public A {};"
1083 "struct B : public X<42> {};",
1084 cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
1085 EXPECT_TRUE(notMatches(
1086 "struct A {};"
1087 "template<int> struct X;"
1088 "template<int i> struct X : public X<i-1> {};"
1089 "template<> struct X<0> : public A {};"
1090 "struct B : public X<42> {};",
1091 cxxRecordDecl(hasName("B"),
1092 isDirectlyDerivedFrom(recordDecl(hasName("A"))))));
1093
1094 // FIXME: Once we have better matchers for template type matching,
1095 // get rid of the Variable(...) matching and match the right template
1096 // declarations directly.
1097 const char *RecursiveTemplateOneParameter =
1098 "class Base1 {}; class Base2 {};"
1099 "template <typename T> class Z;"
1100 "template <> class Z<void> : public Base1 {};"
1101 "template <> class Z<int> : public Base2 {};"
1102 "template <> class Z<float> : public Z<void> {};"
1103 "template <> class Z<double> : public Z<int> {};"
1104 "template <typename T> class Z : public Z<float>, public Z<double> {};"
1105 "void f() { Z<float> z_float; Z<double> z_double; Z<char> z_char; }";
1106 EXPECT_TRUE(matches(
1107 RecursiveTemplateOneParameter,
1108 varDecl(hasName("z_float"),
1109 hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
1110 EXPECT_TRUE(notMatches(
1111 RecursiveTemplateOneParameter,
1112 varDecl(hasName("z_float"),
1113 hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
1114 EXPECT_TRUE(
1115 matches(RecursiveTemplateOneParameter,
1116 varDecl(hasName("z_char"),
1117 hasInitializer(hasType(cxxRecordDecl(
1118 isDerivedFrom("Base1"), isDerivedFrom("Base2")))))));
1119
1120 const char *RecursiveTemplateTwoParameters =
1121 "class Base1 {}; class Base2 {};"
1122 "template <typename T1, typename T2> class Z;"
1123 "template <typename T> class Z<void, T> : public Base1 {};"
1124 "template <typename T> class Z<int, T> : public Base2 {};"
1125 "template <typename T> class Z<float, T> : public Z<void, T> {};"
1126 "template <typename T> class Z<double, T> : public Z<int, T> {};"
1127 "template <typename T1, typename T2> class Z : "
1128 " public Z<float, T2>, public Z<double, T2> {};"
1129 "void f() { Z<float, void> z_float; Z<double, void> z_double; "
1130 " Z<char, void> z_char; }";
1131 EXPECT_TRUE(matches(
1132 RecursiveTemplateTwoParameters,
1133 varDecl(hasName("z_float"),
1134 hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
1135 EXPECT_TRUE(notMatches(
1136 RecursiveTemplateTwoParameters,
1137 varDecl(hasName("z_float"),
1138 hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
1139 EXPECT_TRUE(
1140 matches(RecursiveTemplateTwoParameters,
1141 varDecl(hasName("z_char"),
1142 hasInitializer(hasType(cxxRecordDecl(
1143 isDerivedFrom("Base1"), isDerivedFrom("Base2")))))));
1144 EXPECT_TRUE(matches("namespace ns { class X {}; class Y : public X {}; }",
1145 cxxRecordDecl(isDerivedFrom("::ns::X"))));
1146 EXPECT_TRUE(notMatches("class X {}; class Y : public X {};",
1147 cxxRecordDecl(isDerivedFrom("::ns::X"))));
1148
1149 EXPECT_TRUE(matches(
1150 "class X {}; class Y : public X {};",
1151 cxxRecordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
1152
1153 EXPECT_TRUE(matches("template<typename T> class X {};"
1154 "template<typename T> using Z = X<T>;"
1155 "template <typename T> class Y : Z<T> {};",
1156 cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
1157}
1158
1159TEST_P(ASTMatchersTest, IsDerivedFrom_EmptyName) {
1160 if (!GetParam().isCXX()) {
1161 return;
1162 }
1163
1164 const char *const Code = "class X {}; class Y : public X {};";
1165 EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isDerivedFrom(""))));
1166 EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isDirectlyDerivedFrom(""))));
1167 EXPECT_TRUE(notMatches(Code, cxxRecordDecl(isSameOrDerivedFrom(""))));
1168}
1169
1170TEST_P(ASTMatchersTest, IsDerivedFrom_ElaboratedType) {
1171 if (!GetParam().isCXX()) {
1172 return;
1173 }
1174
1175 DeclarationMatcher IsDerivenFromBase =
1176 cxxRecordDecl(isDerivedFrom(Base: decl().bind(ID: "typedef")));
1177
1178 EXPECT_TRUE(matchAndVerifyResultTrue(
1179 "struct AnInterface {};"
1180 "typedef AnInterface UnusedTypedef;"
1181 "typedef AnInterface Base;"
1182 "class AClass : public Base {};",
1183 IsDerivenFromBase,
1184 std::make_unique<VerifyIdIsBoundTo<TypedefDecl>>("typedef", "Base")));
1185}
1186
1187TEST_P(ASTMatchersTest, IsDerivedFrom_ObjC) {
1188 DeclarationMatcher IsDerivedFromX = objcInterfaceDecl(isDerivedFrom(BaseName: "X"));
1189 EXPECT_TRUE(
1190 matchesObjC("@interface X @end @interface Y : X @end", IsDerivedFromX));
1191 EXPECT_TRUE(matchesObjC(
1192 "@interface X @end @interface Y<__covariant ObjectType> : X @end",
1193 IsDerivedFromX));
1194 EXPECT_TRUE(matchesObjC(
1195 "@interface X @end @compatibility_alias Y X; @interface Z : Y @end",
1196 IsDerivedFromX));
1197 EXPECT_TRUE(matchesObjC(
1198 "@interface X @end typedef X Y; @interface Z : Y @end", IsDerivedFromX));
1199 EXPECT_TRUE(notMatchesObjC("@interface X @end", IsDerivedFromX));
1200 EXPECT_TRUE(notMatchesObjC("@class X;", IsDerivedFromX));
1201 EXPECT_TRUE(notMatchesObjC("@class Y;", IsDerivedFromX));
1202 EXPECT_TRUE(notMatchesObjC("@interface X @end @compatibility_alias Y X;",
1203 IsDerivedFromX));
1204 EXPECT_TRUE(notMatchesObjC("@interface X @end typedef X Y;", IsDerivedFromX));
1205
1206 DeclarationMatcher IsDirectlyDerivedFromX =
1207 objcInterfaceDecl(isDirectlyDerivedFrom(BaseName: "X"));
1208 EXPECT_TRUE(matchesObjC("@interface X @end @interface Y : X @end",
1209 IsDirectlyDerivedFromX));
1210 EXPECT_TRUE(matchesObjC(
1211 "@interface X @end @interface Y<__covariant ObjectType> : X @end",
1212 IsDirectlyDerivedFromX));
1213 EXPECT_TRUE(matchesObjC(
1214 "@interface X @end @compatibility_alias Y X; @interface Z : Y @end",
1215 IsDirectlyDerivedFromX));
1216 EXPECT_TRUE(
1217 matchesObjC("@interface X @end typedef X Y; @interface Z : Y @end",
1218 IsDirectlyDerivedFromX));
1219 EXPECT_TRUE(notMatchesObjC("@interface X @end", IsDirectlyDerivedFromX));
1220 EXPECT_TRUE(notMatchesObjC("@class X;", IsDirectlyDerivedFromX));
1221 EXPECT_TRUE(notMatchesObjC("@class Y;", IsDirectlyDerivedFromX));
1222 EXPECT_TRUE(notMatchesObjC("@interface X @end @compatibility_alias Y X;",
1223 IsDirectlyDerivedFromX));
1224 EXPECT_TRUE(
1225 notMatchesObjC("@interface X @end typedef X Y;", IsDirectlyDerivedFromX));
1226
1227 DeclarationMatcher IsAX = objcInterfaceDecl(isSameOrDerivedFrom(BaseName: "X"));
1228 EXPECT_TRUE(matchesObjC("@interface X @end @interface Y : X @end", IsAX));
1229 EXPECT_TRUE(matchesObjC("@interface X @end", IsAX));
1230 EXPECT_TRUE(matchesObjC("@class X;", IsAX));
1231 EXPECT_TRUE(notMatchesObjC("@interface Y @end", IsAX));
1232 EXPECT_TRUE(notMatchesObjC("@class Y;", IsAX));
1233
1234 DeclarationMatcher ZIsDerivedFromX =
1235 objcInterfaceDecl(hasName(Name: "Z"), isDerivedFrom(BaseName: "X"));
1236 DeclarationMatcher ZIsDirectlyDerivedFromX =
1237 objcInterfaceDecl(hasName(Name: "Z"), isDirectlyDerivedFrom(BaseName: "X"));
1238 EXPECT_TRUE(matchesObjC(
1239 "@interface X @end @interface Y : X @end @interface Z : Y @end",
1240 ZIsDerivedFromX));
1241 EXPECT_TRUE(matchesObjC("@interface X @end @interface Y : X @end typedef Y "
1242 "V; typedef V W; @interface Z : W @end",
1243 ZIsDerivedFromX));
1244 EXPECT_TRUE(matchesObjC(
1245 "@interface X @end typedef X Y; @interface Z : Y @end", ZIsDerivedFromX));
1246 EXPECT_TRUE(
1247 matchesObjC("@interface X @end typedef X Y; @interface Z : Y @end",
1248 ZIsDirectlyDerivedFromX));
1249 EXPECT_TRUE(matchesObjC(
1250 "@interface A @end typedef A X; typedef A Y; @interface Z : Y @end",
1251 ZIsDerivedFromX));
1252 EXPECT_TRUE(matchesObjC(
1253 "@interface A @end typedef A X; typedef A Y; @interface Z : Y @end",
1254 ZIsDirectlyDerivedFromX));
1255 EXPECT_TRUE(matchesObjC(
1256 "@interface X @end @compatibility_alias Y X; @interface Z : Y @end",
1257 ZIsDerivedFromX));
1258 EXPECT_TRUE(matchesObjC(
1259 "@interface X @end @compatibility_alias Y X; @interface Z : Y @end",
1260 ZIsDirectlyDerivedFromX));
1261 EXPECT_TRUE(matchesObjC(
1262 "@interface Y @end @compatibility_alias X Y; @interface Z : Y @end",
1263 ZIsDerivedFromX));
1264 EXPECT_TRUE(matchesObjC(
1265 "@interface Y @end @compatibility_alias X Y; @interface Z : Y @end",
1266 ZIsDirectlyDerivedFromX));
1267 EXPECT_TRUE(matchesObjC(
1268 "@interface A @end @compatibility_alias X A; @compatibility_alias Y A;"
1269 "@interface Z : Y @end",
1270 ZIsDerivedFromX));
1271 EXPECT_TRUE(matchesObjC(
1272 "@interface A @end @compatibility_alias X A; @compatibility_alias Y A;"
1273 "@interface Z : Y @end",
1274 ZIsDirectlyDerivedFromX));
1275 EXPECT_TRUE(matchesObjC(
1276 "@interface Y @end typedef Y X; @interface Z : X @end", ZIsDerivedFromX));
1277 EXPECT_TRUE(
1278 matchesObjC("@interface Y @end typedef Y X; @interface Z : X @end",
1279 ZIsDirectlyDerivedFromX));
1280 EXPECT_TRUE(
1281 matchesObjC("@interface A @end @compatibility_alias Y A; typedef Y X;"
1282 "@interface Z : A @end",
1283 ZIsDerivedFromX));
1284 EXPECT_TRUE(
1285 matchesObjC("@interface A @end @compatibility_alias Y A; typedef Y X;"
1286 "@interface Z : A @end",
1287 ZIsDirectlyDerivedFromX));
1288 EXPECT_TRUE(
1289 matchesObjC("@interface A @end typedef A Y; @compatibility_alias X Y;"
1290 "@interface Z : A @end",
1291 ZIsDerivedFromX));
1292 EXPECT_TRUE(
1293 matchesObjC("@interface A @end typedef A Y; @compatibility_alias X Y;"
1294 "@interface Z : A @end",
1295 ZIsDirectlyDerivedFromX));
1296}
1297
1298TEST_P(ASTMatchersTest, IsLambda) {
1299 if (!GetParam().isCXX11OrLater()) {
1300 return;
1301 }
1302
1303 const auto IsLambda = cxxMethodDecl(ofClass(InnerMatcher: cxxRecordDecl(isLambda())));
1304 EXPECT_TRUE(matches("auto x = []{};", IsLambda));
1305 EXPECT_TRUE(notMatches("struct S { void operator()() const; };", IsLambda));
1306}
1307
1308TEST_P(ASTMatchersTest, Bind) {
1309 DeclarationMatcher ClassX = has(recordDecl(hasName(Name: "::X")).bind(ID: "x"));
1310
1311 EXPECT_TRUE(matchAndVerifyResultTrue(
1312 "class X {};", ClassX,
1313 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x")));
1314
1315 EXPECT_TRUE(matchAndVerifyResultFalse(
1316 "class X {};", ClassX,
1317 std::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("other-id")));
1318
1319 TypeMatcher TypeAHasClassB = hasDeclaration(
1320 InnerMatcher: recordDecl(hasName(Name: "A"), has(recordDecl(hasName(Name: "B")).bind(ID: "b"))));
1321
1322 EXPECT_TRUE(matchAndVerifyResultTrue(
1323 "class A { public: A *a; class B {}; };", TypeAHasClassB,
1324 std::make_unique<VerifyIdIsBoundTo<Decl>>("b")));
1325
1326 StatementMatcher MethodX =
1327 callExpr(callee(InnerMatcher: cxxMethodDecl(hasName(Name: "x")))).bind(ID: "x");
1328
1329 EXPECT_TRUE(matchAndVerifyResultTrue(
1330 "class A { void x() { x(); } };", MethodX,
1331 std::make_unique<VerifyIdIsBoundTo<CXXMemberCallExpr>>("x")));
1332}
1333
1334TEST_P(ASTMatchersTest, Bind_SameNameInAlternatives) {
1335 StatementMatcher matcher = anyOf(
1336 binaryOperator(hasOperatorName(Name: "+"), hasLHS(InnerMatcher: expr().bind(ID: "x")),
1337 hasRHS(InnerMatcher: integerLiteral(equals(Value: 0)))),
1338 binaryOperator(hasOperatorName(Name: "+"), hasLHS(InnerMatcher: integerLiteral(equals(Value: 0))),
1339 hasRHS(InnerMatcher: expr().bind(ID: "x"))));
1340
1341 EXPECT_TRUE(matchAndVerifyResultTrue(
1342 // The first branch of the matcher binds x to 0 but then fails.
1343 // The second branch binds x to f() and succeeds.
1344 "int f() { return 0 + f(); }", matcher,
1345 std::make_unique<VerifyIdIsBoundTo<CallExpr>>("x")));
1346}
1347
1348TEST_P(ASTMatchersTest, Bind_BindsIDForMemoizedResults) {
1349 // Using the same matcher in two match expressions will make memoization
1350 // kick in.
1351 DeclarationMatcher ClassX = recordDecl(hasName(Name: "X")).bind(ID: "x");
1352 EXPECT_TRUE(matchAndVerifyResultTrue(
1353 "class A { class B { class X {}; }; };",
1354 DeclarationMatcher(
1355 anyOf(recordDecl(hasName("A"), hasDescendant(ClassX)),
1356 recordDecl(hasName("B"), hasDescendant(ClassX)))),
1357 std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 2)));
1358}
1359
1360TEST_P(ASTMatchersTest, HasType_MatchesAsString) {
1361 if (!GetParam().isCXX()) {
1362 // FIXME: Add a test for `hasType()` that does not depend on C++.
1363 return;
1364 }
1365
1366 EXPECT_TRUE(
1367 matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
1368 cxxMemberCallExpr(on(hasType(asString("Y *"))))));
1369 EXPECT_TRUE(
1370 matches("class X { void x(int x) {} };",
1371 cxxMethodDecl(hasParameter(0, hasType(asString("int"))))));
1372 EXPECT_TRUE(matches("namespace ns { struct A {}; } struct B { ns::A a; };",
1373 fieldDecl(hasType(asString("ns::A")))));
1374 EXPECT_TRUE(matches("namespace { struct A {}; } struct B { A a; };",
1375 fieldDecl(hasType(asString("A")))));
1376}
1377
1378TEST_P(ASTMatchersTest, HasOverloadedOperatorName) {
1379 if (!GetParam().isCXX()) {
1380 return;
1381 }
1382
1383 StatementMatcher OpCallAndAnd =
1384 cxxOperatorCallExpr(hasOverloadedOperatorName(Name: "&&"));
1385 EXPECT_TRUE(matches("class Y { }; "
1386 "bool operator&&(Y x, Y y) { return true; }; "
1387 "Y a; Y b; bool c = a && b;",
1388 OpCallAndAnd));
1389 StatementMatcher OpCallLessLess =
1390 cxxOperatorCallExpr(hasOverloadedOperatorName(Name: "<<"));
1391 EXPECT_TRUE(notMatches("class Y { }; "
1392 "bool operator&&(Y x, Y y) { return true; }; "
1393 "Y a; Y b; bool c = a && b;",
1394 OpCallLessLess));
1395 StatementMatcher OpStarCall =
1396 cxxOperatorCallExpr(hasOverloadedOperatorName(Name: "*"));
1397 EXPECT_TRUE(
1398 matches("class Y; int operator*(Y &); void f(Y &y) { *y; }", OpStarCall));
1399 DeclarationMatcher ClassWithOpStar =
1400 cxxRecordDecl(hasMethod(InnerMatcher: hasOverloadedOperatorName(Name: "*")));
1401 EXPECT_TRUE(matches("class Y { int operator*(); };", ClassWithOpStar));
1402 EXPECT_TRUE(notMatches("class Y { void myOperator(); };", ClassWithOpStar));
1403 DeclarationMatcher AnyOpStar = functionDecl(hasOverloadedOperatorName(Name: "*"));
1404 EXPECT_TRUE(matches("class Y; int operator*(Y &);", AnyOpStar));
1405 EXPECT_TRUE(matches("class Y { int operator*(); };", AnyOpStar));
1406 DeclarationMatcher AnyAndOp =
1407 functionDecl(hasAnyOverloadedOperatorName("&", "&&"));
1408 EXPECT_TRUE(matches("class Y; Y operator&(Y &, Y &);", AnyAndOp));
1409 EXPECT_TRUE(matches("class Y; Y operator&&(Y &, Y &);", AnyAndOp));
1410 EXPECT_TRUE(matches("class Y { Y operator&(Y &); };", AnyAndOp));
1411 EXPECT_TRUE(matches("class Y { Y operator&&(Y &); };", AnyAndOp));
1412}
1413
1414TEST_P(ASTMatchersTest, HasOverloadedOperatorName_MatchesNestedCalls) {
1415 if (!GetParam().isCXX()) {
1416 return;
1417 }
1418
1419 EXPECT_TRUE(matchAndVerifyResultTrue(
1420 "class Y { }; "
1421 "Y& operator&&(Y& x, Y& y) { return x; }; "
1422 "Y a; Y b; Y c; Y d = a && b && c;",
1423 cxxOperatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
1424 std::make_unique<VerifyIdIsBoundTo<CXXOperatorCallExpr>>("x", 2)));
1425 EXPECT_TRUE(matches("class Y { }; "
1426 "Y& operator&&(Y& x, Y& y) { return x; }; "
1427 "Y a; Y b; Y c; Y d = a && b && c;",
1428 cxxOperatorCallExpr(hasParent(cxxOperatorCallExpr()))));
1429 EXPECT_TRUE(
1430 matches("class Y { }; "
1431 "Y& operator&&(Y& x, Y& y) { return x; }; "
1432 "Y a; Y b; Y c; Y d = a && b && c;",
1433 cxxOperatorCallExpr(hasDescendant(cxxOperatorCallExpr()))));
1434}
1435
1436TEST_P(ASTMatchersTest, HasLocalStorage) {
1437 auto M = varDecl(hasName(Name: "X"), hasLocalStorage());
1438 EXPECT_TRUE(matches("void f() { int X; }", M));
1439 EXPECT_TRUE(notMatches("int X;", M));
1440 EXPECT_TRUE(notMatches("void f() { static int X; }", M));
1441}
1442
1443TEST_P(ASTMatchersTest, HasGlobalStorage) {
1444 auto M = varDecl(hasName(Name: "X"), hasGlobalStorage());
1445 EXPECT_TRUE(notMatches("void f() { int X; }", M));
1446 EXPECT_TRUE(matches("int X;", M));
1447 EXPECT_TRUE(matches("void f() { static int X; }", M));
1448}
1449
1450TEST_P(ASTMatchersTest, IsStaticLocal) {
1451 auto M = varDecl(isStaticLocal());
1452 EXPECT_TRUE(matches("void f() { static int X; }", M));
1453 EXPECT_TRUE(notMatches("static int X;", M));
1454 EXPECT_TRUE(notMatches("void f() { int X; }", M));
1455 EXPECT_TRUE(notMatches("int X;", M));
1456}
1457
1458TEST_P(ASTMatchersTest, IsInitCapture) {
1459 if (!GetParam().isCXX11OrLater()) {
1460 return;
1461 }
1462 auto M = varDecl(hasName(Name: "vd"), isInitCapture());
1463 EXPECT_TRUE(notMatches(
1464 "int main() { int vd = 3; auto f = [vd]() { return vd; }; }", M));
1465
1466 if (!GetParam().isCXX14OrLater()) {
1467 return;
1468 }
1469 EXPECT_TRUE(matches("int main() { auto f = [vd=3]() { return vd; }; }", M));
1470 EXPECT_TRUE(matches(
1471 "int main() { int x = 3; auto f = [vd=x]() { return vd; }; }", M));
1472}
1473
1474TEST_P(ASTMatchersTest, StorageDuration) {
1475 StringRef T =
1476 "void f() { int x; static int y; } int a;static int b;extern int c;";
1477
1478 EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration())));
1479 EXPECT_TRUE(
1480 notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration())));
1481 EXPECT_TRUE(
1482 notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration())));
1483
1484 EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration())));
1485 EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration())));
1486 EXPECT_TRUE(matches(T, varDecl(hasName("b"), hasStaticStorageDuration())));
1487 EXPECT_TRUE(matches(T, varDecl(hasName("c"), hasStaticStorageDuration())));
1488 EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasStaticStorageDuration())));
1489
1490 // FIXME: Add thread_local variables to the source code snippet.
1491 EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasThreadStorageDuration())));
1492 EXPECT_TRUE(notMatches(T, varDecl(hasName("y"), hasThreadStorageDuration())));
1493 EXPECT_TRUE(notMatches(T, varDecl(hasName("a"), hasThreadStorageDuration())));
1494}
1495
1496TEST_P(ASTMatchersTest, VarDecl_MatchesFunctionParameter) {
1497 EXPECT_TRUE(matches("void f(int i) {}", varDecl(hasName("i"))));
1498}
1499
1500TEST_P(ASTMatchersTest, SizeOfExpr_MatchesCorrectType) {
1501 EXPECT_TRUE(matches("void x() { int a = sizeof(a); }",
1502 sizeOfExpr(hasArgumentOfType(asString("int")))));
1503 EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }",
1504 sizeOfExpr(hasArgumentOfType(asString("float")))));
1505 EXPECT_TRUE(matches(
1506 "struct A {}; void x() { struct A a; int b = sizeof(a); }",
1507 sizeOfExpr(hasArgumentOfType(hasDeclaration(recordDecl(hasName("A")))))));
1508 EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }",
1509 sizeOfExpr(hasArgumentOfType(
1510 hasDeclaration(recordDecl(hasName("string")))))));
1511}
1512
1513TEST_P(ASTMatchersTest, IsInteger_MatchesIntegers) {
1514 EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isInteger()))));
1515 EXPECT_TRUE(
1516 matches("long long i = 0; void f(long long) { }; void g() {f(i);}",
1517 callExpr(hasArgument(
1518 0, declRefExpr(to(varDecl(hasType(isInteger()))))))));
1519}
1520
1521TEST_P(ASTMatchersTest, IsInteger_ReportsNoFalsePositives) {
1522 if (!GetParam().isCXX()) {
1523 // FIXME: Add a similar negative test for `isInteger()` that does not depend
1524 // on C++.
1525 return;
1526 }
1527
1528 EXPECT_TRUE(notMatches("int *i;", varDecl(hasType(isInteger()))));
1529 EXPECT_TRUE(
1530 notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}",
1531 callExpr(hasArgument(
1532 0, declRefExpr(to(varDecl(hasType(isInteger()))))))));
1533}
1534
1535TEST_P(ASTMatchersTest, IsSignedInteger_MatchesSignedIntegers) {
1536 EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isSignedInteger()))));
1537 EXPECT_TRUE(
1538 notMatches("unsigned i = 0;", varDecl(hasType(isSignedInteger()))));
1539}
1540
1541TEST_P(ASTMatchersTest, IsUnsignedInteger_MatchesUnsignedIntegers) {
1542 EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isUnsignedInteger()))));
1543 EXPECT_TRUE(
1544 matches("unsigned i = 0;", varDecl(hasType(isUnsignedInteger()))));
1545}
1546
1547TEST_P(ASTMatchersTest, IsAnyPointer_MatchesPointers) {
1548 if (!GetParam().isCXX11OrLater()) {
1549 // FIXME: Add a test for `isAnyPointer()` that does not depend on C++.
1550 return;
1551 }
1552
1553 EXPECT_TRUE(matches("int* i = nullptr;", varDecl(hasType(isAnyPointer()))));
1554}
1555
1556TEST_P(ASTMatchersTest, IsAnyPointer_MatchesObjcPointer) {
1557 EXPECT_TRUE(matchesObjC("@interface Foo @end Foo *f;",
1558 varDecl(hasType(isAnyPointer()))));
1559}
1560
1561TEST_P(ASTMatchersTest, IsAnyPointer_ReportsNoFalsePositives) {
1562 EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isAnyPointer()))));
1563}
1564
1565TEST_P(ASTMatchersTest, IsAnyCharacter_MatchesCharacters) {
1566 EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter()))));
1567}
1568
1569TEST_P(ASTMatchersTest, IsAnyCharacter_ReportsNoFalsePositives) {
1570 EXPECT_TRUE(notMatches("int i;", varDecl(hasType(isAnyCharacter()))));
1571}
1572
1573TEST_P(ASTMatchersTest, IsArrow_MatchesMemberVariablesViaArrow) {
1574 if (!GetParam().isCXX()) {
1575 // FIXME: Add a test for `isArrow()` that does not depend on C++.
1576 return;
1577 }
1578 if (GetParam().hasDelayedTemplateParsing()) {
1579 // FIXME: Fix this test to work with delayed template parsing.
1580 return;
1581 }
1582
1583 EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
1584 memberExpr(isArrow())));
1585 EXPECT_TRUE(
1586 matches("class Y { void x() { y; } int y; };", memberExpr(isArrow())));
1587 EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
1588 memberExpr(isArrow())));
1589 EXPECT_TRUE(
1590 matches("template <class T> class Y { void x() { this->m; } int m; };",
1591 memberExpr(isArrow())));
1592 EXPECT_TRUE(notMatches(
1593 "template <class T> class Y { void x() { (*this).m; } int m; };",
1594 memberExpr(isArrow())));
1595}
1596
1597TEST_P(ASTMatchersTest, IsArrow_MatchesStaticMemberVariablesViaArrow) {
1598 if (!GetParam().isCXX()) {
1599 // FIXME: Add a test for `isArrow()` that does not depend on C++.
1600 return;
1601 }
1602
1603 EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
1604 memberExpr(isArrow())));
1605 EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
1606 memberExpr(isArrow())));
1607 EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } static int y; };",
1608 memberExpr(isArrow())));
1609}
1610
1611TEST_P(ASTMatchersTest, IsArrow_MatchesMemberCallsViaArrow) {
1612 if (!GetParam().isCXX()) {
1613 // FIXME: Add a test for `isArrow()` that does not depend on C++.
1614 return;
1615 }
1616 if (GetParam().hasDelayedTemplateParsing()) {
1617 // FIXME: Fix this test to work with delayed template parsing.
1618 return;
1619 }
1620
1621 EXPECT_TRUE(
1622 matches("class Y { void x() { this->x(); } };", memberExpr(isArrow())));
1623 EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr(isArrow())));
1624 EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
1625 memberExpr(isArrow())));
1626 EXPECT_TRUE(
1627 matches("class Y { template <class T> void x() { this->x<T>(); } };",
1628 unresolvedMemberExpr(isArrow())));
1629 EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };",
1630 unresolvedMemberExpr(isArrow())));
1631 EXPECT_TRUE(
1632 notMatches("class Y { template <class T> void x() { (*this).x<T>(); } };",
1633 unresolvedMemberExpr(isArrow())));
1634}
1635
1636TEST_P(ASTMatchersTest, IsExplicit_CXXConversionDecl) {
1637 if (!GetParam().isCXX11OrLater()) {
1638 return;
1639 }
1640
1641 EXPECT_TRUE(matches("struct S { explicit operator int(); };",
1642 cxxConversionDecl(isExplicit())));
1643 EXPECT_TRUE(notMatches("struct S { operator int(); };",
1644 cxxConversionDecl(isExplicit())));
1645}
1646
1647TEST_P(ASTMatchersTest, IsExplicit_CXXConversionDecl_CXX20) {
1648 if (!GetParam().isCXX20OrLater()) {
1649 return;
1650 }
1651
1652 EXPECT_TRUE(
1653 notMatches("template<bool b> struct S { explicit(b) operator int(); };",
1654 cxxConversionDecl(isExplicit())));
1655 EXPECT_TRUE(matches("struct S { explicit(true) operator int(); };",
1656 cxxConversionDecl(isExplicit())));
1657 EXPECT_TRUE(notMatches("struct S { explicit(false) operator int(); };",
1658 cxxConversionDecl(isExplicit())));
1659}
1660
1661TEST_P(ASTMatchersTest, ArgumentCountAtLeast_CallExpr) {
1662 StatementMatcher Call2PlusArgs = callExpr(argumentCountAtLeast(N: 2));
1663
1664 EXPECT_TRUE(notMatches("void x(void) { x(); }", Call2PlusArgs));
1665 EXPECT_TRUE(notMatches("void x(int) { x(0); }", Call2PlusArgs));
1666 EXPECT_TRUE(matches("void x(int, int) { x(0, 0); }", Call2PlusArgs));
1667 EXPECT_TRUE(matches("void x(int, int, int) { x(0, 0, 0); }", Call2PlusArgs));
1668
1669 if (!GetParam().isCXX()) {
1670 return;
1671 }
1672
1673 EXPECT_TRUE(
1674 notMatches("void x(int = 1) { x(); }", traverse(TK_AsIs, Call2PlusArgs)));
1675 EXPECT_TRUE(matches("void x(int, int = 1) { x(0); }",
1676 traverse(TK_AsIs, Call2PlusArgs)));
1677 EXPECT_TRUE(matches("void x(int, int = 1, int = 1) { x(0); }",
1678 traverse(TK_AsIs, Call2PlusArgs)));
1679 EXPECT_TRUE(matches("void x(int, int, int = 1) { x(0, 0); }",
1680 traverse(TK_AsIs, Call2PlusArgs)));
1681 EXPECT_TRUE(matches("void x(int, int, int, int = 1) { x(0, 0, 0); }",
1682 traverse(TK_AsIs, Call2PlusArgs)));
1683
1684 EXPECT_TRUE(
1685 notMatches("void x(int = 1) { x(); }",
1686 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1687 EXPECT_TRUE(
1688 notMatches("void x(int, int = 1) { x(0); }",
1689 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1690 EXPECT_TRUE(
1691 notMatches("void x(int, int = 1, int = 1) { x(0); }",
1692 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1693 EXPECT_TRUE(matches("void x(int, int, int = 1) { x(0, 0); }",
1694 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1695 EXPECT_TRUE(matches("void x(int, int, int, int = 1) { x(0, 0, 0); }",
1696 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1697}
1698
1699TEST_P(ASTMatchersTest, ArgumentCountAtLeast_CallExpr_CXX) {
1700 if (!GetParam().isCXX()) {
1701 return;
1702 }
1703
1704 StatementMatcher Call2PlusArgs = callExpr(argumentCountAtLeast(N: 2));
1705 EXPECT_TRUE(notMatches("class X { void x() { x(); } };", Call2PlusArgs));
1706 EXPECT_TRUE(notMatches("class X { void x(int) { x(0); } };", Call2PlusArgs));
1707 EXPECT_TRUE(
1708 matches("class X { void x(int, int) { x(0, 0); } };", Call2PlusArgs));
1709 EXPECT_TRUE(matches("class X { void x(int, int, int) { x(0, 0, 0); } };",
1710 Call2PlusArgs));
1711
1712 EXPECT_TRUE(notMatches("class X { void x(int = 1) { x(0); } };",
1713 traverse(TK_AsIs, Call2PlusArgs)));
1714 EXPECT_TRUE(matches("class X { void x(int, int = 1) { x(0); } };",
1715 traverse(TK_AsIs, Call2PlusArgs)));
1716 EXPECT_TRUE(matches("class X { void x(int, int = 1, int = 1) { x(0); } };",
1717 traverse(TK_AsIs, Call2PlusArgs)));
1718 EXPECT_TRUE(matches("class X { void x(int, int, int = 1) { x(0, 0); } };",
1719 traverse(TK_AsIs, Call2PlusArgs)));
1720 EXPECT_TRUE(
1721 matches("class X { void x(int, int, int, int = 1) { x(0, 0, 0); } };",
1722 traverse(TK_AsIs, Call2PlusArgs)));
1723
1724 EXPECT_TRUE(
1725 notMatches("class X { void x(int = 1) { x(0); } };",
1726 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1727 EXPECT_TRUE(
1728 notMatches("class X { void x(int, int = 1) { x(0); } };",
1729 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1730 EXPECT_TRUE(
1731 notMatches("class X { void x(int, int = 1, int = 1) { x(0); } };",
1732 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1733 EXPECT_TRUE(matches("class X { void x(int, int, int = 1) { x(0, 0); } };",
1734 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1735 EXPECT_TRUE(
1736 matches("class X { void x(int, int, int, int = 1) { x(0, 0, 0); } };",
1737 traverse(TK_IgnoreUnlessSpelledInSource, Call2PlusArgs)));
1738
1739 EXPECT_TRUE(
1740 notMatches("class X { static void x() { x(); } };", Call2PlusArgs));
1741 EXPECT_TRUE(
1742 notMatches("class X { static void x(int) { x(0); } };", Call2PlusArgs));
1743 EXPECT_TRUE(matches("class X { static void x(int, int) { x(0, 0); } };",
1744 Call2PlusArgs));
1745 EXPECT_TRUE(
1746 matches("class X { static void x(int, int, int) { x(0, 0, 0); } };",
1747 Call2PlusArgs));
1748}
1749
1750TEST_P(ASTMatchersTest, ArgumentCountIs_CallExpr) {
1751 StatementMatcher Call1Arg = callExpr(argumentCountIs(N: 1));
1752
1753 EXPECT_TRUE(matches("void x(int) { x(0); }", Call1Arg));
1754 EXPECT_TRUE(notMatches("void x(int, int) { x(0, 0); }", Call1Arg));
1755}
1756
1757TEST_P(ASTMatchersTest, ArgumentCountIs_CallExpr_CXX) {
1758 if (!GetParam().isCXX()) {
1759 return;
1760 }
1761
1762 StatementMatcher Call1Arg = callExpr(argumentCountIs(N: 1));
1763 EXPECT_TRUE(matches("class X { void x(int) { x(0); } };", Call1Arg));
1764}
1765
1766TEST_P(ASTMatchersTest, ParameterCountIs) {
1767 DeclarationMatcher Function1Arg = functionDecl(parameterCountIs(N: 1));
1768 EXPECT_TRUE(matches("void f(int i) {}", Function1Arg));
1769 EXPECT_TRUE(notMatches("void f() {}", Function1Arg));
1770 EXPECT_TRUE(notMatches("void f(int i, int j, int k) {}", Function1Arg));
1771 EXPECT_TRUE(matches("void f(int i, ...) {};", Function1Arg));
1772}
1773
1774TEST_P(ASTMatchersTest, ParameterCountIs_CXX) {
1775 if (!GetParam().isCXX()) {
1776 return;
1777 }
1778
1779 DeclarationMatcher Function1Arg = functionDecl(parameterCountIs(N: 1));
1780 EXPECT_TRUE(matches("class X { void f(int i) {} };", Function1Arg));
1781}
1782
1783TEST_P(ASTMatchersTest, References) {
1784 if (!GetParam().isCXX()) {
1785 // FIXME: Add a test for `references()` that does not depend on C++.
1786 return;
1787 }
1788
1789 DeclarationMatcher ReferenceClassX =
1790 varDecl(hasType(InnerMatcher: references(InnerMatcher: recordDecl(hasName(Name: "X")))));
1791 EXPECT_TRUE(
1792 matches("class X {}; void y(X y) { X &x = y; }", ReferenceClassX));
1793 EXPECT_TRUE(
1794 matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX));
1795 // The match here is on the implicit copy constructor code for
1796 // class X, not on code 'X x = y'.
1797 EXPECT_TRUE(matches("class X {}; void y(X y) { X x = y; }", ReferenceClassX));
1798 EXPECT_TRUE(notMatches("class X {}; extern X x;", ReferenceClassX));
1799 EXPECT_TRUE(
1800 notMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX));
1801}
1802
1803TEST_P(ASTMatchersTest, HasLocalQualifiers) {
1804 if (!GetParam().isCXX11OrLater()) {
1805 // FIXME: Add a test for `hasLocalQualifiers()` that does not depend on C++.
1806 return;
1807 }
1808
1809 EXPECT_TRUE(notMatches("typedef const int const_int; const_int i = 1;",
1810 varDecl(hasType(hasLocalQualifiers()))));
1811 EXPECT_TRUE(matches("int *const j = nullptr;",
1812 varDecl(hasType(hasLocalQualifiers()))));
1813 EXPECT_TRUE(
1814 matches("int *volatile k;", varDecl(hasType(hasLocalQualifiers()))));
1815 EXPECT_TRUE(notMatches("int m;", varDecl(hasType(hasLocalQualifiers()))));
1816}
1817
1818TEST_P(ASTMatchersTest, IsExternC_MatchesExternCFunctionDeclarations) {
1819 if (!GetParam().isCXX()) {
1820 return;
1821 }
1822
1823 EXPECT_TRUE(matches("extern \"C\" void f() {}", functionDecl(isExternC())));
1824 EXPECT_TRUE(
1825 matches("extern \"C\" { void f() {} }", functionDecl(isExternC())));
1826 EXPECT_TRUE(notMatches("void f() {}", functionDecl(isExternC())));
1827}
1828
1829TEST_P(ASTMatchersTest, IsExternC_MatchesExternCVariableDeclarations) {
1830 if (!GetParam().isCXX()) {
1831 return;
1832 }
1833
1834 EXPECT_TRUE(matches("extern \"C\" int i;", varDecl(isExternC())));
1835 EXPECT_TRUE(matches("extern \"C\" { int i; }", varDecl(isExternC())));
1836 EXPECT_TRUE(notMatches("int i;", varDecl(isExternC())));
1837}
1838
1839TEST_P(ASTMatchersTest, IsStaticStorageClass) {
1840 EXPECT_TRUE(
1841 matches("static void f() {}", functionDecl(isStaticStorageClass())));
1842 EXPECT_TRUE(matches("static int i = 1;", varDecl(isStaticStorageClass())));
1843 EXPECT_TRUE(notMatches("int i = 1;", varDecl(isStaticStorageClass())));
1844 EXPECT_TRUE(notMatches("extern int i;", varDecl(isStaticStorageClass())));
1845 EXPECT_TRUE(notMatches("void f() {}", functionDecl(isStaticStorageClass())));
1846}
1847
1848TEST_P(ASTMatchersTest, IsDefaulted) {
1849 if (!GetParam().isCXX()) {
1850 return;
1851 }
1852
1853 EXPECT_TRUE(notMatches("class A { ~A(); };",
1854 functionDecl(hasName("~A"), isDefaulted())));
1855 EXPECT_TRUE(matches("class B { ~B() = default; };",
1856 functionDecl(hasName("~B"), isDefaulted())));
1857}
1858
1859TEST_P(ASTMatchersTest, IsDeleted) {
1860 if (!GetParam().isCXX()) {
1861 return;
1862 }
1863
1864 EXPECT_TRUE(
1865 notMatches("void Func();", functionDecl(hasName("Func"), isDeleted())));
1866 EXPECT_TRUE(matches("void Func() = delete;",
1867 functionDecl(hasName("Func"), isDeleted())));
1868}
1869
1870TEST_P(ASTMatchersTest, IsNoThrow_DynamicExceptionSpec) {
1871 if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
1872 return;
1873 }
1874
1875 EXPECT_TRUE(notMatches("void f();", functionDecl(isNoThrow())));
1876 EXPECT_TRUE(notMatches("void f() throw(int);", functionDecl(isNoThrow())));
1877 EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow())));
1878
1879 EXPECT_TRUE(notMatches("void f();", functionProtoType(isNoThrow())));
1880 EXPECT_TRUE(
1881 notMatches("void f() throw(int);", functionProtoType(isNoThrow())));
1882 EXPECT_TRUE(matches("void f() throw();", functionProtoType(isNoThrow())));
1883}
1884
1885TEST_P(ASTMatchersTest, IsNoThrow_CXX11) {
1886 if (!GetParam().isCXX11OrLater()) {
1887 return;
1888 }
1889
1890 EXPECT_TRUE(
1891 notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
1892 EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow())));
1893
1894 EXPECT_TRUE(
1895 notMatches("void f() noexcept(false);", functionProtoType(isNoThrow())));
1896 EXPECT_TRUE(matches("void f() noexcept;", functionProtoType(isNoThrow())));
1897}
1898
1899TEST_P(ASTMatchersTest, IsConsteval) {
1900 if (!GetParam().isCXX20OrLater())
1901 return;
1902
1903 EXPECT_TRUE(matches("consteval int bar();",
1904 functionDecl(hasName("bar"), isConsteval())));
1905 EXPECT_TRUE(notMatches("constexpr int bar();",
1906 functionDecl(hasName("bar"), isConsteval())));
1907 EXPECT_TRUE(
1908 notMatches("int bar();", functionDecl(hasName("bar"), isConsteval())));
1909}
1910
1911TEST_P(ASTMatchersTest, IsConsteval_MatchesIfConsteval) {
1912 if (!GetParam().isCXX20OrLater())
1913 return;
1914
1915 EXPECT_TRUE(matches("void baz() { if consteval {} }", ifStmt(isConsteval())));
1916 EXPECT_TRUE(
1917 matches("void baz() { if ! consteval {} }", ifStmt(isConsteval())));
1918 EXPECT_TRUE(matches("void baz() { if ! consteval {} else {} }",
1919 ifStmt(isConsteval())));
1920 EXPECT_TRUE(
1921 matches("void baz() { if not consteval {} }", ifStmt(isConsteval())));
1922 EXPECT_TRUE(notMatches("void baz() { if constexpr(1 > 0) {} }",
1923 ifStmt(isConsteval())));
1924 EXPECT_TRUE(
1925 notMatches("void baz() { if (1 > 0) {} }", ifStmt(isConsteval())));
1926}
1927
1928TEST_P(ASTMatchersTest, IsConstexpr) {
1929 if (!GetParam().isCXX11OrLater()) {
1930 return;
1931 }
1932
1933 EXPECT_TRUE(matches("constexpr int foo = 42;",
1934 varDecl(hasName("foo"), isConstexpr())));
1935 EXPECT_TRUE(matches("constexpr int bar();",
1936 functionDecl(hasName("bar"), isConstexpr())));
1937}
1938
1939TEST_P(ASTMatchersTest, IsConstexpr_MatchesIfConstexpr) {
1940 if (!GetParam().isCXX17OrLater()) {
1941 return;
1942 }
1943
1944 EXPECT_TRUE(
1945 matches("void baz() { if constexpr(1 > 0) {} }", ifStmt(isConstexpr())));
1946 EXPECT_TRUE(
1947 notMatches("void baz() { if (1 > 0) {} }", ifStmt(isConstexpr())));
1948}
1949
1950TEST_P(ASTMatchersTest, IsConstinit) {
1951 if (!GetParam().isCXX20OrLater())
1952 return;
1953
1954 EXPECT_TRUE(matches("constinit int foo = 1;",
1955 varDecl(hasName("foo"), isConstinit())));
1956 EXPECT_TRUE(matches("extern constinit int foo;",
1957 varDecl(hasName("foo"), isConstinit())));
1958 EXPECT_TRUE(matches("constinit const char* foo = \"bar\";",
1959 varDecl(hasName("foo"), isConstinit())));
1960 EXPECT_TRUE(
1961 notMatches("[[clang::require_constant_initialization]] int foo = 1;",
1962 varDecl(hasName("foo"), isConstinit())));
1963 EXPECT_TRUE(notMatches("constexpr int foo = 1;",
1964 varDecl(hasName("foo"), isConstinit())));
1965 EXPECT_TRUE(notMatches("static inline int foo = 1;",
1966 varDecl(hasName("foo"), isConstinit())));
1967}
1968
1969TEST_P(ASTMatchersTest, HasInitStatement_MatchesSelectionInitializers) {
1970 EXPECT_TRUE(notMatches("void baz() { if (1 > 0) {} }",
1971 ifStmt(hasInitStatement(anything()))));
1972 EXPECT_TRUE(notMatches("void baz(int i) { switch (i) { default: break; } }",
1973 switchStmt(hasInitStatement(anything()))));
1974}
1975
1976TEST_P(ASTMatchersTest, HasInitStatement_MatchesSelectionInitializers_CXX) {
1977 if (!GetParam().isCXX()) {
1978 return;
1979 }
1980
1981 EXPECT_TRUE(notMatches("void baz() { if (int i = 1) {} }",
1982 ifStmt(hasInitStatement(anything()))));
1983}
1984
1985TEST_P(ASTMatchersTest, HasInitStatement_MatchesSelectionInitializers_CXX17) {
1986 if (!GetParam().isCXX17OrLater()) {
1987 return;
1988 }
1989
1990 EXPECT_TRUE(matches("void baz() { if (int i = 1; i > 0) {} }",
1991 ifStmt(hasInitStatement(anything()))));
1992 EXPECT_TRUE(
1993 matches("void baz(int i) { switch (int j = i; j) { default: break; } }",
1994 switchStmt(hasInitStatement(anything()))));
1995}
1996
1997TEST_P(ASTMatchersTest, HasInitStatement_MatchesRangeForInitializers) {
1998 if (!GetParam().isCXX20OrLater()) {
1999 return;
2000 }
2001
2002 EXPECT_TRUE(matches("void baz() {"
2003 "int items[] = {};"
2004 "for (auto &arr = items; auto &item : arr) {}"
2005 "}",
2006 cxxForRangeStmt(hasInitStatement(anything()))));
2007 EXPECT_TRUE(notMatches("void baz() {"
2008 "int items[] = {};"
2009 "for (auto &item : items) {}"
2010 "}",
2011 cxxForRangeStmt(hasInitStatement(anything()))));
2012}
2013
2014TEST_P(ASTMatchersTest, TemplateArgumentCountIs) {
2015 if (!GetParam().isCXX()) {
2016 return;
2017 }
2018
2019 EXPECT_TRUE(
2020 matches("template<typename T> struct C {}; C<int> c;",
2021 classTemplateSpecializationDecl(templateArgumentCountIs(1))));
2022 EXPECT_TRUE(
2023 notMatches("template<typename T> struct C {}; C<int> c;",
2024 classTemplateSpecializationDecl(templateArgumentCountIs(2))));
2025
2026 EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;",
2027 templateSpecializationType(templateArgumentCountIs(1))));
2028 EXPECT_TRUE(
2029 notMatches("template<typename T> struct C {}; C<int> c;",
2030 templateSpecializationType(templateArgumentCountIs(2))));
2031
2032 const char *FuncTemplateCode =
2033 "template<typename T> T f(); auto v = f<int>();";
2034 EXPECT_TRUE(
2035 matches(FuncTemplateCode, functionDecl(templateArgumentCountIs(1))));
2036 EXPECT_TRUE(
2037 notMatches(FuncTemplateCode, functionDecl(templateArgumentCountIs(2))));
2038}
2039
2040TEST_P(ASTMatchersTest, IsIntegral) {
2041 if (!GetParam().isCXX()) {
2042 return;
2043 }
2044
2045 EXPECT_TRUE(matches(
2046 "template<int T> struct C {}; C<42> c;",
2047 classTemplateSpecializationDecl(hasAnyTemplateArgument(isIntegral()))));
2048 EXPECT_TRUE(notMatches("template<typename T> struct C {}; C<int> c;",
2049 classTemplateSpecializationDecl(hasAnyTemplateArgument(
2050 templateArgument(isIntegral())))));
2051}
2052
2053TEST_P(ASTMatchersTest, EqualsIntegralValue) {
2054 if (!GetParam().isCXX()) {
2055 return;
2056 }
2057
2058 EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
2059 classTemplateSpecializationDecl(
2060 hasAnyTemplateArgument(equalsIntegralValue("42")))));
2061 EXPECT_TRUE(matches("template<int T> struct C {}; C<-42> c;",
2062 classTemplateSpecializationDecl(
2063 hasAnyTemplateArgument(equalsIntegralValue("-42")))));
2064 EXPECT_TRUE(matches("template<int T> struct C {}; C<-0042> c;",
2065 classTemplateSpecializationDecl(
2066 hasAnyTemplateArgument(equalsIntegralValue("-34")))));
2067 EXPECT_TRUE(notMatches("template<int T> struct C {}; C<42> c;",
2068 classTemplateSpecializationDecl(hasAnyTemplateArgument(
2069 equalsIntegralValue("0042")))));
2070}
2071
2072TEST_P(ASTMatchersTest, AccessSpecDecl) {
2073 if (!GetParam().isCXX()) {
2074 return;
2075 }
2076
2077 EXPECT_TRUE(matches("class C { public: int i; };", accessSpecDecl()));
2078 EXPECT_TRUE(
2079 matches("class C { public: int i; };", accessSpecDecl(isPublic())));
2080 EXPECT_TRUE(
2081 notMatches("class C { public: int i; };", accessSpecDecl(isProtected())));
2082 EXPECT_TRUE(
2083 notMatches("class C { public: int i; };", accessSpecDecl(isPrivate())));
2084
2085 EXPECT_TRUE(notMatches("class C { int i; };", accessSpecDecl()));
2086}
2087
2088TEST_P(ASTMatchersTest, IsFinal) {
2089 if (!GetParam().isCXX11OrLater()) {
2090 return;
2091 }
2092
2093 EXPECT_TRUE(matches("class X final {};", cxxRecordDecl(isFinal())));
2094 EXPECT_TRUE(matches("class X { virtual void f() final; };",
2095 cxxMethodDecl(isFinal())));
2096 EXPECT_TRUE(notMatches("class X {};", cxxRecordDecl(isFinal())));
2097 EXPECT_TRUE(
2098 notMatches("class X { virtual void f(); };", cxxMethodDecl(isFinal())));
2099}
2100
2101TEST_P(ASTMatchersTest, IsVirtual) {
2102 if (!GetParam().isCXX()) {
2103 return;
2104 }
2105
2106 EXPECT_TRUE(matches("class X { virtual int f(); };",
2107 cxxMethodDecl(isVirtual(), hasName("::X::f"))));
2108 EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isVirtual())));
2109}
2110
2111TEST_P(ASTMatchersTest, IsVirtualAsWritten) {
2112 if (!GetParam().isCXX()) {
2113 return;
2114 }
2115
2116 EXPECT_TRUE(matches("class A { virtual int f(); };"
2117 "class B : public A { int f(); };",
2118 cxxMethodDecl(isVirtualAsWritten(), hasName("::A::f"))));
2119 EXPECT_TRUE(
2120 notMatches("class A { virtual int f(); };"
2121 "class B : public A { int f(); };",
2122 cxxMethodDecl(isVirtualAsWritten(), hasName("::B::f"))));
2123}
2124
2125TEST_P(ASTMatchersTest, IsPure) {
2126 if (!GetParam().isCXX()) {
2127 return;
2128 }
2129
2130 EXPECT_TRUE(matches("class X { virtual int f() = 0; };",
2131 cxxMethodDecl(isPure(), hasName("::X::f"))));
2132 EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isPure())));
2133}
2134
2135TEST_P(ASTMatchersTest, IsExplicitObjectMemberFunction) {
2136 if (!GetParam().isCXX23OrLater()) {
2137 return;
2138 }
2139
2140 auto ExpObjParamFn = cxxMethodDecl(isExplicitObjectMemberFunction());
2141 EXPECT_TRUE(
2142 notMatches("struct A { static int operator()(int); };", ExpObjParamFn));
2143 EXPECT_TRUE(notMatches("struct A { int operator+(int); };", ExpObjParamFn));
2144 EXPECT_TRUE(
2145 matches("struct A { int operator-(this A, int); };", ExpObjParamFn));
2146 EXPECT_TRUE(matches("struct A { void fun(this A &&self); };", ExpObjParamFn));
2147}
2148
2149TEST_P(ASTMatchersTest, IsCopyAssignmentOperator) {
2150 if (!GetParam().isCXX()) {
2151 return;
2152 }
2153
2154 auto CopyAssignment =
2155 cxxMethodDecl(isCopyAssignmentOperator(), unless(isImplicit()));
2156 EXPECT_TRUE(matches("class X { X &operator=(X); };", CopyAssignment));
2157 EXPECT_TRUE(matches("class X { X &operator=(X &); };", CopyAssignment));
2158 EXPECT_TRUE(matches("class X { X &operator=(const X &); };", CopyAssignment));
2159 EXPECT_TRUE(matches("class X { X &operator=(volatile X &); };", //
2160 CopyAssignment));
2161 EXPECT_TRUE(matches("class X { X &operator=(const volatile X &); };",
2162 CopyAssignment));
2163 EXPECT_TRUE(notMatches("class X { X &operator=(X &&); };", CopyAssignment));
2164}
2165
2166TEST_P(ASTMatchersTest, IsMoveAssignmentOperator) {
2167 if (!GetParam().isCXX()) {
2168 return;
2169 }
2170
2171 auto MoveAssignment =
2172 cxxMethodDecl(isMoveAssignmentOperator(), unless(isImplicit()));
2173 EXPECT_TRUE(notMatches("class X { X &operator=(X); };", MoveAssignment));
2174 EXPECT_TRUE(matches("class X { X &operator=(X &&); };", MoveAssignment));
2175 EXPECT_TRUE(matches("class X { X &operator=(const X &&); };", //
2176 MoveAssignment));
2177 EXPECT_TRUE(matches("class X { X &operator=(volatile X &&); };", //
2178 MoveAssignment));
2179 EXPECT_TRUE(matches("class X { X &operator=(const volatile X &&); };",
2180 MoveAssignment));
2181 EXPECT_TRUE(notMatches("class X { X &operator=(X &); };", MoveAssignment));
2182}
2183
2184TEST_P(ASTMatchersTest, IsConst) {
2185 if (!GetParam().isCXX()) {
2186 return;
2187 }
2188
2189 EXPECT_TRUE(
2190 matches("struct A { void foo() const; };", cxxMethodDecl(isConst())));
2191 EXPECT_TRUE(
2192 notMatches("struct A { void foo(); };", cxxMethodDecl(isConst())));
2193}
2194
2195TEST_P(ASTMatchersTest, IsOverride) {
2196 if (!GetParam().isCXX()) {
2197 return;
2198 }
2199
2200 EXPECT_TRUE(matches("class X { virtual int f(); }; "
2201 "class Y : public X { int f(); };",
2202 cxxMethodDecl(isOverride(), hasName("::Y::f"))));
2203 EXPECT_TRUE(notMatches("class X { virtual int f(); }; "
2204 "class Y : public X { int f(); };",
2205 cxxMethodDecl(isOverride(), hasName("::X::f"))));
2206 EXPECT_TRUE(notMatches("class X { int f(); }; "
2207 "class Y : public X { int f(); };",
2208 cxxMethodDecl(isOverride())));
2209 EXPECT_TRUE(notMatches("class X { int f(); int f(int); }; ",
2210 cxxMethodDecl(isOverride())));
2211 EXPECT_TRUE(
2212 matches("template <typename Base> struct Y : Base { void f() override;};",
2213 cxxMethodDecl(isOverride(), hasName("::Y::f"))));
2214}
2215
2216TEST_P(ASTMatchersTest, HasArgument_CXXConstructorDecl) {
2217 if (!GetParam().isCXX()) {
2218 return;
2219 }
2220
2221 auto Constructor = traverse(
2222 TK: TK_AsIs,
2223 InnerMatcher: cxxConstructExpr(hasArgument(N: 0, InnerMatcher: declRefExpr(to(InnerMatcher: varDecl(hasName(Name: "y")))))));
2224
2225 EXPECT_TRUE(matches(
2226 "class X { public: X(int); }; void x() { int y; X x(y); }", Constructor));
2227 EXPECT_TRUE(
2228 matches("class X { public: X(int); }; void x() { int y; X x = X(y); }",
2229 Constructor));
2230 EXPECT_TRUE(
2231 matches("class X { public: X(int); }; void x() { int y; X x = y; }",
2232 Constructor));
2233 EXPECT_TRUE(notMatches(
2234 "class X { public: X(int); }; void x() { int z; X x(z); }", Constructor));
2235
2236 StatementMatcher WrongIndex =
2237 traverse(TK: TK_AsIs, InnerMatcher: cxxConstructExpr(hasArgument(
2238 N: 42, InnerMatcher: declRefExpr(to(InnerMatcher: varDecl(hasName(Name: "y")))))));
2239 EXPECT_TRUE(notMatches(
2240 "class X { public: X(int); }; void x() { int y; X x(y); }", WrongIndex));
2241}
2242
2243TEST_P(ASTMatchersTest, ArgumentCountIs_CXXConstructExpr) {
2244 if (!GetParam().isCXX()) {
2245 return;
2246 }
2247
2248 auto Constructor1Arg =
2249 traverse(TK: TK_AsIs, InnerMatcher: cxxConstructExpr(argumentCountIs(N: 1)));
2250
2251 EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x(0); }",
2252 Constructor1Arg));
2253 EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x = X(0); }",
2254 Constructor1Arg));
2255 EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x = 0; }",
2256 Constructor1Arg));
2257 EXPECT_TRUE(
2258 notMatches("class X { public: X(int, int); }; void x() { X x(0, 0); }",
2259 Constructor1Arg));
2260}
2261
2262TEST_P(ASTMatchersTest, HasDependentName_DependentScopeDeclRefExpr) {
2263 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
2264 // FIXME: Fix this test to work with delayed template parsing.
2265 return;
2266 }
2267
2268 EXPECT_TRUE(matches("template <class T> class X : T { void f() { T::v; } };",
2269 dependentScopeDeclRefExpr(hasDependentName("v"))));
2270
2271 EXPECT_TRUE(matches("template <typename T> struct S { static T Foo; };"
2272 "template <typename T> void x() { (void)S<T>::Foo; }",
2273 dependentScopeDeclRefExpr(hasDependentName("Foo"))));
2274
2275 EXPECT_TRUE(matches("template <typename T> struct S { static T foo(); };"
2276 "template <typename T> void x() { S<T>::foo(); }",
2277 dependentScopeDeclRefExpr(hasDependentName("foo"))));
2278}
2279
2280TEST_P(ASTMatchersTest, HasDependentName_DependentNameType) {
2281 if (!GetParam().isCXX()) {
2282 // FIXME: Fix this test to work with delayed template parsing.
2283 return;
2284 }
2285
2286 EXPECT_TRUE(matches(
2287 R"(
2288 template <typename T> struct declToImport {
2289 typedef typename T::type dependent_name;
2290 };
2291 )",
2292 dependentNameType(hasDependentName("type"))));
2293}
2294
2295TEST(ASTMatchersTest, NamesMember_CXXDependentScopeMemberExpr) {
2296
2297 // Member functions:
2298 {
2299 auto Code = "template <typename T> struct S{ void mem(); }; template "
2300 "<typename T> void x() { S<T> s; s.mem(); }";
2301
2302 EXPECT_TRUE(matches(
2303 Code,
2304 cxxDependentScopeMemberExpr(
2305 hasObjectExpression(declRefExpr(hasType(elaboratedType(namesType(
2306 templateSpecializationType(hasDeclaration(classTemplateDecl(
2307 has(cxxRecordDecl(has(cxxMethodDecl(hasName("mem"))
2308 .bind("templMem")))))))))))),
2309 memberHasSameNameAsBoundNode("templMem"))));
2310
2311 EXPECT_TRUE(
2312 matches(Code, cxxDependentScopeMemberExpr(hasMemberName("mem"))));
2313 }
2314
2315 // Member variables:
2316 {
2317 auto Code = "template <typename T> struct S{ int mem; }; template "
2318 "<typename T> void x() { S<T> s; s.mem; }";
2319
2320 EXPECT_TRUE(
2321 matches(Code, cxxDependentScopeMemberExpr(hasMemberName("mem"))));
2322
2323 EXPECT_TRUE(matches(
2324 Code,
2325 cxxDependentScopeMemberExpr(
2326 hasObjectExpression(declRefExpr(
2327 hasType(elaboratedType(namesType(templateSpecializationType(
2328 hasDeclaration(classTemplateDecl(has(cxxRecordDecl(has(
2329 fieldDecl(hasName("mem")).bind("templMem")))))))))))),
2330 memberHasSameNameAsBoundNode("templMem"))));
2331 }
2332
2333 // static member variables:
2334 {
2335 auto Code = "template <typename T> struct S{ static int mem; }; template "
2336 "<typename T> void x() { S<T> s; s.mem; }";
2337
2338 EXPECT_TRUE(
2339 matches(Code, cxxDependentScopeMemberExpr(hasMemberName("mem"))));
2340
2341 EXPECT_TRUE(matches(
2342 Code,
2343 cxxDependentScopeMemberExpr(
2344 hasObjectExpression(declRefExpr(
2345 hasType(elaboratedType(namesType(templateSpecializationType(
2346 hasDeclaration(classTemplateDecl(has(cxxRecordDecl(
2347 has(varDecl(hasName("mem")).bind("templMem")))))))))))),
2348 memberHasSameNameAsBoundNode("templMem"))));
2349 }
2350 {
2351 auto Code = R"cpp(
2352template <typename T>
2353struct S {
2354 bool operator==(int) const { return true; }
2355};
2356
2357template <typename T>
2358void func(T t) {
2359 S<T> s;
2360 s.operator==(1);
2361}
2362)cpp";
2363
2364 EXPECT_TRUE(matches(
2365 Code, cxxDependentScopeMemberExpr(hasMemberName("operator=="))));
2366 }
2367
2368 // other named decl:
2369 {
2370 auto Code = "template <typename T> struct S{ static int mem; }; struct "
2371 "mem{}; template "
2372 "<typename T> void x() { S<T> s; s.mem; }";
2373
2374 EXPECT_TRUE(matches(
2375 Code,
2376 translationUnitDecl(has(cxxRecordDecl(hasName("mem"))),
2377 hasDescendant(cxxDependentScopeMemberExpr()))));
2378
2379 EXPECT_FALSE(matches(
2380 Code,
2381 translationUnitDecl(has(cxxRecordDecl(hasName("mem")).bind("templMem")),
2382 hasDescendant(cxxDependentScopeMemberExpr(
2383 memberHasSameNameAsBoundNode("templMem"))))));
2384 }
2385}
2386
2387TEST(ASTMatchersTest, ArgumentCountIs_CXXUnresolvedConstructExpr) {
2388 const auto *Code =
2389 "template <typename T> struct S{}; template <typename T> void "
2390 "x() { auto s = S<T>(); }";
2391
2392 EXPECT_TRUE(matches(Code, cxxUnresolvedConstructExpr(argumentCountIs(0))));
2393 EXPECT_TRUE(notMatches(Code, cxxUnresolvedConstructExpr(argumentCountIs(1))));
2394}
2395
2396TEST(ASTMatchersTest, HasArgument_CXXUnresolvedConstructExpr) {
2397 const auto *Code =
2398 "template <typename T> struct S{ S(int){} }; template <typename "
2399 "T> void x() { int y; auto s = S<T>(y); }";
2400 EXPECT_TRUE(matches(Code, cxxUnresolvedConstructExpr(hasArgument(
2401 0, declRefExpr(to(varDecl(hasName("y"))))))));
2402 EXPECT_TRUE(
2403 notMatches(Code, cxxUnresolvedConstructExpr(hasArgument(
2404 0, declRefExpr(to(varDecl(hasName("x"))))))));
2405}
2406
2407TEST_P(ASTMatchersTest, IsListInitialization) {
2408 if (!GetParam().isCXX11OrLater()) {
2409 return;
2410 }
2411
2412 auto ConstructorListInit =
2413 traverse(TK: TK_AsIs, InnerMatcher: varDecl(has(cxxConstructExpr(isListInitialization()))));
2414
2415 EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x{0}; }",
2416 ConstructorListInit));
2417 EXPECT_FALSE(matches("class X { public: X(int); }; void x() { X x(0); }",
2418 ConstructorListInit));
2419}
2420
2421TEST_P(ASTMatchersTest, IsImplicit_CXXConstructorDecl) {
2422 if (!GetParam().isCXX()) {
2423 return;
2424 }
2425
2426 // This one doesn't match because the constructor is not added by the
2427 // compiler (it is not needed).
2428 EXPECT_TRUE(notMatches("class Foo { };", cxxConstructorDecl(isImplicit())));
2429 // The compiler added the implicit default constructor.
2430 EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
2431 cxxConstructorDecl(isImplicit())));
2432 EXPECT_TRUE(matches("class Foo { Foo(){} };",
2433 cxxConstructorDecl(unless(isImplicit()))));
2434 // The compiler added an implicit assignment operator.
2435 EXPECT_TRUE(matches("struct A { int x; } a = {0}, b = a; void f() { a = b; }",
2436 cxxMethodDecl(isImplicit(), hasName("operator="))));
2437}
2438
2439TEST_P(ASTMatchersTest, IsExplicit_CXXConstructorDecl) {
2440 if (!GetParam().isCXX()) {
2441 return;
2442 }
2443
2444 EXPECT_TRUE(matches("struct S { explicit S(int); };",
2445 cxxConstructorDecl(isExplicit())));
2446 EXPECT_TRUE(
2447 notMatches("struct S { S(int); };", cxxConstructorDecl(isExplicit())));
2448}
2449
2450TEST_P(ASTMatchersTest, IsExplicit_CXXConstructorDecl_CXX20) {
2451 if (!GetParam().isCXX20OrLater()) {
2452 return;
2453 }
2454
2455 EXPECT_TRUE(notMatches("template<bool b> struct S { explicit(b) S(int);};",
2456 cxxConstructorDecl(isExplicit())));
2457 EXPECT_TRUE(matches("struct S { explicit(true) S(int);};",
2458 cxxConstructorDecl(isExplicit())));
2459 EXPECT_TRUE(notMatches("struct S { explicit(false) S(int);};",
2460 cxxConstructorDecl(isExplicit())));
2461}
2462
2463TEST_P(ASTMatchersTest, IsExplicit_CXXDeductionGuideDecl) {
2464 if (!GetParam().isCXX17OrLater()) {
2465 return;
2466 }
2467
2468 EXPECT_TRUE(notMatches("template<typename T> struct S { S(int);};"
2469 "S(int) -> S<int>;",
2470 cxxDeductionGuideDecl(isExplicit())));
2471 EXPECT_TRUE(matches("template<typename T> struct S { S(int);};"
2472 "explicit S(int) -> S<int>;",
2473 cxxDeductionGuideDecl(isExplicit())));
2474}
2475
2476TEST_P(ASTMatchersTest, IsExplicit_CXXDeductionGuideDecl_CXX20) {
2477 if (!GetParam().isCXX20OrLater()) {
2478 return;
2479 }
2480
2481 EXPECT_TRUE(matches("template<typename T> struct S { S(int);};"
2482 "explicit(true) S(int) -> S<int>;",
2483 cxxDeductionGuideDecl(isExplicit())));
2484 EXPECT_TRUE(notMatches("template<typename T> struct S { S(int);};"
2485 "explicit(false) S(int) -> S<int>;",
2486 cxxDeductionGuideDecl(isExplicit())));
2487 EXPECT_TRUE(
2488 notMatches("template<typename T> struct S { S(int);};"
2489 "template<bool b = true> explicit(b) S(int) -> S<int>;",
2490 cxxDeductionGuideDecl(isExplicit())));
2491}
2492
2493TEST_P(ASTMatchersTest, CXXConstructorDecl_Kinds) {
2494 if (!GetParam().isCXX()) {
2495 return;
2496 }
2497
2498 EXPECT_TRUE(
2499 matches("struct S { S(); };", cxxConstructorDecl(isDefaultConstructor(),
2500 unless(isImplicit()))));
2501 EXPECT_TRUE(notMatches(
2502 "struct S { S(); };",
2503 cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
2504 EXPECT_TRUE(notMatches(
2505 "struct S { S(); };",
2506 cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
2507
2508 EXPECT_TRUE(notMatches(
2509 "struct S { S(const S&); };",
2510 cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
2511 EXPECT_TRUE(
2512 matches("struct S { S(const S&); };",
2513 cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
2514 EXPECT_TRUE(notMatches(
2515 "struct S { S(const S&); };",
2516 cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
2517
2518 EXPECT_TRUE(notMatches(
2519 "struct S { S(S&&); };",
2520 cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
2521 EXPECT_TRUE(notMatches(
2522 "struct S { S(S&&); };",
2523 cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
2524 EXPECT_TRUE(
2525 matches("struct S { S(S&&); };",
2526 cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
2527}
2528
2529TEST_P(ASTMatchersTest, IsUserProvided) {
2530 if (!GetParam().isCXX11OrLater()) {
2531 return;
2532 }
2533
2534 EXPECT_TRUE(notMatches("struct S { int X = 0; };",
2535 cxxConstructorDecl(isUserProvided())));
2536 EXPECT_TRUE(notMatches("struct S { S() = default; };",
2537 cxxConstructorDecl(isUserProvided())));
2538 EXPECT_TRUE(notMatches("struct S { S() = delete; };",
2539 cxxConstructorDecl(isUserProvided())));
2540 EXPECT_TRUE(
2541 matches("struct S { S(); };", cxxConstructorDecl(isUserProvided())));
2542 EXPECT_TRUE(matches("struct S { S(); }; S::S(){}",
2543 cxxConstructorDecl(isUserProvided())));
2544}
2545
2546TEST_P(ASTMatchersTest, IsDelegatingConstructor) {
2547 if (!GetParam().isCXX11OrLater()) {
2548 return;
2549 }
2550
2551 EXPECT_TRUE(notMatches("struct S { S(); S(int); int X; };",
2552 cxxConstructorDecl(isDelegatingConstructor())));
2553 EXPECT_TRUE(notMatches("struct S { S(){} S(int X) : X(X) {} int X; };",
2554 cxxConstructorDecl(isDelegatingConstructor())));
2555 EXPECT_TRUE(matches(
2556 "struct S { S() : S(0) {} S(int X) : X(X) {} int X; };",
2557 cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(0))));
2558 EXPECT_TRUE(matches(
2559 "struct S { S(); S(int X); int X; }; S::S(int X) : S() {}",
2560 cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(1))));
2561}
2562
2563TEST_P(ASTMatchersTest, HasSize) {
2564 StatementMatcher Literal = stringLiteral(hasSize(N: 4));
2565 EXPECT_TRUE(matches("const char *s = \"abcd\";", Literal));
2566 // with escaped characters
2567 EXPECT_TRUE(matches("const char *s = \"\x05\x06\x07\x08\";", Literal));
2568 // no matching, too small
2569 EXPECT_TRUE(notMatches("const char *s = \"ab\";", Literal));
2570}
2571
2572TEST_P(ASTMatchersTest, HasSize_CXX) {
2573 if (!GetParam().isCXX()) {
2574 // FIXME: Fix this test to also work in non-C++ language modes.
2575 return;
2576 }
2577
2578 StatementMatcher Literal = stringLiteral(hasSize(N: 4));
2579 // wide string
2580 EXPECT_TRUE(matches("const wchar_t *s = L\"abcd\";", Literal));
2581}
2582
2583TEST_P(ASTMatchersTest, HasName_MatchesNamespaces) {
2584 if (!GetParam().isCXX()) {
2585 return;
2586 }
2587
2588 EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2589 recordDecl(hasName("a::b::C"))));
2590 EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2591 recordDecl(hasName("::a::b::C"))));
2592 EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2593 recordDecl(hasName("b::C"))));
2594 EXPECT_TRUE(matches("namespace a { namespace b { class C; } }",
2595 recordDecl(hasName("C"))));
2596 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2597 recordDecl(hasName("c::b::C"))));
2598 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2599 recordDecl(hasName("a::c::C"))));
2600 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2601 recordDecl(hasName("a::b::A"))));
2602 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2603 recordDecl(hasName("::C"))));
2604 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2605 recordDecl(hasName("::b::C"))));
2606 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2607 recordDecl(hasName("z::a::b::C"))));
2608 EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }",
2609 recordDecl(hasName("a+b::C"))));
2610 EXPECT_TRUE(notMatches("namespace a { namespace b { class AC; } }",
2611 recordDecl(hasName("C"))));
2612 EXPECT_TRUE(matches("namespace a { inline namespace a { class C; } }",
2613 recordDecl(hasName("::a::C"))));
2614 EXPECT_TRUE(matches("namespace a { inline namespace a { class C; } }",
2615 recordDecl(hasName("::a::a::C"))));
2616}
2617
2618TEST_P(ASTMatchersTest, HasName_MatchesOuterClasses) {
2619 if (!GetParam().isCXX()) {
2620 return;
2621 }
2622
2623 EXPECT_TRUE(matches("class A { class B { class C; }; };",
2624 recordDecl(hasName("A::B::C"))));
2625 EXPECT_TRUE(matches("class A { class B { class C; }; };",
2626 recordDecl(hasName("::A::B::C"))));
2627 EXPECT_TRUE(matches("class A { class B { class C; }; };",
2628 recordDecl(hasName("B::C"))));
2629 EXPECT_TRUE(
2630 matches("class A { class B { class C; }; };", recordDecl(hasName("C"))));
2631 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2632 recordDecl(hasName("c::B::C"))));
2633 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2634 recordDecl(hasName("A::c::C"))));
2635 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2636 recordDecl(hasName("A::B::A"))));
2637 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2638 recordDecl(hasName("::C"))));
2639 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2640 recordDecl(hasName("::B::C"))));
2641 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2642 recordDecl(hasName("z::A::B::C"))));
2643 EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
2644 recordDecl(hasName("A+B::C"))));
2645}
2646
2647TEST_P(ASTMatchersTest, HasName_MatchesInlinedNamespaces) {
2648 if (!GetParam().isCXX()) {
2649 return;
2650 }
2651
2652 StringRef code = "namespace a { inline namespace b { class C; } }";
2653 EXPECT_TRUE(matches(code, recordDecl(hasName("a::b::C"))));
2654 EXPECT_TRUE(matches(code, recordDecl(hasName("a::C"))));
2655 EXPECT_TRUE(matches(code, recordDecl(hasName("::a::b::C"))));
2656 EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C"))));
2657}
2658
2659TEST_P(ASTMatchersTest, HasName_MatchesSpecializedInlinedNamespace) {
2660 if (!GetParam().isCXX11OrLater()) {
2661 return;
2662 }
2663
2664 StringRef code = R"(
2665namespace a {
2666 inline namespace v1 {
2667 template<typename T> T foo(T);
2668 }
2669}
2670
2671namespace a {
2672 enum Tag{T1, T2};
2673
2674 template <Tag, typename T> T foo(T);
2675}
2676
2677auto v1 = a::foo(1);
2678auto v2 = a::foo<a::T1>(1);
2679)";
2680 EXPECT_TRUE(matches(
2681 code, varDecl(hasName("v1"), hasDescendant(callExpr(callee(
2682 functionDecl(hasName("::a::foo"))))))));
2683 EXPECT_TRUE(matches(
2684 code, varDecl(hasName("v2"), hasDescendant(callExpr(callee(
2685 functionDecl(hasName("::a::foo"))))))));
2686}
2687
2688TEST_P(ASTMatchersTest, HasName_MatchesAnonymousNamespaces) {
2689 if (!GetParam().isCXX()) {
2690 return;
2691 }
2692
2693 StringRef code = "namespace a { namespace { class C; } }";
2694 EXPECT_TRUE(
2695 matches(code, recordDecl(hasName("a::(anonymous namespace)::C"))));
2696 EXPECT_TRUE(matches(code, recordDecl(hasName("a::C"))));
2697 EXPECT_TRUE(
2698 matches(code, recordDecl(hasName("::a::(anonymous namespace)::C"))));
2699 EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C"))));
2700}
2701
2702TEST_P(ASTMatchersTest, HasName_MatchesAnonymousOuterClasses) {
2703 if (!GetParam().isCXX()) {
2704 return;
2705 }
2706
2707 EXPECT_TRUE(matches("class A { class { class C; } x; };",
2708 recordDecl(hasName("A::(anonymous class)::C"))));
2709 EXPECT_TRUE(matches("class A { class { class C; } x; };",
2710 recordDecl(hasName("::A::(anonymous class)::C"))));
2711 EXPECT_FALSE(matches("class A { class { class C; } x; };",
2712 recordDecl(hasName("::A::C"))));
2713 EXPECT_TRUE(matches("class A { struct { class C; } x; };",
2714 recordDecl(hasName("A::(anonymous struct)::C"))));
2715 EXPECT_TRUE(matches("class A { struct { class C; } x; };",
2716 recordDecl(hasName("::A::(anonymous struct)::C"))));
2717 EXPECT_FALSE(matches("class A { struct { class C; } x; };",
2718 recordDecl(hasName("::A::C"))));
2719}
2720
2721TEST_P(ASTMatchersTest, HasName_MatchesFunctionScope) {
2722 if (!GetParam().isCXX()) {
2723 return;
2724 }
2725
2726 StringRef code =
2727 "namespace a { void F(int a) { struct S { int m; }; int i; } }";
2728 EXPECT_TRUE(matches(code, varDecl(hasName("i"))));
2729 EXPECT_FALSE(matches(code, varDecl(hasName("F()::i"))));
2730
2731 EXPECT_TRUE(matches(code, fieldDecl(hasName("m"))));
2732 EXPECT_TRUE(matches(code, fieldDecl(hasName("S::m"))));
2733 EXPECT_TRUE(matches(code, fieldDecl(hasName("F(int)::S::m"))));
2734 EXPECT_TRUE(matches(code, fieldDecl(hasName("a::F(int)::S::m"))));
2735 EXPECT_TRUE(matches(code, fieldDecl(hasName("::a::F(int)::S::m"))));
2736}
2737
2738TEST_P(ASTMatchersTest, HasName_QualifiedStringMatchesThroughLinkage) {
2739 if (!GetParam().isCXX()) {
2740 return;
2741 }
2742
2743 // https://bugs.llvm.org/show_bug.cgi?id=42193
2744 StringRef code = R"cpp(namespace foo { extern "C" void test(); })cpp";
2745 EXPECT_TRUE(matches(code, functionDecl(hasName("test"))));
2746 EXPECT_TRUE(matches(code, functionDecl(hasName("foo::test"))));
2747 EXPECT_TRUE(matches(code, functionDecl(hasName("::foo::test"))));
2748 EXPECT_TRUE(notMatches(code, functionDecl(hasName("::test"))));
2749
2750 code = R"cpp(namespace foo { extern "C" { void test(); } })cpp";
2751 EXPECT_TRUE(matches(code, functionDecl(hasName("test"))));
2752 EXPECT_TRUE(matches(code, functionDecl(hasName("foo::test"))));
2753 EXPECT_TRUE(matches(code, functionDecl(hasName("::foo::test"))));
2754 EXPECT_TRUE(notMatches(code, functionDecl(hasName("::test"))));
2755}
2756
2757TEST_P(ASTMatchersTest, HasAnyName) {
2758 if (!GetParam().isCXX()) {
2759 // FIXME: Add a test for `hasAnyName()` that does not depend on C++.
2760 return;
2761 }
2762
2763 StringRef Code = "namespace a { namespace b { class C; } }";
2764
2765 EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("XX", "a::b::C"))));
2766 EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("a::b::C", "XX"))));
2767 EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("XX::C", "a::b::C"))));
2768 EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("XX", "C"))));
2769
2770 EXPECT_TRUE(notMatches(Code, recordDecl(hasAnyName("::C", "::b::C"))));
2771 EXPECT_TRUE(
2772 matches(Code, recordDecl(hasAnyName("::C", "::b::C", "::a::b::C"))));
2773
2774 std::vector<StringRef> Names = {"::C", "::b::C", "::a::b::C"};
2775 EXPECT_TRUE(matches(Code, recordDecl(hasAnyName(Names))));
2776}
2777
2778TEST_P(ASTMatchersTest, IsDefinition) {
2779 DeclarationMatcher DefinitionOfClassA =
2780 recordDecl(hasName(Name: "A"), isDefinition());
2781 EXPECT_TRUE(matches("struct A {};", DefinitionOfClassA));
2782 EXPECT_TRUE(notMatches("struct A;", DefinitionOfClassA));
2783
2784 DeclarationMatcher DefinitionOfVariableA =
2785 varDecl(hasName(Name: "a"), isDefinition());
2786 EXPECT_TRUE(matches("int a;", DefinitionOfVariableA));
2787 EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
2788}
2789
2790TEST_P(ASTMatchersTest, IsDefinition_CXX) {
2791 if (!GetParam().isCXX()) {
2792 return;
2793 }
2794
2795 DeclarationMatcher DefinitionOfMethodA =
2796 cxxMethodDecl(hasName(Name: "a"), isDefinition());
2797 EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
2798 EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
2799
2800 DeclarationMatcher DefinitionOfObjCMethodA =
2801 objcMethodDecl(hasName(Name: "a"), isDefinition());
2802 EXPECT_TRUE(matchesObjC("@interface A @end "
2803 "@implementation A; -(void)a {} @end",
2804 DefinitionOfObjCMethodA));
2805 EXPECT_TRUE(
2806 notMatchesObjC("@interface A; - (void)a; @end", DefinitionOfObjCMethodA));
2807}
2808
2809TEST_P(ASTMatchersTest, HandlesNullQualTypes) {
2810 if (!GetParam().isCXX()) {
2811 // FIXME: Add an equivalent test that does not depend on C++.
2812 return;
2813 }
2814
2815 // FIXME: Add a Type matcher so we can replace uses of this
2816 // variable with Type(True())
2817 const TypeMatcher AnyType = anything();
2818
2819 // We don't really care whether this matcher succeeds; we're testing that
2820 // it completes without crashing.
2821 EXPECT_TRUE(matches(
2822 "struct A { };"
2823 "template <typename T>"
2824 "void f(T t) {"
2825 " T local_t(t /* this becomes a null QualType in the AST */);"
2826 "}"
2827 "void g() {"
2828 " f(0);"
2829 "}",
2830 expr(hasType(TypeMatcher(anyOf(TypeMatcher(hasDeclaration(anything())),
2831 pointsTo(AnyType), references(AnyType)
2832 // Other QualType matchers should go here.
2833 ))))));
2834}
2835
2836TEST_P(ASTMatchersTest, ObjCIvarRefExpr) {
2837 StringRef ObjCString =
2838 "@interface A @end "
2839 "@implementation A { A *x; } - (void) func { x = 0; } @end";
2840 EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr()));
2841 EXPECT_TRUE(matchesObjC(
2842 ObjCString, objcIvarRefExpr(hasDeclaration(namedDecl(hasName("x"))))));
2843 EXPECT_FALSE(matchesObjC(
2844 ObjCString, objcIvarRefExpr(hasDeclaration(namedDecl(hasName("y"))))));
2845}
2846
2847TEST_P(ASTMatchersTest, BlockExpr) {
2848 EXPECT_TRUE(matchesObjC("void f() { ^{}(); }", blockExpr()));
2849}
2850
2851TEST_P(ASTMatchersTest,
2852 StatementCountIs_FindsNoStatementsInAnEmptyCompoundStatement) {
2853 EXPECT_TRUE(matches("void f() { }", compoundStmt(statementCountIs(0))));
2854 EXPECT_TRUE(notMatches("void f() {}", compoundStmt(statementCountIs(1))));
2855}
2856
2857TEST_P(ASTMatchersTest, StatementCountIs_AppearsToMatchOnlyOneCount) {
2858 EXPECT_TRUE(matches("void f() { 1; }", compoundStmt(statementCountIs(1))));
2859 EXPECT_TRUE(notMatches("void f() { 1; }", compoundStmt(statementCountIs(0))));
2860 EXPECT_TRUE(notMatches("void f() { 1; }", compoundStmt(statementCountIs(2))));
2861}
2862
2863TEST_P(ASTMatchersTest, StatementCountIs_WorksWithMultipleStatements) {
2864 EXPECT_TRUE(
2865 matches("void f() { 1; 2; 3; }", compoundStmt(statementCountIs(3))));
2866}
2867
2868TEST_P(ASTMatchersTest, StatementCountIs_WorksWithNestedCompoundStatements) {
2869 EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
2870 compoundStmt(statementCountIs(1))));
2871 EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
2872 compoundStmt(statementCountIs(2))));
2873 EXPECT_TRUE(notMatches("void f() { { 1; } { 1; 2; 3; 4; } }",
2874 compoundStmt(statementCountIs(3))));
2875 EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }",
2876 compoundStmt(statementCountIs(4))));
2877}
2878
2879TEST_P(ASTMatchersTest, Member_WorksInSimplestCase) {
2880 if (!GetParam().isCXX()) {
2881 // FIXME: Add a test for `member()` that does not depend on C++.
2882 return;
2883 }
2884 EXPECT_TRUE(matches("struct { int first; } s; int i(s.first);",
2885 memberExpr(member(hasName("first")))));
2886}
2887
2888TEST_P(ASTMatchersTest, Member_DoesNotMatchTheBaseExpression) {
2889 if (!GetParam().isCXX()) {
2890 // FIXME: Add a test for `member()` that does not depend on C++.
2891 return;
2892 }
2893
2894 // Don't pick out the wrong part of the member expression, this should
2895 // be checking the member (name) only.
2896 EXPECT_TRUE(notMatches("struct { int i; } first; int i(first.i);",
2897 memberExpr(member(hasName("first")))));
2898}
2899
2900TEST_P(ASTMatchersTest, Member_MatchesInMemberFunctionCall) {
2901 if (!GetParam().isCXX()) {
2902 return;
2903 }
2904
2905 EXPECT_TRUE(matches("void f() {"
2906 " struct { void first() {}; } s;"
2907 " s.first();"
2908 "};",
2909 memberExpr(member(hasName("first")))));
2910}
2911
2912TEST_P(ASTMatchersTest, FieldDecl) {
2913 EXPECT_TRUE(
2914 matches("struct A { int i; }; void f() { struct A a; a.i = 2; }",
2915 memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
2916 EXPECT_TRUE(
2917 notMatches("struct A { float f; }; void f() { struct A a; a.f = 2.0f; }",
2918 memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
2919}
2920
2921TEST_P(ASTMatchersTest, IsBitField) {
2922 EXPECT_TRUE(matches("struct C { int a : 2; int b; };",
2923 fieldDecl(isBitField(), hasName("a"))));
2924 EXPECT_TRUE(notMatches("struct C { int a : 2; int b; };",
2925 fieldDecl(isBitField(), hasName("b"))));
2926 EXPECT_TRUE(matches("struct C { int a : 2; int b : 4; };",
2927 fieldDecl(isBitField(), hasBitWidth(2), hasName("a"))));
2928}
2929
2930TEST_P(ASTMatchersTest, HasInClassInitializer) {
2931 if (!GetParam().isCXX()) {
2932 return;
2933 }
2934
2935 EXPECT_TRUE(
2936 matches("class C { int a = 2; int b; };",
2937 fieldDecl(hasInClassInitializer(integerLiteral(equals(2))),
2938 hasName("a"))));
2939 EXPECT_TRUE(
2940 notMatches("class C { int a = 2; int b; };",
2941 fieldDecl(hasInClassInitializer(anything()), hasName("b"))));
2942}
2943
2944TEST_P(ASTMatchersTest, IsPublic_IsProtected_IsPrivate) {
2945 if (!GetParam().isCXX()) {
2946 return;
2947 }
2948
2949 EXPECT_TRUE(
2950 matches("struct A { int i; };", fieldDecl(isPublic(), hasName("i"))));
2951 EXPECT_TRUE(notMatches("struct A { int i; };",
2952 fieldDecl(isProtected(), hasName("i"))));
2953 EXPECT_TRUE(
2954 notMatches("struct A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
2955
2956 EXPECT_TRUE(
2957 notMatches("class A { int i; };", fieldDecl(isPublic(), hasName("i"))));
2958 EXPECT_TRUE(notMatches("class A { int i; };",
2959 fieldDecl(isProtected(), hasName("i"))));
2960 EXPECT_TRUE(
2961 matches("class A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
2962
2963 EXPECT_TRUE(notMatches("class A { protected: int i; };",
2964 fieldDecl(isPublic(), hasName("i"))));
2965 EXPECT_TRUE(matches("class A { protected: int i; };",
2966 fieldDecl(isProtected(), hasName("i"))));
2967 EXPECT_TRUE(notMatches("class A { protected: int i; };",
2968 fieldDecl(isPrivate(), hasName("i"))));
2969
2970 // Non-member decls have the AccessSpecifier AS_none and thus aren't matched.
2971 EXPECT_TRUE(notMatches("int i;", varDecl(isPublic(), hasName("i"))));
2972 EXPECT_TRUE(notMatches("int i;", varDecl(isProtected(), hasName("i"))));
2973 EXPECT_TRUE(notMatches("int i;", varDecl(isPrivate(), hasName("i"))));
2974}
2975
2976TEST_P(ASTMatchersTest,
2977 HasDynamicExceptionSpec_MatchesDynamicExceptionSpecifications) {
2978 if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
2979 return;
2980 }
2981
2982 EXPECT_TRUE(notMatches("void f();", functionDecl(hasDynamicExceptionSpec())));
2983 EXPECT_TRUE(
2984 matches("void j() throw();", functionDecl(hasDynamicExceptionSpec())));
2985 EXPECT_TRUE(
2986 matches("void k() throw(int);", functionDecl(hasDynamicExceptionSpec())));
2987 EXPECT_TRUE(
2988 matches("void l() throw(...);", functionDecl(hasDynamicExceptionSpec())));
2989
2990 EXPECT_TRUE(
2991 notMatches("void f();", functionProtoType(hasDynamicExceptionSpec())));
2992 EXPECT_TRUE(matches("void j() throw();",
2993 functionProtoType(hasDynamicExceptionSpec())));
2994 EXPECT_TRUE(matches("void k() throw(int);",
2995 functionProtoType(hasDynamicExceptionSpec())));
2996 EXPECT_TRUE(matches("void l() throw(...);",
2997 functionProtoType(hasDynamicExceptionSpec())));
2998}
2999
3000TEST_P(ASTMatchersTest,
3001 HasDynamicExceptionSpec_MatchesDynamicExceptionSpecifications_CXX11) {
3002 if (!GetParam().isCXX11OrLater()) {
3003 return;
3004 }
3005
3006 EXPECT_TRUE(notMatches("void g() noexcept;",
3007 functionDecl(hasDynamicExceptionSpec())));
3008 EXPECT_TRUE(notMatches("void h() noexcept(true);",
3009 functionDecl(hasDynamicExceptionSpec())));
3010 EXPECT_TRUE(notMatches("void i() noexcept(false);",
3011 functionDecl(hasDynamicExceptionSpec())));
3012
3013 EXPECT_TRUE(notMatches("void g() noexcept;",
3014 functionProtoType(hasDynamicExceptionSpec())));
3015 EXPECT_TRUE(notMatches("void h() noexcept(true);",
3016 functionProtoType(hasDynamicExceptionSpec())));
3017 EXPECT_TRUE(notMatches("void i() noexcept(false);",
3018 functionProtoType(hasDynamicExceptionSpec())));
3019}
3020
3021TEST_P(ASTMatchersTest, HasObjectExpression_DoesNotMatchMember) {
3022 if (!GetParam().isCXX()) {
3023 return;
3024 }
3025
3026 EXPECT_TRUE(notMatches(
3027 "class X {}; struct Z { X m; }; void f(Z z) { z.m; }",
3028 memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
3029}
3030
3031TEST_P(ASTMatchersTest, HasObjectExpression_MatchesBaseOfVariable) {
3032 EXPECT_TRUE(matches(
3033 "struct X { int m; }; void f(struct X x) { x.m; }",
3034 memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
3035 EXPECT_TRUE(matches("struct X { int m; }; void f(struct X* x) { x->m; }",
3036 memberExpr(hasObjectExpression(
3037 hasType(pointsTo(recordDecl(hasName("X"))))))));
3038}
3039
3040TEST_P(ASTMatchersTest, HasObjectExpression_MatchesBaseOfVariable_CXX) {
3041 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3042 // FIXME: Fix this test to work with delayed template parsing.
3043 return;
3044 }
3045
3046 EXPECT_TRUE(matches("template <class T> struct X { void f() { T t; t.m; } };",
3047 cxxDependentScopeMemberExpr(hasObjectExpression(
3048 declRefExpr(to(namedDecl(hasName("t"))))))));
3049 EXPECT_TRUE(
3050 matches("template <class T> struct X { void f() { T t; t->m; } };",
3051 cxxDependentScopeMemberExpr(hasObjectExpression(
3052 declRefExpr(to(namedDecl(hasName("t"))))))));
3053}
3054
3055TEST_P(ASTMatchersTest, HasObjectExpression_MatchesBaseOfMemberFunc) {
3056 if (!GetParam().isCXX()) {
3057 return;
3058 }
3059
3060 EXPECT_TRUE(matches(
3061 "struct X { void f(); }; void g(X x) { x.f(); }",
3062 memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
3063}
3064
3065TEST_P(ASTMatchersTest, HasObjectExpression_MatchesBaseOfMemberFunc_Template) {
3066 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3067 // FIXME: Fix this test to work with delayed template parsing.
3068 return;
3069 }
3070
3071 EXPECT_TRUE(matches("struct X { template <class T> void f(); };"
3072 "template <class T> void g(X x) { x.f<T>(); }",
3073 unresolvedMemberExpr(hasObjectExpression(
3074 hasType(recordDecl(hasName("X")))))));
3075 EXPECT_TRUE(matches("template <class T> void f(T t) { t.g(); }",
3076 cxxDependentScopeMemberExpr(hasObjectExpression(
3077 declRefExpr(to(namedDecl(hasName("t"))))))));
3078}
3079
3080TEST_P(ASTMatchersTest, HasObjectExpression_ImplicitlyFormedMemberExpression) {
3081 if (!GetParam().isCXX()) {
3082 return;
3083 }
3084
3085 EXPECT_TRUE(matches("class X {}; struct S { X m; void f() { this->m; } };",
3086 memberExpr(hasObjectExpression(
3087 hasType(pointsTo(recordDecl(hasName("S"))))))));
3088 EXPECT_TRUE(matches("class X {}; struct S { X m; void f() { m; } };",
3089 memberExpr(hasObjectExpression(
3090 hasType(pointsTo(recordDecl(hasName("S"))))))));
3091}
3092
3093TEST_P(ASTMatchersTest, FieldDecl_DoesNotMatchNonFieldMembers) {
3094 if (!GetParam().isCXX()) {
3095 return;
3096 }
3097
3098 EXPECT_TRUE(notMatches("class X { void m(); };", fieldDecl(hasName("m"))));
3099 EXPECT_TRUE(notMatches("class X { class m {}; };", fieldDecl(hasName("m"))));
3100 EXPECT_TRUE(notMatches("class X { enum { m }; };", fieldDecl(hasName("m"))));
3101 EXPECT_TRUE(notMatches("class X { enum m {}; };", fieldDecl(hasName("m"))));
3102}
3103
3104TEST_P(ASTMatchersTest, FieldDecl_MatchesField) {
3105 EXPECT_TRUE(matches("struct X { int m; };", fieldDecl(hasName("m"))));
3106}
3107
3108TEST_P(ASTMatchersTest, IsVolatileQualified) {
3109 EXPECT_TRUE(
3110 matches("volatile int i = 42;", varDecl(hasType(isVolatileQualified()))));
3111 EXPECT_TRUE(
3112 notMatches("volatile int *i;", varDecl(hasType(isVolatileQualified()))));
3113 EXPECT_TRUE(matches("typedef volatile int v_int; v_int i = 42;",
3114 varDecl(hasType(isVolatileQualified()))));
3115}
3116
3117TEST_P(ASTMatchersTest, IsConstQualified_MatchesConstInt) {
3118 EXPECT_TRUE(
3119 matches("const int i = 42;", varDecl(hasType(isConstQualified()))));
3120}
3121
3122TEST_P(ASTMatchersTest, IsConstQualified_MatchesConstPointer) {
3123 EXPECT_TRUE(matches("int i = 42; int* const p = &i;",
3124 varDecl(hasType(isConstQualified()))));
3125}
3126
3127TEST_P(ASTMatchersTest, IsConstQualified_MatchesThroughTypedef) {
3128 EXPECT_TRUE(matches("typedef const int const_int; const_int i = 42;",
3129 varDecl(hasType(isConstQualified()))));
3130 EXPECT_TRUE(matches("typedef int* int_ptr; const int_ptr p = ((int*)0);",
3131 varDecl(hasType(isConstQualified()))));
3132}
3133
3134TEST_P(ASTMatchersTest, IsConstQualified_DoesNotMatchInappropriately) {
3135 EXPECT_TRUE(notMatches("typedef int nonconst_int; nonconst_int i = 42;",
3136 varDecl(hasType(isConstQualified()))));
3137 EXPECT_TRUE(
3138 notMatches("int const* p;", varDecl(hasType(isConstQualified()))));
3139}
3140
3141TEST_P(ASTMatchersTest, DeclCountIs_DeclCountIsCorrect) {
3142 EXPECT_TRUE(matches("void f() {int i,j;}", declStmt(declCountIs(2))));
3143 EXPECT_TRUE(
3144 notMatches("void f() {int i,j; int k;}", declStmt(declCountIs(3))));
3145 EXPECT_TRUE(
3146 notMatches("void f() {int i,j, k, l;}", declStmt(declCountIs(3))));
3147}
3148
3149TEST_P(ASTMatchersTest, EachOf_TriggersForEachMatch) {
3150 EXPECT_TRUE(matchAndVerifyResultTrue(
3151 "class A { int a; int b; };",
3152 recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3153 has(fieldDecl(hasName("b")).bind("v")))),
3154 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 2)));
3155}
3156
3157TEST_P(ASTMatchersTest, EachOf_BehavesLikeAnyOfUnlessBothMatch) {
3158 EXPECT_TRUE(matchAndVerifyResultTrue(
3159 "struct A { int a; int c; };",
3160 recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3161 has(fieldDecl(hasName("b")).bind("v")))),
3162 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 1)));
3163 EXPECT_TRUE(matchAndVerifyResultTrue(
3164 "struct A { int c; int b; };",
3165 recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3166 has(fieldDecl(hasName("b")).bind("v")))),
3167 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 1)));
3168 EXPECT_TRUE(
3169 notMatches("struct A { int c; int d; };",
3170 recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
3171 has(fieldDecl(hasName("b")).bind("v"))))));
3172}
3173
3174TEST_P(ASTMatchersTest, Optionally_SubmatchersDoNotMatch) {
3175 EXPECT_TRUE(matchAndVerifyResultFalse(
3176 "class A { int a; int b; };",
3177 recordDecl(optionally(has(fieldDecl(hasName("c")).bind("c")))),
3178 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("c")));
3179}
3180
3181// Regression test.
3182TEST_P(ASTMatchersTest, Optionally_SubmatchersDoNotMatchButPreserveBindings) {
3183 StringRef Code = "class A { int a; int b; };";
3184 auto Matcher = recordDecl(decl().bind(ID: "decl"),
3185 optionally(has(fieldDecl(hasName(Name: "c")).bind(ID: "v"))));
3186 // "decl" is still bound.
3187 EXPECT_TRUE(matchAndVerifyResultTrue(
3188 Code, Matcher, std::make_unique<VerifyIdIsBoundTo<RecordDecl>>("decl")));
3189 // "v" is not bound, but the match still suceeded.
3190 EXPECT_TRUE(matchAndVerifyResultFalse(
3191 Code, Matcher, std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v")));
3192}
3193
3194TEST_P(ASTMatchersTest, Optionally_SubmatchersMatch) {
3195 EXPECT_TRUE(matchAndVerifyResultTrue(
3196 "class A { int a; int c; };",
3197 recordDecl(optionally(has(fieldDecl(hasName("a")).bind("v")))),
3198 std::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v")));
3199}
3200
3201TEST_P(ASTMatchersTest,
3202 IsTemplateInstantiation_MatchesImplicitClassTemplateInstantiation) {
3203 if (!GetParam().isCXX()) {
3204 return;
3205 }
3206
3207 // Make sure that we can both match the class by name (::X) and by the type
3208 // the template was instantiated with (via a field).
3209
3210 EXPECT_TRUE(
3211 matches("template <typename T> class X {}; class A {}; X<A> x;",
3212 cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
3213
3214 EXPECT_TRUE(matches(
3215 "template <typename T> class X { T t; }; class A {}; X<A> x;",
3216 cxxRecordDecl(
3217 isTemplateInstantiation(),
3218 hasDescendant(fieldDecl(hasType(recordDecl(hasName("A"))))))));
3219}
3220
3221TEST_P(ASTMatchersTest,
3222 IsTemplateInstantiation_MatchesImplicitFunctionTemplateInstantiation) {
3223 if (!GetParam().isCXX()) {
3224 return;
3225 }
3226
3227 EXPECT_TRUE(matches(
3228 "template <typename T> void f(T t) {} class A {}; void g() { f(A()); }",
3229 functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
3230 isTemplateInstantiation())));
3231}
3232
3233TEST_P(ASTMatchersTest,
3234 IsTemplateInstantiation_MatchesExplicitClassTemplateInstantiation) {
3235 if (!GetParam().isCXX()) {
3236 return;
3237 }
3238
3239 EXPECT_TRUE(matches("template <typename T> class X { T t; }; class A {};"
3240 "template class X<A>;",
3241 cxxRecordDecl(isTemplateInstantiation(),
3242 hasDescendant(fieldDecl(
3243 hasType(recordDecl(hasName("A"))))))));
3244
3245 // Make sure that we match the instantiation instead of the template
3246 // definition by checking whether the member function is present.
3247 EXPECT_TRUE(
3248 matches("template <typename T> class X { void f() { T t; } };"
3249 "extern template class X<int>;",
3250 cxxRecordDecl(isTemplateInstantiation(),
3251 unless(hasDescendant(varDecl(hasName("t")))))));
3252}
3253
3254TEST_P(
3255 ASTMatchersTest,
3256 IsTemplateInstantiation_MatchesInstantiationOfPartiallySpecializedClassTemplate) {
3257 if (!GetParam().isCXX()) {
3258 return;
3259 }
3260
3261 EXPECT_TRUE(
3262 matches("template <typename T> class X {};"
3263 "template <typename T> class X<T*> {}; class A {}; X<A*> x;",
3264 cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
3265}
3266
3267TEST_P(
3268 ASTMatchersTest,
3269 IsTemplateInstantiation_MatchesInstantiationOfClassTemplateNestedInNonTemplate) {
3270 if (!GetParam().isCXX()) {
3271 return;
3272 }
3273
3274 EXPECT_TRUE(
3275 matches("class A {};"
3276 "class X {"
3277 " template <typename U> class Y { U u; };"
3278 " Y<A> y;"
3279 "};",
3280 cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation())));
3281}
3282
3283TEST_P(
3284 ASTMatchersTest,
3285 IsTemplateInstantiation_DoesNotMatchInstantiationsInsideOfInstantiation) {
3286 if (!GetParam().isCXX()) {
3287 return;
3288 }
3289
3290 // FIXME: Figure out whether this makes sense. It doesn't affect the
3291 // normal use case as long as the uppermost instantiation always is marked
3292 // as template instantiation, but it might be confusing as a predicate.
3293 EXPECT_TRUE(matches(
3294 "class A {};"
3295 "template <typename T> class X {"
3296 " template <typename U> class Y { U u; };"
3297 " Y<T> y;"
3298 "}; X<A> x;",
3299 cxxRecordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation()))));
3300}
3301
3302TEST_P(
3303 ASTMatchersTest,
3304 IsTemplateInstantiation_DoesNotMatchExplicitClassTemplateSpecialization) {
3305 if (!GetParam().isCXX()) {
3306 return;
3307 }
3308
3309 EXPECT_TRUE(
3310 notMatches("template <typename T> class X {}; class A {};"
3311 "template <> class X<A> {}; X<A> x;",
3312 cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
3313}
3314
3315TEST_P(ASTMatchersTest, IsTemplateInstantiation_DoesNotMatchNonTemplate) {
3316 if (!GetParam().isCXX()) {
3317 return;
3318 }
3319
3320 EXPECT_TRUE(notMatches("class A {}; class Y { A a; };",
3321 cxxRecordDecl(isTemplateInstantiation())));
3322}
3323
3324TEST_P(ASTMatchersTest, IsInstantiated_MatchesInstantiation) {
3325 if (!GetParam().isCXX()) {
3326 return;
3327 }
3328
3329 EXPECT_TRUE(
3330 matches("template<typename T> class A { T i; }; class Y { A<int> a; };",
3331 cxxRecordDecl(isInstantiated())));
3332}
3333
3334TEST_P(ASTMatchersTest, IsInstantiated_NotMatchesDefinition) {
3335 if (!GetParam().isCXX()) {
3336 return;
3337 }
3338
3339 EXPECT_TRUE(notMatches("template<typename T> class A { T i; };",
3340 cxxRecordDecl(isInstantiated())));
3341}
3342
3343TEST_P(ASTMatchersTest, IsInTemplateInstantiation_MatchesInstantiationStmt) {
3344 if (!GetParam().isCXX()) {
3345 return;
3346 }
3347
3348 EXPECT_TRUE(matches("template<typename T> struct A { A() { T i; } };"
3349 "class Y { A<int> a; }; Y y;",
3350 declStmt(isInTemplateInstantiation())));
3351}
3352
3353TEST_P(ASTMatchersTest, IsInTemplateInstantiation_NotMatchesDefinitionStmt) {
3354 if (!GetParam().isCXX()) {
3355 return;
3356 }
3357
3358 EXPECT_TRUE(notMatches("template<typename T> struct A { void x() { T i; } };",
3359 declStmt(isInTemplateInstantiation())));
3360}
3361
3362TEST_P(ASTMatchersTest, IsInstantiated_MatchesFunctionInstantiation) {
3363 if (!GetParam().isCXX()) {
3364 return;
3365 }
3366
3367 EXPECT_TRUE(
3368 matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
3369 functionDecl(isInstantiated())));
3370}
3371
3372TEST_P(ASTMatchersTest, IsInstantiated_NotMatchesFunctionDefinition) {
3373 if (!GetParam().isCXX()) {
3374 return;
3375 }
3376
3377 EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }",
3378 varDecl(isInstantiated())));
3379}
3380
3381TEST_P(ASTMatchersTest,
3382 IsInTemplateInstantiation_MatchesFunctionInstantiationStmt) {
3383 if (!GetParam().isCXX()) {
3384 return;
3385 }
3386
3387 EXPECT_TRUE(
3388 matches("template<typename T> void A(T t) { T i; } void x() { A(0); }",
3389 declStmt(isInTemplateInstantiation())));
3390}
3391
3392TEST_P(ASTMatchersTest,
3393 IsInTemplateInstantiation_NotMatchesFunctionDefinitionStmt) {
3394 if (!GetParam().isCXX()) {
3395 return;
3396 }
3397
3398 EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }",
3399 declStmt(isInTemplateInstantiation())));
3400}
3401
3402TEST_P(ASTMatchersTest, IsInstantiated_MatchesVariableInstantiation) {
3403 if (!GetParam().isCXX14OrLater()) {
3404 return;
3405 }
3406
3407 EXPECT_TRUE(matches("template<typename T> int V = 10; void x() { V<int>; }",
3408 varDecl(isInstantiated())));
3409}
3410
3411TEST_P(ASTMatchersTest, IsInstantiated_NotMatchesVariableDefinition) {
3412 if (!GetParam().isCXX14OrLater()) {
3413 return;
3414 }
3415
3416 EXPECT_TRUE(notMatches("template<typename T> int V = 10;",
3417 varDecl(isInstantiated())));
3418}
3419
3420TEST_P(ASTMatchersTest,
3421 IsInTemplateInstantiation_MatchesVariableInstantiationStmt) {
3422 if (!GetParam().isCXX14OrLater()) {
3423 return;
3424 }
3425
3426 EXPECT_TRUE(matches(
3427 "template<typename T> auto V = []() { T i; }; void x() { V<int>(); }",
3428 declStmt(isInTemplateInstantiation())));
3429}
3430
3431TEST_P(ASTMatchersTest,
3432 IsInTemplateInstantiation_NotMatchesVariableDefinitionStmt) {
3433 if (!GetParam().isCXX14OrLater()) {
3434 return;
3435 }
3436
3437 EXPECT_TRUE(notMatches("template<typename T> auto V = []() { T i; };",
3438 declStmt(isInTemplateInstantiation())));
3439}
3440
3441TEST_P(ASTMatchersTest, IsInTemplateInstantiation_Sharing) {
3442 if (!GetParam().isCXX()) {
3443 return;
3444 }
3445
3446 auto Matcher = binaryOperator(unless(isInTemplateInstantiation()));
3447 // FIXME: Node sharing is an implementation detail, exposing it is ugly
3448 // and makes the matcher behave in non-obvious ways.
3449 EXPECT_TRUE(notMatches(
3450 "int j; template<typename T> void A(T t) { j += 42; } void x() { A(0); }",
3451 Matcher));
3452 EXPECT_TRUE(matches(
3453 "int j; template<typename T> void A(T t) { j += t; } void x() { A(0); }",
3454 Matcher));
3455}
3456
3457TEST_P(ASTMatchersTest, IsInstantiationDependent_MatchesNonValueTypeDependent) {
3458 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3459 // FIXME: Fix this test to work with delayed template parsing.
3460 return;
3461 }
3462
3463 EXPECT_TRUE(matches(
3464 "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
3465 expr(isInstantiationDependent())));
3466}
3467
3468TEST_P(ASTMatchersTest, IsInstantiationDependent_MatchesValueDependent) {
3469 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3470 // FIXME: Fix this test to work with delayed template parsing.
3471 return;
3472 }
3473
3474 EXPECT_TRUE(matches("template<int T> int f() { return T; }",
3475 expr(isInstantiationDependent())));
3476}
3477
3478TEST_P(ASTMatchersTest, IsInstantiationDependent_MatchesTypeDependent) {
3479 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3480 // FIXME: Fix this test to work with delayed template parsing.
3481 return;
3482 }
3483
3484 EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
3485 expr(isInstantiationDependent())));
3486}
3487
3488TEST_P(ASTMatchersTest, IsTypeDependent_MatchesTypeDependent) {
3489 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3490 // FIXME: Fix this test to work with delayed template parsing.
3491 return;
3492 }
3493
3494 EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
3495 expr(isTypeDependent())));
3496}
3497
3498TEST_P(ASTMatchersTest, IsTypeDependent_NotMatchesValueDependent) {
3499 if (!GetParam().isCXX()) {
3500 return;
3501 }
3502
3503 EXPECT_TRUE(notMatches("template<int T> int f() { return T; }",
3504 expr(isTypeDependent())));
3505}
3506
3507TEST_P(ASTMatchersTest, IsValueDependent_MatchesValueDependent) {
3508 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3509 // FIXME: Fix this test to work with delayed template parsing.
3510 return;
3511 }
3512
3513 EXPECT_TRUE(matches("template<int T> int f() { return T; }",
3514 expr(isValueDependent())));
3515}
3516
3517TEST_P(ASTMatchersTest, IsValueDependent_MatchesTypeDependent) {
3518 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3519 // FIXME: Fix this test to work with delayed template parsing.
3520 return;
3521 }
3522
3523 EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
3524 expr(isValueDependent())));
3525}
3526
3527TEST_P(ASTMatchersTest, IsValueDependent_MatchesInstantiationDependent) {
3528 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
3529 // FIXME: Fix this test to work with delayed template parsing.
3530 return;
3531 }
3532
3533 EXPECT_TRUE(matches(
3534 "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
3535 expr(isValueDependent())));
3536}
3537
3538TEST_P(ASTMatchersTest,
3539 IsExplicitTemplateSpecialization_DoesNotMatchPrimaryTemplate) {
3540 if (!GetParam().isCXX()) {
3541 return;
3542 }
3543
3544 EXPECT_TRUE(notMatches("template <typename T> class X {};",
3545 cxxRecordDecl(isExplicitTemplateSpecialization())));
3546 EXPECT_TRUE(notMatches("template <typename T> void f(T t);",
3547 functionDecl(isExplicitTemplateSpecialization())));
3548}
3549
3550TEST_P(
3551 ASTMatchersTest,
3552 IsExplicitTemplateSpecialization_DoesNotMatchExplicitTemplateInstantiations) {
3553 if (!GetParam().isCXX()) {
3554 return;
3555 }
3556
3557 EXPECT_TRUE(
3558 notMatches("template <typename T> class X {};"
3559 "template class X<int>; extern template class X<long>;",
3560 cxxRecordDecl(isExplicitTemplateSpecialization())));
3561 EXPECT_TRUE(
3562 notMatches("template <typename T> void f(T t) {}"
3563 "template void f(int t); extern template void f(long t);",
3564 functionDecl(isExplicitTemplateSpecialization())));
3565}
3566
3567TEST_P(
3568 ASTMatchersTest,
3569 IsExplicitTemplateSpecialization_DoesNotMatchImplicitTemplateInstantiations) {
3570 if (!GetParam().isCXX()) {
3571 return;
3572 }
3573
3574 EXPECT_TRUE(notMatches("template <typename T> class X {}; X<int> x;",
3575 cxxRecordDecl(isExplicitTemplateSpecialization())));
3576 EXPECT_TRUE(
3577 notMatches("template <typename T> void f(T t); void g() { f(10); }",
3578 functionDecl(isExplicitTemplateSpecialization())));
3579}
3580
3581TEST_P(
3582 ASTMatchersTest,
3583 IsExplicitTemplateSpecialization_MatchesExplicitTemplateSpecializations) {
3584 if (!GetParam().isCXX()) {
3585 return;
3586 }
3587
3588 EXPECT_TRUE(matches("template <typename T> class X {};"
3589 "template<> class X<int> {};",
3590 cxxRecordDecl(isExplicitTemplateSpecialization())));
3591 EXPECT_TRUE(matches("template <typename T> void f(T t) {}"
3592 "template<> void f(int t) {}",
3593 functionDecl(isExplicitTemplateSpecialization())));
3594}
3595
3596TEST_P(ASTMatchersTest, IsNoReturn) {
3597 EXPECT_TRUE(notMatches("void func();", functionDecl(isNoReturn())));
3598 EXPECT_TRUE(notMatches("void func() {}", functionDecl(isNoReturn())));
3599
3600 EXPECT_TRUE(matches("__attribute__((noreturn)) void func();",
3601 functionDecl(isNoReturn())));
3602 EXPECT_TRUE(matches("__attribute__((noreturn)) void func() {}",
3603 functionDecl(isNoReturn())));
3604
3605 EXPECT_TRUE(matches("_Noreturn void func();", functionDecl(isNoReturn())));
3606 EXPECT_TRUE(matches("_Noreturn void func() {}", functionDecl(isNoReturn())));
3607}
3608
3609TEST_P(ASTMatchersTest, IsNoReturn_CXX) {
3610 if (!GetParam().isCXX()) {
3611 return;
3612 }
3613
3614 EXPECT_TRUE(
3615 notMatches("struct S { void func(); };", functionDecl(isNoReturn())));
3616 EXPECT_TRUE(
3617 notMatches("struct S { void func() {} };", functionDecl(isNoReturn())));
3618
3619 EXPECT_TRUE(notMatches("struct S { static void func(); };",
3620 functionDecl(isNoReturn())));
3621 EXPECT_TRUE(notMatches("struct S { static void func() {} };",
3622 functionDecl(isNoReturn())));
3623
3624 EXPECT_TRUE(notMatches("struct S { S(); };", functionDecl(isNoReturn())));
3625 EXPECT_TRUE(notMatches("struct S { S() {} };", functionDecl(isNoReturn())));
3626
3627 // ---
3628
3629 EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func(); };",
3630 functionDecl(isNoReturn())));
3631 EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func() {} };",
3632 functionDecl(isNoReturn())));
3633
3634 EXPECT_TRUE(
3635 matches("struct S { __attribute__((noreturn)) static void func(); };",
3636 functionDecl(isNoReturn())));
3637 EXPECT_TRUE(
3638 matches("struct S { __attribute__((noreturn)) static void func() {} };",
3639 functionDecl(isNoReturn())));
3640
3641 EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S(); };",
3642 functionDecl(isNoReturn())));
3643 EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S() {} };",
3644 functionDecl(isNoReturn())));
3645}
3646
3647TEST_P(ASTMatchersTest, IsNoReturn_CXX11Attribute) {
3648 if (!GetParam().isCXX11OrLater()) {
3649 return;
3650 }
3651
3652 EXPECT_TRUE(matches("[[noreturn]] void func();", functionDecl(isNoReturn())));
3653 EXPECT_TRUE(
3654 matches("[[noreturn]] void func() {}", functionDecl(isNoReturn())));
3655
3656 EXPECT_TRUE(matches("struct S { [[noreturn]] void func(); };",
3657 functionDecl(isNoReturn())));
3658 EXPECT_TRUE(matches("struct S { [[noreturn]] void func() {} };",
3659 functionDecl(isNoReturn())));
3660
3661 EXPECT_TRUE(matches("struct S { [[noreturn]] static void func(); };",
3662 functionDecl(isNoReturn())));
3663 EXPECT_TRUE(matches("struct S { [[noreturn]] static void func() {} };",
3664 functionDecl(isNoReturn())));
3665
3666 EXPECT_TRUE(
3667 matches("struct S { [[noreturn]] S(); };", functionDecl(isNoReturn())));
3668 EXPECT_TRUE(
3669 matches("struct S { [[noreturn]] S() {} };", functionDecl(isNoReturn())));
3670}
3671
3672TEST_P(ASTMatchersTest, BooleanType) {
3673 if (!GetParam().isCXX()) {
3674 // FIXME: Add a test for `booleanType()` that does not depend on C++.
3675 return;
3676 }
3677
3678 EXPECT_TRUE(matches("struct S { bool func(); };",
3679 cxxMethodDecl(returns(booleanType()))));
3680 EXPECT_TRUE(notMatches("struct S { void func(); };",
3681 cxxMethodDecl(returns(booleanType()))));
3682}
3683
3684TEST_P(ASTMatchersTest, VoidType) {
3685 if (!GetParam().isCXX()) {
3686 // FIXME: Add a test for `voidType()` that does not depend on C++.
3687 return;
3688 }
3689
3690 EXPECT_TRUE(matches("struct S { void func(); };",
3691 cxxMethodDecl(returns(voidType()))));
3692}
3693
3694TEST_P(ASTMatchersTest, RealFloatingPointType) {
3695 if (!GetParam().isCXX()) {
3696 // FIXME: Add a test for `realFloatingPointType()` that does not depend on
3697 // C++.
3698 return;
3699 }
3700
3701 EXPECT_TRUE(matches("struct S { float func(); };",
3702 cxxMethodDecl(returns(realFloatingPointType()))));
3703 EXPECT_TRUE(notMatches("struct S { int func(); };",
3704 cxxMethodDecl(returns(realFloatingPointType()))));
3705 EXPECT_TRUE(matches("struct S { long double func(); };",
3706 cxxMethodDecl(returns(realFloatingPointType()))));
3707}
3708
3709TEST_P(ASTMatchersTest, ArrayType) {
3710 EXPECT_TRUE(matches("int a[] = {2,3};", arrayType()));
3711 EXPECT_TRUE(matches("int a[42];", arrayType()));
3712 EXPECT_TRUE(matches("void f(int b) { int a[b]; }", arrayType()));
3713
3714 EXPECT_TRUE(notMatches("struct A {}; struct A a[7];",
3715 arrayType(hasElementType(builtinType()))));
3716
3717 EXPECT_TRUE(matches("int const a[] = { 2, 3 };",
3718 qualType(arrayType(hasElementType(builtinType())))));
3719 EXPECT_TRUE(matches(
3720 "int const a[] = { 2, 3 };",
3721 qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
3722 EXPECT_TRUE(matches("typedef const int T; T x[] = { 1, 2 };",
3723 qualType(isConstQualified(), arrayType())));
3724
3725 EXPECT_TRUE(notMatches(
3726 "int a[] = { 2, 3 };",
3727 qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
3728 EXPECT_TRUE(notMatches(
3729 "int a[] = { 2, 3 };",
3730 qualType(arrayType(hasElementType(isConstQualified(), builtinType())))));
3731 EXPECT_TRUE(notMatches("int const a[] = { 2, 3 };",
3732 qualType(arrayType(hasElementType(builtinType())),
3733 unless(isConstQualified()))));
3734
3735 EXPECT_TRUE(
3736 matches("int a[2];", constantArrayType(hasElementType(builtinType()))));
3737 EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger())));
3738}
3739
3740TEST_P(ASTMatchersTest, DecayedType) {
3741 EXPECT_TRUE(
3742 matches("void f(int i[]);",
3743 valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))));
3744 EXPECT_TRUE(notMatches("int i[7];", decayedType()));
3745}
3746
3747TEST_P(ASTMatchersTest, ComplexType) {
3748 EXPECT_TRUE(matches("_Complex float f;", complexType()));
3749 EXPECT_TRUE(
3750 matches("_Complex float f;", complexType(hasElementType(builtinType()))));
3751 EXPECT_TRUE(notMatches("_Complex float f;",
3752 complexType(hasElementType(isInteger()))));
3753}
3754
3755TEST_P(ASTMatchersTest, IsAnonymous) {
3756 if (!GetParam().isCXX()) {
3757 return;
3758 }
3759
3760 EXPECT_TRUE(notMatches("namespace N {}", namespaceDecl(isAnonymous())));
3761 EXPECT_TRUE(matches("namespace {}", namespaceDecl(isAnonymous())));
3762}
3763
3764TEST_P(ASTMatchersTest, InStdNamespace) {
3765 if (!GetParam().isCXX()) {
3766 return;
3767 }
3768
3769 EXPECT_TRUE(notMatches("class vector {};"
3770 "namespace foo {"
3771 " class vector {};"
3772 "}"
3773 "namespace foo {"
3774 " namespace std {"
3775 " class vector {};"
3776 " }"
3777 "}",
3778 cxxRecordDecl(hasName("vector"), isInStdNamespace())));
3779
3780 EXPECT_TRUE(matches("namespace std {"
3781 " class vector {};"
3782 "}",
3783 cxxRecordDecl(hasName("vector"), isInStdNamespace())));
3784
3785 EXPECT_TRUE(matches("namespace std {"
3786 " extern \"C++\" class vector {};"
3787 "}",
3788 cxxRecordDecl(hasName("vector"), isInStdNamespace())));
3789}
3790
3791TEST_P(ASTMatchersTest, InAnonymousNamespace) {
3792 if (!GetParam().isCXX()) {
3793 return;
3794 }
3795
3796 EXPECT_TRUE(
3797 notMatches("class vector {};"
3798 "namespace foo {"
3799 " class vector {};"
3800 "}",
3801 cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
3802
3803 EXPECT_TRUE(
3804 matches("namespace {"
3805 " class vector {};"
3806 "}",
3807 cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
3808
3809 EXPECT_TRUE(
3810 matches("namespace foo {"
3811 " namespace {"
3812 " class vector {};"
3813 " }"
3814 "}",
3815 cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
3816
3817 EXPECT_TRUE(
3818 matches("namespace {"
3819 " namespace foo {"
3820 " class vector {};"
3821 " }"
3822 "}",
3823 cxxRecordDecl(hasName("vector"), isInAnonymousNamespace())));
3824}
3825
3826TEST_P(ASTMatchersTest, InStdNamespace_CXX11) {
3827 if (!GetParam().isCXX11OrLater()) {
3828 return;
3829 }
3830
3831 EXPECT_TRUE(matches("namespace std {"
3832 " inline namespace __1 {"
3833 " class vector {};"
3834 " }"
3835 "}",
3836 cxxRecordDecl(hasName("vector"), isInStdNamespace())));
3837 EXPECT_TRUE(notMatches("namespace std {"
3838 " inline namespace __1 {"
3839 " inline namespace __fs {"
3840 " namespace filesystem {"
3841 " inline namespace v1 {"
3842 " class path {};"
3843 " }"
3844 " }"
3845 " }"
3846 " }"
3847 "}",
3848 cxxRecordDecl(hasName("path"), isInStdNamespace())));
3849 EXPECT_TRUE(
3850 matches("namespace std {"
3851 " inline namespace __1 {"
3852 " inline namespace __fs {"
3853 " namespace filesystem {"
3854 " inline namespace v1 {"
3855 " class path {};"
3856 " }"
3857 " }"
3858 " }"
3859 " }"
3860 "}",
3861 cxxRecordDecl(hasName("path"),
3862 hasAncestor(namespaceDecl(hasName("filesystem"),
3863 isInStdNamespace())))));
3864}
3865
3866TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_QualType) {
3867 EXPECT_TRUE(matches(
3868 "int i = 1;", varDecl(hasType(qualType().bind("type")),
3869 hasInitializer(ignoringParenImpCasts(
3870 hasType(qualType(equalsBoundNode("type"))))))));
3871 EXPECT_TRUE(notMatches("int i = 1.f;",
3872 varDecl(hasType(qualType().bind("type")),
3873 hasInitializer(ignoringParenImpCasts(hasType(
3874 qualType(equalsBoundNode("type"))))))));
3875}
3876
3877TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_NonMatchingTypes) {
3878 EXPECT_TRUE(notMatches(
3879 "int i = 1;", varDecl(namedDecl(hasName("i")).bind("name"),
3880 hasInitializer(ignoringParenImpCasts(
3881 hasType(qualType(equalsBoundNode("type"))))))));
3882}
3883
3884TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_Stmt) {
3885 EXPECT_TRUE(
3886 matches("void f() { if(1) {} }",
3887 stmt(allOf(ifStmt().bind("if"),
3888 hasParent(stmt(has(stmt(equalsBoundNode("if")))))))));
3889
3890 EXPECT_TRUE(notMatches(
3891 "void f() { if(1) { if (1) {} } }",
3892 stmt(allOf(ifStmt().bind("if"), has(stmt(equalsBoundNode("if")))))));
3893}
3894
3895TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_Decl) {
3896 if (!GetParam().isCXX()) {
3897 // FIXME: Add a test for `equalsBoundNode()` for declarations that does not
3898 // depend on C++.
3899 return;
3900 }
3901
3902 EXPECT_TRUE(matches(
3903 "class X { class Y {}; };",
3904 decl(allOf(recordDecl(hasName("::X::Y")).bind("record"),
3905 hasParent(decl(has(decl(equalsBoundNode("record")))))))));
3906
3907 EXPECT_TRUE(notMatches("class X { class Y {}; };",
3908 decl(allOf(recordDecl(hasName("::X")).bind("record"),
3909 has(decl(equalsBoundNode("record")))))));
3910}
3911
3912TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_Type) {
3913 if (!GetParam().isCXX()) {
3914 // FIXME: Add a test for `equalsBoundNode()` for types that does not depend
3915 // on C++.
3916 return;
3917 }
3918 EXPECT_TRUE(matches(
3919 "class X { int a; int b; };",
3920 recordDecl(
3921 has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
3922 has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
3923
3924 EXPECT_TRUE(notMatches(
3925 "class X { int a; double b; };",
3926 recordDecl(
3927 has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
3928 has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
3929}
3930
3931TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_UsingForEachDescendant) {
3932 EXPECT_TRUE(matchAndVerifyResultTrue(
3933 "int f() {"
3934 " if (1) {"
3935 " int i = 9;"
3936 " }"
3937 " int j = 10;"
3938 " {"
3939 " float k = 9.0;"
3940 " }"
3941 " return 0;"
3942 "}",
3943 // Look for variable declarations within functions whose type is the same
3944 // as the function return type.
3945 functionDecl(
3946 returns(qualType().bind("type")),
3947 forEachDescendant(varDecl(hasType(qualType(equalsBoundNode("type"))))
3948 .bind("decl"))),
3949 // Only i and j should match, not k.
3950 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("decl", 2)));
3951}
3952
3953TEST_P(ASTMatchersTest, EqualsBoundNodeMatcher_FiltersMatchedCombinations) {
3954 EXPECT_TRUE(matchAndVerifyResultTrue(
3955 "void f() {"
3956 " int x;"
3957 " double d;"
3958 " x = d + x - d + x;"
3959 "}",
3960 functionDecl(
3961 hasName("f"), forEachDescendant(varDecl().bind("d")),
3962 forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))),
3963 std::make_unique<VerifyIdIsBoundTo<VarDecl>>("d", 5)));
3964}
3965
3966TEST_P(ASTMatchersTest,
3967 EqualsBoundNodeMatcher_UnlessDescendantsOfAncestorsMatch) {
3968 EXPECT_TRUE(matchAndVerifyResultTrue(
3969 "struct StringRef { int size() const; const char* data() const; };"
3970 "void f(StringRef v) {"
3971 " v.data();"
3972 "}",
3973 cxxMemberCallExpr(
3974 callee(cxxMethodDecl(hasName("data"))),
3975 on(declRefExpr(to(
3976 varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
3977 unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
3978 callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
3979 on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
3980 .bind("data"),
3981 std::make_unique<VerifyIdIsBoundTo<Expr>>("data", 1)));
3982
3983 EXPECT_FALSE(matches(
3984 "struct StringRef { int size() const; const char* data() const; };"
3985 "void f(StringRef v) {"
3986 " v.data();"
3987 " v.size();"
3988 "}",
3989 cxxMemberCallExpr(
3990 callee(cxxMethodDecl(hasName("data"))),
3991 on(declRefExpr(to(
3992 varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
3993 unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
3994 callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
3995 on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
3996 .bind("data")));
3997}
3998
3999TEST_P(ASTMatchersTest, NullPointerConstant) {
4000 EXPECT_TRUE(matches("#define NULL ((void *)0)\n"
4001 "void *v1 = NULL;",
4002 expr(nullPointerConstant())));
4003 EXPECT_TRUE(matches("char *cp = (char *)0;", expr(nullPointerConstant())));
4004 EXPECT_TRUE(matches("int *ip = 0;", expr(nullPointerConstant())));
4005 EXPECT_FALSE(matches("int i = 0;", expr(nullPointerConstant())));
4006}
4007
4008TEST_P(ASTMatchersTest, NullPointerConstant_GNUNull) {
4009 if (!GetParam().isCXX()) {
4010 return;
4011 }
4012
4013 EXPECT_TRUE(matches("void *p = __null;", expr(nullPointerConstant())));
4014}
4015
4016TEST_P(ASTMatchersTest, NullPointerConstant_GNUNullInTemplate) {
4017 if (!GetParam().isCXX() || GetParam().hasDelayedTemplateParsing()) {
4018 // FIXME: Fix this test to work with delayed template parsing.
4019 return;
4020 }
4021
4022 const char kTest[] = R"(
4023 template <typename T>
4024 struct MyTemplate {
4025 MyTemplate() : field_(__null) {}
4026 T* field_;
4027 };
4028 )";
4029 EXPECT_TRUE(matches(kTest, expr(nullPointerConstant())));
4030}
4031
4032TEST_P(ASTMatchersTest, NullPointerConstant_CXX11Nullptr) {
4033 if (!GetParam().isCXX11OrLater()) {
4034 return;
4035 }
4036
4037 EXPECT_TRUE(matches("void *p = nullptr;", expr(nullPointerConstant())));
4038}
4039
4040TEST_P(ASTMatchersTest, HasExternalFormalLinkage) {
4041 EXPECT_TRUE(matches("int a = 0;",
4042 namedDecl(hasName("a"), hasExternalFormalLinkage())));
4043 EXPECT_TRUE(notMatches("static int a = 0;",
4044 namedDecl(hasName("a"), hasExternalFormalLinkage())));
4045 EXPECT_TRUE(notMatches("static void f(void) { int a = 0; }",
4046 namedDecl(hasName("a"), hasExternalFormalLinkage())));
4047 EXPECT_TRUE(notMatches("void f(void) { int a = 0; }",
4048 namedDecl(hasName("a"), hasExternalFormalLinkage())));
4049}
4050
4051TEST_P(ASTMatchersTest, HasExternalFormalLinkage_CXX) {
4052 if (!GetParam().isCXX()) {
4053 return;
4054 }
4055
4056 EXPECT_TRUE(notMatches("namespace { int a = 0; }",
4057 namedDecl(hasName("a"), hasExternalFormalLinkage())));
4058}
4059
4060TEST_P(ASTMatchersTest, HasDefaultArgument) {
4061 if (!GetParam().isCXX()) {
4062 return;
4063 }
4064
4065 EXPECT_TRUE(
4066 matches("void x(int val = 0) {}", parmVarDecl(hasDefaultArgument())));
4067 EXPECT_TRUE(
4068 notMatches("void x(int val) {}", parmVarDecl(hasDefaultArgument())));
4069}
4070
4071TEST_P(ASTMatchersTest, IsAtPosition) {
4072 EXPECT_TRUE(matches("void x(int a, int b) {}", parmVarDecl(isAtPosition(1))));
4073 EXPECT_TRUE(matches("void x(int a, int b) {}", parmVarDecl(isAtPosition(0))));
4074 EXPECT_TRUE(matches("void x(int a, int b) {}", parmVarDecl(isAtPosition(1))));
4075 EXPECT_TRUE(notMatches("void x(int val) {}", parmVarDecl(isAtPosition(1))));
4076}
4077
4078TEST_P(ASTMatchersTest, IsAtPosition_FunctionDecl) {
4079 EXPECT_TRUE(matches("void x(int a);", parmVarDecl(isAtPosition(0))));
4080 EXPECT_TRUE(matches("void x(int a, int b);", parmVarDecl(isAtPosition(0))));
4081 EXPECT_TRUE(matches("void x(int a, int b);", parmVarDecl(isAtPosition(1))));
4082 EXPECT_TRUE(notMatches("void x(int val);", parmVarDecl(isAtPosition(1))));
4083}
4084
4085TEST_P(ASTMatchersTest, IsAtPosition_Lambda) {
4086 if (!GetParam().isCXX11OrLater()) {
4087 return;
4088 }
4089
4090 EXPECT_TRUE(
4091 matches("void x() { [](int a) {}; }", parmVarDecl(isAtPosition(0))));
4092 EXPECT_TRUE(matches("void x() { [](int a, int b) {}; }",
4093 parmVarDecl(isAtPosition(0))));
4094 EXPECT_TRUE(matches("void x() { [](int a, int b) {}; }",
4095 parmVarDecl(isAtPosition(1))));
4096 EXPECT_TRUE(
4097 notMatches("void x() { [](int val) {}; }", parmVarDecl(isAtPosition(1))));
4098}
4099
4100TEST_P(ASTMatchersTest, IsAtPosition_BlockDecl) {
4101 EXPECT_TRUE(matchesObjC(
4102 "void func() { void (^my_block)(int arg) = ^void(int arg) {}; } ",
4103 parmVarDecl(isAtPosition(0))));
4104
4105 EXPECT_TRUE(matchesObjC("void func() { void (^my_block)(int x, int y) = "
4106 "^void(int x, int y) {}; } ",
4107 parmVarDecl(isAtPosition(1))));
4108
4109 EXPECT_TRUE(notMatchesObjC(
4110 "void func() { void (^my_block)(int arg) = ^void(int arg) {}; } ",
4111 parmVarDecl(isAtPosition(1))));
4112}
4113
4114TEST_P(ASTMatchersTest, IsArray) {
4115 if (!GetParam().isCXX()) {
4116 return;
4117 }
4118
4119 EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];",
4120 cxxNewExpr(isArray())));
4121}
4122
4123TEST_P(ASTMatchersTest, HasArraySize) {
4124 if (!GetParam().isCXX()) {
4125 return;
4126 }
4127
4128 EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];",
4129 cxxNewExpr(hasArraySize(
4130 ignoringParenImpCasts(integerLiteral(equals(10)))))));
4131}
4132
4133TEST_P(ASTMatchersTest, HasDefinition_MatchesStructDefinition) {
4134 if (!GetParam().isCXX()) {
4135 return;
4136 }
4137
4138 EXPECT_TRUE(matches("struct x {};", cxxRecordDecl(hasDefinition())));
4139 EXPECT_TRUE(notMatches("struct x;", cxxRecordDecl(hasDefinition())));
4140}
4141
4142TEST_P(ASTMatchersTest, HasDefinition_MatchesClassDefinition) {
4143 if (!GetParam().isCXX()) {
4144 return;
4145 }
4146
4147 EXPECT_TRUE(matches("class x {};", cxxRecordDecl(hasDefinition())));
4148 EXPECT_TRUE(notMatches("class x;", cxxRecordDecl(hasDefinition())));
4149}
4150
4151TEST_P(ASTMatchersTest, HasDefinition_MatchesUnionDefinition) {
4152 if (!GetParam().isCXX()) {
4153 return;
4154 }
4155
4156 EXPECT_TRUE(matches("union x {};", cxxRecordDecl(hasDefinition())));
4157 EXPECT_TRUE(notMatches("union x;", cxxRecordDecl(hasDefinition())));
4158}
4159
4160TEST_P(ASTMatchersTest, IsScoped_MatchesScopedEnum) {
4161 if (!GetParam().isCXX11OrLater()) {
4162 return;
4163 }
4164 EXPECT_TRUE(matches("enum class X {};", enumDecl(isScoped())));
4165}
4166
4167TEST_P(ASTMatchersTest, IsScoped_NotMatchesRegularEnum) {
4168 EXPECT_TRUE(notMatches("enum E { E1 };", enumDecl(isScoped())));
4169}
4170
4171TEST_P(ASTMatchersTest, IsStruct) {
4172 EXPECT_TRUE(matches("struct S {};", tagDecl(isStruct())));
4173}
4174
4175TEST_P(ASTMatchersTest, IsUnion) {
4176 EXPECT_TRUE(matches("union U {};", tagDecl(isUnion())));
4177}
4178
4179TEST_P(ASTMatchersTest, IsEnum) {
4180 EXPECT_TRUE(matches("enum E { E1 };", tagDecl(isEnum())));
4181}
4182
4183TEST_P(ASTMatchersTest, IsClass) {
4184 if (!GetParam().isCXX()) {
4185 return;
4186 }
4187
4188 EXPECT_TRUE(matches("class C {};", tagDecl(isClass())));
4189}
4190
4191TEST_P(ASTMatchersTest, HasTrailingReturn_MatchesTrailingReturn) {
4192 if (!GetParam().isCXX11OrLater()) {
4193 return;
4194 }
4195
4196 EXPECT_TRUE(matches("auto Y() -> int { return 0; }",
4197 functionDecl(hasTrailingReturn())));
4198 EXPECT_TRUE(matches("auto X() -> int;", functionDecl(hasTrailingReturn())));
4199 EXPECT_TRUE(
4200 notMatches("int X() { return 0; }", functionDecl(hasTrailingReturn())));
4201 EXPECT_TRUE(notMatches("int X();", functionDecl(hasTrailingReturn())));
4202 EXPECT_TRUE(notMatches("void X();", functionDecl(hasTrailingReturn())));
4203}
4204
4205TEST_P(ASTMatchersTest, HasTrailingReturn_MatchesLambdaTrailingReturn) {
4206 if (!GetParam().isCXX11OrLater()) {
4207 return;
4208 }
4209
4210 EXPECT_TRUE(matches(
4211 "auto lambda2 = [](double x, double y) -> double {return x + y;};",
4212 functionDecl(hasTrailingReturn())));
4213 EXPECT_TRUE(
4214 notMatches("auto lambda2 = [](double x, double y) {return x + y;};",
4215 functionDecl(hasTrailingReturn())));
4216}
4217
4218TEST_P(ASTMatchersTest, IsAssignmentOperator) {
4219 if (!GetParam().isCXX()) {
4220 return;
4221 }
4222
4223 StatementMatcher BinAsgmtOperator = binaryOperator(isAssignmentOperator());
4224 StatementMatcher CXXAsgmtOperator =
4225 cxxOperatorCallExpr(isAssignmentOperator());
4226
4227 EXPECT_TRUE(matches("void x() { int a; a += 1; }", BinAsgmtOperator));
4228 EXPECT_TRUE(matches("void x() { int a; a = 2; }", BinAsgmtOperator));
4229 EXPECT_TRUE(matches("void x() { int a; a &= 3; }", BinAsgmtOperator));
4230 EXPECT_TRUE(matches("struct S { S& operator=(const S&); };"
4231 "void x() { S s1, s2; s1 = s2; }",
4232 CXXAsgmtOperator));
4233 EXPECT_TRUE(
4234 notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
4235}
4236
4237TEST_P(ASTMatchersTest, IsComparisonOperator) {
4238 if (!GetParam().isCXX()) {
4239 return;
4240 }
4241
4242 StatementMatcher BinCompOperator = binaryOperator(isComparisonOperator());
4243 StatementMatcher CXXCompOperator =
4244 cxxOperatorCallExpr(isComparisonOperator());
4245
4246 EXPECT_TRUE(matches("void x() { int a; a == 1; }", BinCompOperator));
4247 EXPECT_TRUE(matches("void x() { int a; a > 2; }", BinCompOperator));
4248 EXPECT_TRUE(matches("struct S { bool operator==(const S&); };"
4249 "void x() { S s1, s2; bool b1 = s1 == s2; }",
4250 CXXCompOperator));
4251 EXPECT_TRUE(
4252 notMatches("void x() { int a; if(a = 0) return; }", BinCompOperator));
4253}
4254
4255TEST_P(ASTMatchersTest, isRightFold) {
4256 if (!GetParam().isCXX17OrLater()) {
4257 return;
4258 }
4259
4260 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4261 "return (0 + ... + args); }",
4262 cxxFoldExpr(isRightFold())));
4263 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4264 "return (args + ... + 0); }",
4265 cxxFoldExpr(isRightFold())));
4266 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4267 "return (... + args); };",
4268 cxxFoldExpr(isRightFold())));
4269 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4270 "return (args + ...); };",
4271 cxxFoldExpr(isRightFold())));
4272}
4273
4274TEST_P(ASTMatchersTest, isLeftFold) {
4275 if (!GetParam().isCXX17OrLater()) {
4276 return;
4277 }
4278
4279 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4280 "return (0 + ... + args); }",
4281 cxxFoldExpr(isLeftFold())));
4282 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4283 "return (args + ... + 0); }",
4284 cxxFoldExpr(isLeftFold())));
4285 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4286 "return (... + args); };",
4287 cxxFoldExpr(isLeftFold())));
4288 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4289 "return (args + ...); };",
4290 cxxFoldExpr(isLeftFold())));
4291}
4292
4293TEST_P(ASTMatchersTest, isUnaryFold) {
4294 if (!GetParam().isCXX17OrLater()) {
4295 return;
4296 }
4297
4298 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4299 "return (0 + ... + args); }",
4300 cxxFoldExpr(isUnaryFold())));
4301 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4302 "return (args + ... + 0); }",
4303 cxxFoldExpr(isUnaryFold())));
4304 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4305 "return (... + args); };",
4306 cxxFoldExpr(isUnaryFold())));
4307 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4308 "return (args + ...); };",
4309 cxxFoldExpr(isUnaryFold())));
4310}
4311
4312TEST_P(ASTMatchersTest, isBinaryFold) {
4313 if (!GetParam().isCXX17OrLater()) {
4314 return;
4315 }
4316
4317 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4318 "return (0 + ... + args); }",
4319 cxxFoldExpr(isBinaryFold())));
4320 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4321 "return (args + ... + 0); }",
4322 cxxFoldExpr(isBinaryFold())));
4323 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4324 "return (... + args); };",
4325 cxxFoldExpr(isBinaryFold())));
4326 EXPECT_FALSE(matches("template <typename... Args> auto sum(Args... args) { "
4327 "return (args + ...); };",
4328 cxxFoldExpr(isBinaryFold())));
4329}
4330
4331TEST_P(ASTMatchersTest, hasOperator) {
4332 if (!GetParam().isCXX17OrLater()) {
4333 return;
4334 }
4335
4336 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4337 "return (0 + ... + args); }",
4338 cxxFoldExpr(hasOperatorName("+"))));
4339 EXPECT_TRUE(matches("template <typename... Args> auto sum(Args... args) { "
4340 "return (... + args); };",
4341 cxxFoldExpr(hasOperatorName("+"))));
4342
4343 EXPECT_FALSE(
4344 matches("template <typename... Args> auto multiply(Args... args) { "
4345 "return (0 * ... * args); }",
4346 cxxFoldExpr(hasOperatorName("+"))));
4347 EXPECT_FALSE(
4348 matches("template <typename... Args> auto multiply(Args... args) { "
4349 "return (... * args); };",
4350 cxxFoldExpr(hasOperatorName("+"))));
4351}
4352
4353TEST_P(ASTMatchersTest, IsMain) {
4354 EXPECT_TRUE(matches("int main() {}", functionDecl(isMain())));
4355
4356 EXPECT_TRUE(notMatches("int main2() { return 0; }", functionDecl(isMain())));
4357}
4358
4359TEST_P(ASTMatchersTest, OMPExecutableDirective_IsStandaloneDirective) {
4360 auto Matcher = ompExecutableDirective(isStandaloneDirective());
4361
4362 StringRef Source0 = R"(
4363void x() {
4364#pragma omp parallel
4365;
4366})";
4367 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4368
4369 StringRef Source1 = R"(
4370void x() {
4371#pragma omp taskyield
4372})";
4373 EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher));
4374}
4375
4376TEST_P(ASTMatchersTest, OMPExecutableDirective_HasStructuredBlock) {
4377 StringRef Source0 = R"(
4378void x() {
4379#pragma omp parallel
4380;
4381})";
4382 EXPECT_TRUE(matchesWithOpenMP(
4383 Source0, ompExecutableDirective(hasStructuredBlock(nullStmt()))));
4384
4385 StringRef Source1 = R"(
4386void x() {
4387#pragma omp parallel
4388{;}
4389})";
4390 EXPECT_TRUE(notMatchesWithOpenMP(
4391 Source1, ompExecutableDirective(hasStructuredBlock(nullStmt()))));
4392 EXPECT_TRUE(matchesWithOpenMP(
4393 Source1, ompExecutableDirective(hasStructuredBlock(compoundStmt()))));
4394
4395 StringRef Source2 = R"(
4396void x() {
4397#pragma omp taskyield
4398{;}
4399})";
4400 EXPECT_TRUE(notMatchesWithOpenMP(
4401 Source2, ompExecutableDirective(hasStructuredBlock(anything()))));
4402}
4403
4404TEST_P(ASTMatchersTest, OMPExecutableDirective_HasClause) {
4405 auto Matcher = ompExecutableDirective(hasAnyClause(InnerMatcher: anything()));
4406
4407 StringRef Source0 = R"(
4408void x() {
4409;
4410})";
4411 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4412
4413 StringRef Source1 = R"(
4414void x() {
4415#pragma omp parallel
4416;
4417})";
4418 EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));
4419
4420 StringRef Source2 = R"(
4421void x() {
4422#pragma omp parallel default(none)
4423;
4424})";
4425 EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher));
4426
4427 StringRef Source3 = R"(
4428void x() {
4429#pragma omp parallel default(shared)
4430;
4431})";
4432 EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher));
4433
4434 StringRef Source4 = R"(
4435void x() {
4436#pragma omp parallel default(firstprivate)
4437;
4438})";
4439 EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
4440
4441 StringRef Source5 = R"(
4442void x(int x) {
4443#pragma omp parallel num_threads(x)
4444;
4445})";
4446 EXPECT_TRUE(matchesWithOpenMP(Source5, Matcher));
4447}
4448
4449TEST_P(ASTMatchersTest, OMPDefaultClause_IsNoneKind) {
4450 auto Matcher =
4451 ompExecutableDirective(hasAnyClause(InnerMatcher: ompDefaultClause(isNoneKind())));
4452
4453 StringRef Source0 = R"(
4454void x() {
4455;
4456})";
4457 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4458
4459 StringRef Source1 = R"(
4460void x() {
4461#pragma omp parallel
4462;
4463})";
4464 EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));
4465
4466 StringRef Source2 = R"(
4467void x() {
4468#pragma omp parallel default(none)
4469;
4470})";
4471 EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher));
4472
4473 StringRef Source3 = R"(
4474void x() {
4475#pragma omp parallel default(shared)
4476;
4477})";
4478 EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher));
4479
4480 StringRef Source4 = R"(
4481void x(int x) {
4482#pragma omp parallel default(firstprivate)
4483;
4484})";
4485 EXPECT_TRUE(notMatchesWithOpenMP51(Source4, Matcher));
4486
4487 StringRef Source5 = R"(
4488void x(int x) {
4489#pragma omp parallel default(private)
4490;
4491})";
4492 EXPECT_TRUE(notMatchesWithOpenMP51(Source5, Matcher));
4493
4494 const std::string Source6 = R"(
4495void x(int x) {
4496#pragma omp parallel num_threads(x)
4497;
4498})";
4499 EXPECT_TRUE(notMatchesWithOpenMP(Source6, Matcher));
4500}
4501
4502TEST_P(ASTMatchersTest, OMPDefaultClause_IsSharedKind) {
4503 auto Matcher =
4504 ompExecutableDirective(hasAnyClause(InnerMatcher: ompDefaultClause(isSharedKind())));
4505
4506 StringRef Source0 = R"(
4507void x() {
4508;
4509})";
4510 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4511
4512 StringRef Source1 = R"(
4513void x() {
4514#pragma omp parallel
4515;
4516})";
4517 EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));
4518
4519 StringRef Source2 = R"(
4520void x() {
4521#pragma omp parallel default(shared)
4522;
4523})";
4524 EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher));
4525
4526 StringRef Source3 = R"(
4527void x() {
4528#pragma omp parallel default(none)
4529;
4530})";
4531 EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher));
4532
4533 StringRef Source4 = R"(
4534void x(int x) {
4535#pragma omp parallel default(firstprivate)
4536;
4537})";
4538 EXPECT_TRUE(notMatchesWithOpenMP51(Source4, Matcher));
4539
4540 StringRef Source5 = R"(
4541void x(int x) {
4542#pragma omp parallel default(private)
4543;
4544})";
4545 EXPECT_TRUE(notMatchesWithOpenMP51(Source5, Matcher));
4546
4547 const std::string Source6 = R"(
4548void x(int x) {
4549#pragma omp parallel num_threads(x)
4550;
4551})";
4552 EXPECT_TRUE(notMatchesWithOpenMP(Source6, Matcher));
4553}
4554
4555TEST(OMPDefaultClause, isFirstPrivateKind) {
4556 auto Matcher = ompExecutableDirective(
4557 hasAnyClause(InnerMatcher: ompDefaultClause(isFirstPrivateKind())));
4558
4559 const std::string Source0 = R"(
4560void x() {
4561;
4562})";
4563 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4564
4565 const std::string Source1 = R"(
4566void x() {
4567#pragma omp parallel
4568;
4569})";
4570 EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));
4571
4572 const std::string Source2 = R"(
4573void x() {
4574#pragma omp parallel default(shared)
4575;
4576})";
4577 EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher));
4578
4579 const std::string Source3 = R"(
4580void x() {
4581#pragma omp parallel default(none)
4582;
4583})";
4584 EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher));
4585
4586 const std::string Source4 = R"(
4587void x(int x) {
4588#pragma omp parallel default(firstprivate)
4589;
4590})";
4591 EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
4592
4593 const std::string Source5 = R"(
4594void x(int x) {
4595#pragma omp parallel default(private)
4596;
4597})";
4598 EXPECT_TRUE(notMatchesWithOpenMP51(Source5, Matcher));
4599
4600 const std::string Source6 = R"(
4601void x(int x) {
4602#pragma omp parallel num_threads(x)
4603;
4604})";
4605 EXPECT_TRUE(notMatchesWithOpenMP(Source6, Matcher));
4606}
4607
4608TEST(OMPDefaultClause, istPrivateKind) {
4609 auto Matcher =
4610 ompExecutableDirective(hasAnyClause(InnerMatcher: ompDefaultClause(isPrivateKind())));
4611
4612 const std::string Source0 = R"(
4613void x() {
4614;
4615})";
4616 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4617
4618 const std::string Source1 = R"(
4619void x() {
4620#pragma omp parallel
4621;
4622})";
4623 EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));
4624
4625 const std::string Source2 = R"(
4626void x() {
4627#pragma omp parallel default(shared)
4628;
4629})";
4630 EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher));
4631
4632 const std::string Source3 = R"(
4633void x() {
4634#pragma omp parallel default(none)
4635;
4636})";
4637 EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher));
4638
4639 const std::string Source4 = R"(
4640void x(int x) {
4641#pragma omp parallel default(firstprivate)
4642;
4643})";
4644 EXPECT_TRUE(notMatchesWithOpenMP51(Source4, Matcher));
4645
4646 const std::string Source5 = R"(
4647void x(int x) {
4648#pragma omp parallel default(private)
4649;
4650})";
4651 EXPECT_TRUE(matchesWithOpenMP51(Source5, Matcher));
4652
4653 const std::string Source6 = R"(
4654void x(int x) {
4655#pragma omp parallel num_threads(x)
4656;
4657})";
4658 EXPECT_TRUE(notMatchesWithOpenMP(Source6, Matcher));
4659}
4660
4661TEST_P(ASTMatchersTest, OMPExecutableDirective_IsAllowedToContainClauseKind) {
4662 auto Matcher = ompExecutableDirective(
4663 isAllowedToContainClauseKind(llvm::omp::OMPC_default));
4664
4665 StringRef Source0 = R"(
4666void x() {
4667;
4668})";
4669 EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
4670
4671 StringRef Source1 = R"(
4672void x() {
4673#pragma omp parallel
4674;
4675})";
4676 EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher));
4677
4678 StringRef Source2 = R"(
4679void x() {
4680#pragma omp parallel default(none)
4681;
4682})";
4683 EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher));
4684
4685 StringRef Source3 = R"(
4686void x() {
4687#pragma omp parallel default(shared)
4688;
4689})";
4690 EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher));
4691
4692 StringRef Source4 = R"(
4693void x() {
4694#pragma omp parallel default(firstprivate)
4695;
4696})";
4697 EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
4698
4699 StringRef Source5 = R"(
4700void x() {
4701#pragma omp parallel default(private)
4702;
4703})";
4704 EXPECT_TRUE(matchesWithOpenMP51(Source5, Matcher));
4705
4706 StringRef Source6 = R"(
4707void x(int x) {
4708#pragma omp parallel num_threads(x)
4709;
4710})";
4711 EXPECT_TRUE(matchesWithOpenMP(Source6, Matcher));
4712
4713 StringRef Source7 = R"(
4714void x() {
4715#pragma omp taskyield
4716})";
4717 EXPECT_TRUE(notMatchesWithOpenMP(Source7, Matcher));
4718
4719 StringRef Source8 = R"(
4720void x() {
4721#pragma omp task
4722;
4723})";
4724 EXPECT_TRUE(matchesWithOpenMP(Source8, Matcher));
4725}
4726
4727TEST_P(ASTMatchersTest, HasAnyBase_DirectBase) {
4728 if (!GetParam().isCXX()) {
4729 return;
4730 }
4731 EXPECT_TRUE(matches(
4732 "struct Base {};"
4733 "struct ExpectedMatch : Base {};",
4734 cxxRecordDecl(hasName("ExpectedMatch"),
4735 hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))));
4736}
4737
4738TEST_P(ASTMatchersTest, HasAnyBase_IndirectBase) {
4739 if (!GetParam().isCXX()) {
4740 return;
4741 }
4742 EXPECT_TRUE(matches(
4743 "struct Base {};"
4744 "struct Intermediate : Base {};"
4745 "struct ExpectedMatch : Intermediate {};",
4746 cxxRecordDecl(hasName("ExpectedMatch"),
4747 hasAnyBase(hasType(cxxRecordDecl(hasName("Base")))))));
4748}
4749
4750TEST_P(ASTMatchersTest, HasAnyBase_NoBase) {
4751 if (!GetParam().isCXX()) {
4752 return;
4753 }
4754 EXPECT_TRUE(notMatches("struct Foo {};"
4755 "struct Bar {};",
4756 cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl())))));
4757}
4758
4759TEST_P(ASTMatchersTest, HasAnyBase_IsPublic_Public) {
4760 if (!GetParam().isCXX()) {
4761 return;
4762 }
4763 EXPECT_TRUE(matches("class Base {};"
4764 "class Derived : public Base {};",
4765 cxxRecordDecl(hasAnyBase(isPublic()))));
4766}
4767
4768TEST_P(ASTMatchersTest, HasAnyBase_IsPublic_DefaultAccessSpecifierPublic) {
4769 if (!GetParam().isCXX()) {
4770 return;
4771 }
4772 EXPECT_TRUE(matches("class Base {};"
4773 "struct Derived : Base {};",
4774 cxxRecordDecl(hasAnyBase(isPublic()))));
4775}
4776
4777TEST_P(ASTMatchersTest, HasAnyBase_IsPublic_Private) {
4778 if (!GetParam().isCXX()) {
4779 return;
4780 }
4781 EXPECT_TRUE(notMatches("class Base {};"
4782 "class Derived : private Base {};",
4783 cxxRecordDecl(hasAnyBase(isPublic()))));
4784}
4785
4786TEST_P(ASTMatchersTest, HasAnyBase_IsPublic_DefaultAccessSpecifierPrivate) {
4787 if (!GetParam().isCXX()) {
4788 return;
4789 }
4790 EXPECT_TRUE(notMatches("class Base {};"
4791 "class Derived : Base {};",
4792 cxxRecordDecl(hasAnyBase(isPublic()))));
4793}
4794
4795TEST_P(ASTMatchersTest, HasAnyBase_IsPublic_Protected) {
4796 if (!GetParam().isCXX()) {
4797 return;
4798 }
4799 EXPECT_TRUE(notMatches("class Base {};"
4800 "class Derived : protected Base {};",
4801 cxxRecordDecl(hasAnyBase(isPublic()))));
4802}
4803
4804TEST_P(ASTMatchersTest, HasAnyBase_IsPrivate_Private) {
4805 if (!GetParam().isCXX()) {
4806 return;
4807 }
4808 EXPECT_TRUE(matches("class Base {};"
4809 "class Derived : private Base {};",
4810 cxxRecordDecl(hasAnyBase(isPrivate()))));
4811}
4812
4813TEST_P(ASTMatchersTest, HasAnyBase_IsPrivate_DefaultAccessSpecifierPrivate) {
4814 if (!GetParam().isCXX()) {
4815 return;
4816 }
4817 EXPECT_TRUE(matches("struct Base {};"
4818 "class Derived : Base {};",
4819 cxxRecordDecl(hasAnyBase(isPrivate()))));
4820}
4821
4822TEST_P(ASTMatchersTest, HasAnyBase_IsPrivate_Public) {
4823 if (!GetParam().isCXX()) {
4824 return;
4825 }
4826 EXPECT_TRUE(notMatches("class Base {};"
4827 "class Derived : public Base {};",
4828 cxxRecordDecl(hasAnyBase(isPrivate()))));
4829}
4830
4831TEST_P(ASTMatchersTest, HasAnyBase_IsPrivate_DefaultAccessSpecifierPublic) {
4832 if (!GetParam().isCXX()) {
4833 return;
4834 }
4835 EXPECT_TRUE(notMatches("class Base {};"
4836 "struct Derived : Base {};",
4837 cxxRecordDecl(hasAnyBase(isPrivate()))));
4838}
4839
4840TEST_P(ASTMatchersTest, HasAnyBase_IsPrivate_Protected) {
4841 if (!GetParam().isCXX()) {
4842 return;
4843 }
4844 EXPECT_TRUE(notMatches("class Base {};"
4845 "class Derived : protected Base {};",
4846 cxxRecordDecl(hasAnyBase(isPrivate()))));
4847}
4848
4849TEST_P(ASTMatchersTest, HasAnyBase_IsProtected_Protected) {
4850 if (!GetParam().isCXX()) {
4851 return;
4852 }
4853 EXPECT_TRUE(matches("class Base {};"
4854 "class Derived : protected Base {};",
4855 cxxRecordDecl(hasAnyBase(isProtected()))));
4856}
4857
4858TEST_P(ASTMatchersTest, HasAnyBase_IsProtected_Public) {
4859 if (!GetParam().isCXX()) {
4860 return;
4861 }
4862 EXPECT_TRUE(notMatches("class Base {};"
4863 "class Derived : public Base {};",
4864 cxxRecordDecl(hasAnyBase(isProtected()))));
4865}
4866
4867TEST_P(ASTMatchersTest, HasAnyBase_IsProtected_Private) {
4868 if (!GetParam().isCXX()) {
4869 return;
4870 }
4871 EXPECT_TRUE(notMatches("class Base {};"
4872 "class Derived : private Base {};",
4873 cxxRecordDecl(hasAnyBase(isProtected()))));
4874}
4875
4876TEST_P(ASTMatchersTest, HasAnyBase_IsVirtual_Directly) {
4877 if (!GetParam().isCXX()) {
4878 return;
4879 }
4880 EXPECT_TRUE(matches("class Base {};"
4881 "class Derived : virtual Base {};",
4882 cxxRecordDecl(hasAnyBase(isVirtual()))));
4883}
4884
4885TEST_P(ASTMatchersTest, HasAnyBase_IsVirtual_Indirectly) {
4886 if (!GetParam().isCXX()) {
4887 return;
4888 }
4889 EXPECT_TRUE(
4890 matches("class Base {};"
4891 "class Intermediate : virtual Base {};"
4892 "class Derived : Intermediate {};",
4893 cxxRecordDecl(hasName("Derived"), hasAnyBase(isVirtual()))));
4894}
4895
4896TEST_P(ASTMatchersTest, HasAnyBase_IsVirtual_NoVirtualBase) {
4897 if (!GetParam().isCXX()) {
4898 return;
4899 }
4900 EXPECT_TRUE(notMatches("class Base {};"
4901 "class Derived : Base {};",
4902 cxxRecordDecl(hasAnyBase(isVirtual()))));
4903}
4904
4905TEST_P(ASTMatchersTest, HasDirectBase) {
4906 if (!GetParam().isCXX()) {
4907 return;
4908 }
4909
4910 DeclarationMatcher ClassHasAnyDirectBase =
4911 cxxRecordDecl(hasDirectBase(BaseSpecMatcher: cxxBaseSpecifier()));
4912 EXPECT_TRUE(notMatches("class X {};", ClassHasAnyDirectBase));
4913 EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyDirectBase));
4914 EXPECT_TRUE(matches("class X {}; class Y : public virtual X {};",
4915 ClassHasAnyDirectBase));
4916
4917 EXPECT_TRUE(matches(
4918 R"cc(
4919 class Base {};
4920 class Derived : Base{};
4921 )cc",
4922 cxxRecordDecl(hasName("Derived"),
4923 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
4924
4925 StringRef MultiDerived = R"cc(
4926 class Base {};
4927 class Base2 {};
4928 class Derived : Base, Base2{};
4929 )cc";
4930
4931 EXPECT_TRUE(matches(
4932 MultiDerived,
4933 cxxRecordDecl(hasName("Derived"),
4934 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
4935 EXPECT_TRUE(matches(
4936 MultiDerived,
4937 cxxRecordDecl(hasName("Derived"),
4938 hasDirectBase(hasType(cxxRecordDecl(hasName("Base2")))))));
4939
4940 StringRef Indirect = R"cc(
4941 class Base {};
4942 class Intermediate : Base {};
4943 class Derived : Intermediate{};
4944 )cc";
4945
4946 EXPECT_TRUE(
4947 matches(Indirect, cxxRecordDecl(hasName("Derived"),
4948 hasDirectBase(hasType(cxxRecordDecl(
4949 hasName("Intermediate")))))));
4950 EXPECT_TRUE(notMatches(
4951 Indirect,
4952 cxxRecordDecl(hasName("Derived"),
4953 hasDirectBase(hasType(cxxRecordDecl(hasName("Base")))))));
4954}
4955
4956TEST_P(ASTMatchersTest, CapturesThis) {
4957 if (!GetParam().isCXX11OrLater()) {
4958 return;
4959 }
4960 auto matcher = lambdaExpr(hasAnyCapture(InnerMatcher: lambdaCapture(capturesThis())));
4961 EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [this](){ return "
4962 "cc; }; return l(); } };",
4963 matcher));
4964 EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [=](){ return cc; "
4965 "}; return l(); } };",
4966 matcher));
4967 EXPECT_TRUE(matches("class C { int cc; int f() { auto l = [&](){ return cc; "
4968 "}; return l(); } };",
4969 matcher));
4970 EXPECT_FALSE(matches("class C { int cc; int f() { auto l = [cc](){ return "
4971 "cc; }; return l(); } };",
4972 matcher));
4973 EXPECT_FALSE(matches("class C { int this; int f() { auto l = [this](){ "
4974 "return this; }; return l(); } };",
4975 matcher));
4976}
4977
4978TEST_P(ASTMatchersTest, IsImplicit_LambdaCapture) {
4979 if (!GetParam().isCXX11OrLater()) {
4980 return;
4981 }
4982 auto matcher = lambdaExpr(hasAnyCapture(
4983 InnerMatcher: lambdaCapture(isImplicit(), capturesVar(InnerMatcher: varDecl(hasName(Name: "cc"))))));
4984 EXPECT_TRUE(
4985 matches("int main() { int cc; auto f = [&](){ return cc; }; }", matcher));
4986 EXPECT_TRUE(
4987 matches("int main() { int cc; auto f = [=](){ return cc; }; }", matcher));
4988 EXPECT_FALSE(matches("int main() { int cc; auto f = [cc](){ return cc; }; }",
4989 matcher));
4990}
4991
4992} // namespace ast_matchers
4993} // namespace clang
4994

Provided by KDAB

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

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