1 | |
2 | |
3 | |
4 | |
5 | |
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/ADT/Triple.h" |
15 | #include "llvm/Support/Host.h" |
16 | #include "gtest/gtest.h" |
17 | |
18 | namespace clang { |
19 | namespace ast_matchers { |
20 | |
21 | |
22 | TEST(AllOf, AllOverloadsWork) { |
23 | const char Program[] = |
24 | "struct T { };" |
25 | "int f(int, T*, int, int);" |
26 | "void g(int x) { T t; f(x, &t, 3, 4); }"; |
27 | EXPECT_TRUE(matches(Program, |
28 | callExpr(allOf(callee(functionDecl(hasName("f"))), |
29 | hasArgument(0, declRefExpr(to(varDecl()))))))); |
30 | EXPECT_TRUE(matches(Program, |
31 | callExpr(allOf(callee(functionDecl(hasName("f"))), |
32 | hasArgument(0, declRefExpr(to(varDecl()))), |
33 | hasArgument(1, hasType(pointsTo( |
34 | recordDecl(hasName("T"))))))))); |
35 | EXPECT_TRUE(matches(Program, |
36 | callExpr(allOf(callee(functionDecl(hasName("f"))), |
37 | hasArgument(0, declRefExpr(to(varDecl()))), |
38 | hasArgument(1, hasType(pointsTo( |
39 | recordDecl(hasName("T"))))), |
40 | hasArgument(2, integerLiteral(equals(3))))))); |
41 | EXPECT_TRUE(matches(Program, |
42 | callExpr(allOf(callee(functionDecl(hasName("f"))), |
43 | hasArgument(0, declRefExpr(to(varDecl()))), |
44 | hasArgument(1, hasType(pointsTo( |
45 | recordDecl(hasName("T"))))), |
46 | hasArgument(2, integerLiteral(equals(3))), |
47 | hasArgument(3, integerLiteral(equals(4))))))); |
48 | } |
49 | |
50 | TEST(DeclarationMatcher, MatchHas) { |
51 | DeclarationMatcher HasClassX = recordDecl(has(recordDecl(hasName("X")))); |
52 | EXPECT_TRUE(matches("class Y { class X {}; };", HasClassX)); |
53 | EXPECT_TRUE(matches("class X {};", HasClassX)); |
54 | |
55 | DeclarationMatcher YHasClassX = |
56 | recordDecl(hasName("Y"), has(recordDecl(hasName("X")))); |
57 | EXPECT_TRUE(matches("class Y { class X {}; };", YHasClassX)); |
58 | EXPECT_TRUE(notMatches("class X {};", YHasClassX)); |
59 | EXPECT_TRUE( |
60 | notMatches("class Y { class Z { class X {}; }; };", YHasClassX)); |
61 | } |
62 | |
63 | TEST(DeclarationMatcher, MatchHasRecursiveAllOf) { |
64 | DeclarationMatcher Recursive = |
65 | recordDecl( |
66 | has(recordDecl( |
67 | has(recordDecl(hasName("X"))), |
68 | has(recordDecl(hasName("Y"))), |
69 | hasName("Z"))), |
70 | has(recordDecl( |
71 | has(recordDecl(hasName("A"))), |
72 | has(recordDecl(hasName("B"))), |
73 | hasName("C"))), |
74 | hasName("F")); |
75 | |
76 | EXPECT_TRUE(matches( |
77 | "class F {" |
78 | " class Z {" |
79 | " class X {};" |
80 | " class Y {};" |
81 | " };" |
82 | " class C {" |
83 | " class A {};" |
84 | " class B {};" |
85 | " };" |
86 | "};", Recursive)); |
87 | |
88 | EXPECT_TRUE(matches( |
89 | "class F {" |
90 | " class Z {" |
91 | " class A {};" |
92 | " class X {};" |
93 | " class Y {};" |
94 | " };" |
95 | " class C {" |
96 | " class X {};" |
97 | " class A {};" |
98 | " class B {};" |
99 | " };" |
100 | "};", Recursive)); |
101 | |
102 | EXPECT_TRUE(matches( |
103 | "class O1 {" |
104 | " class O2 {" |
105 | " class F {" |
106 | " class Z {" |
107 | " class A {};" |
108 | " class X {};" |
109 | " class Y {};" |
110 | " };" |
111 | " class C {" |
112 | " class X {};" |
113 | " class A {};" |
114 | " class B {};" |
115 | " };" |
116 | " };" |
117 | " };" |
118 | "};", Recursive)); |
119 | } |
120 | |
121 | TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) { |
122 | DeclarationMatcher Recursive = |
123 | recordDecl( |
124 | anyOf( |
125 | has(recordDecl( |
126 | anyOf( |
127 | has(recordDecl( |
128 | hasName("X"))), |
129 | has(recordDecl( |
130 | hasName("Y"))), |
131 | hasName("Z")))), |
132 | has(recordDecl( |
133 | anyOf( |
134 | hasName("C"), |
135 | has(recordDecl( |
136 | hasName("A"))), |
137 | has(recordDecl( |
138 | hasName("B")))))), |
139 | hasName("F"))); |
140 | |
141 | EXPECT_TRUE(matches("class F {};", Recursive)); |
142 | EXPECT_TRUE(matches("class Z {};", Recursive)); |
143 | EXPECT_TRUE(matches("class C {};", Recursive)); |
144 | EXPECT_TRUE(matches("class M { class N { class X {}; }; };", Recursive)); |
145 | EXPECT_TRUE(matches("class M { class N { class B {}; }; };", Recursive)); |
146 | EXPECT_TRUE( |
147 | matches("class O1 { class O2 {" |
148 | " class M { class N { class B {}; }; }; " |
149 | "}; };", Recursive)); |
150 | } |
151 | |
152 | TEST(DeclarationMatcher, MatchNot) { |
153 | DeclarationMatcher NotClassX = |
154 | cxxRecordDecl( |
155 | isDerivedFrom("Y"), |
156 | unless(hasName("X"))); |
157 | EXPECT_TRUE(notMatches("", NotClassX)); |
158 | EXPECT_TRUE(notMatches("class Y {};", NotClassX)); |
159 | EXPECT_TRUE(matches("class Y {}; class Z : public Y {};", NotClassX)); |
160 | EXPECT_TRUE(notMatches("class Y {}; class X : public Y {};", NotClassX)); |
161 | EXPECT_TRUE( |
162 | notMatches("class Y {}; class Z {}; class X : public Y {};", |
163 | NotClassX)); |
164 | |
165 | DeclarationMatcher ClassXHasNotClassY = |
166 | recordDecl( |
167 | hasName("X"), |
168 | has(recordDecl(hasName("Z"))), |
169 | unless( |
170 | has(recordDecl(hasName("Y"))))); |
171 | EXPECT_TRUE(matches("class X { class Z {}; };", ClassXHasNotClassY)); |
172 | EXPECT_TRUE(notMatches("class X { class Y {}; class Z {}; };", |
173 | ClassXHasNotClassY)); |
174 | |
175 | DeclarationMatcher NamedNotRecord = |
176 | namedDecl(hasName("Foo"), unless(recordDecl())); |
177 | EXPECT_TRUE(matches("void Foo(){}", NamedNotRecord)); |
178 | EXPECT_TRUE(notMatches("struct Foo {};", NamedNotRecord)); |
179 | } |
180 | |
181 | TEST(CastExpression, HasCastKind) { |
182 | EXPECT_TRUE(matches("char *p = 0;", |
183 | castExpr(hasCastKind(CK_NullToPointer)))); |
184 | EXPECT_TRUE(notMatches("char *p = 0;", |
185 | castExpr(hasCastKind(CK_DerivedToBase)))); |
186 | EXPECT_TRUE(matches("char *p = 0;", |
187 | implicitCastExpr(hasCastKind(CK_NullToPointer)))); |
188 | } |
189 | |
190 | TEST(DeclarationMatcher, HasDescendant) { |
191 | DeclarationMatcher ZDescendantClassX = |
192 | recordDecl( |
193 | hasDescendant(recordDecl(hasName("X"))), |
194 | hasName("Z")); |
195 | EXPECT_TRUE(matches("class Z { class X {}; };", ZDescendantClassX)); |
196 | EXPECT_TRUE( |
197 | matches("class Z { class Y { class X {}; }; };", ZDescendantClassX)); |
198 | EXPECT_TRUE( |
199 | matches("class Z { class A { class Y { class X {}; }; }; };", |
200 | ZDescendantClassX)); |
201 | EXPECT_TRUE( |
202 | matches("class Z { class A { class B { class Y { class X {}; }; }; }; };", |
203 | ZDescendantClassX)); |
204 | EXPECT_TRUE(notMatches("class Z {};", ZDescendantClassX)); |
205 | |
206 | DeclarationMatcher ZDescendantClassXHasClassY = |
207 | recordDecl( |
208 | hasDescendant(recordDecl(has(recordDecl(hasName("Y"))), |
209 | hasName("X"))), |
210 | hasName("Z")); |
211 | EXPECT_TRUE(matches("class Z { class X { class Y {}; }; };", |
212 | ZDescendantClassXHasClassY)); |
213 | EXPECT_TRUE( |
214 | matches("class Z { class A { class B { class X { class Y {}; }; }; }; };", |
215 | ZDescendantClassXHasClassY)); |
216 | EXPECT_TRUE(notMatches( |
217 | "class Z {" |
218 | " class A {" |
219 | " class B {" |
220 | " class X {" |
221 | " class C {" |
222 | " class Y {};" |
223 | " };" |
224 | " };" |
225 | " }; " |
226 | " };" |
227 | "};", ZDescendantClassXHasClassY)); |
228 | |
229 | DeclarationMatcher ZDescendantClassXDescendantClassY = |
230 | recordDecl( |
231 | hasDescendant(recordDecl(hasDescendant(recordDecl(hasName("Y"))), |
232 | hasName("X"))), |
233 | hasName("Z")); |
234 | EXPECT_TRUE( |
235 | matches("class Z { class A { class X { class B { class Y {}; }; }; }; };", |
236 | ZDescendantClassXDescendantClassY)); |
237 | EXPECT_TRUE(matches( |
238 | "class Z {" |
239 | " class A {" |
240 | " class X {" |
241 | " class B {" |
242 | " class Y {};" |
243 | " };" |
244 | " class Y {};" |
245 | " };" |
246 | " };" |
247 | "};", ZDescendantClassXDescendantClassY)); |
248 | } |
249 | |
250 | TEST(DeclarationMatcher, HasDescendantMemoization) { |
251 | DeclarationMatcher CannotMemoize = |
252 | decl(hasDescendant(typeLoc().bind("x")), has(decl())); |
253 | EXPECT_TRUE(matches("void f() { int i; }", CannotMemoize)); |
254 | } |
255 | |
256 | TEST(DeclarationMatcher, HasDescendantMemoizationUsesRestrictKind) { |
257 | auto Name = hasName("i"); |
258 | auto VD = internal::Matcher<VarDecl>(Name).dynCastTo<Decl>(); |
259 | auto RD = internal::Matcher<RecordDecl>(Name).dynCastTo<Decl>(); |
260 | |
261 | EXPECT_TRUE(notMatches("void f() { int i; }", |
262 | decl(hasDescendant(VD), hasDescendant(RD)))); |
263 | EXPECT_TRUE(notMatches("void f() { int i; }", |
264 | decl(hasDescendant(RD), hasDescendant(VD)))); |
265 | |
266 | EXPECT_TRUE(matches("void f() { int i; }", |
267 | decl(anyOf(hasDescendant(RD), hasDescendant(VD))))); |
268 | } |
269 | |
270 | TEST(DeclarationMatcher, HasAncestorMemoization) { |
271 | |
272 | |
273 | |
274 | DeclarationMatcher CannotMemoize = classTemplateSpecializationDecl( |
275 | hasAnyTemplateArgument(templateArgument().bind("targ")), |
276 | forEach(fieldDecl(hasAncestor(forStmt())))); |
277 | |
278 | EXPECT_TRUE(notMatches("template <typename T> struct S;" |
279 | "template <> struct S<int>{ int i; int j; };", |
280 | CannotMemoize)); |
281 | } |
282 | |
283 | TEST(DeclarationMatcher, HasAttr) { |
284 | EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};", |
285 | decl(hasAttr(clang::attr::WarnUnused)))); |
286 | EXPECT_FALSE(matches("struct X {};", |
287 | decl(hasAttr(clang::attr::WarnUnused)))); |
288 | } |
289 | |
290 | |
291 | TEST(DeclarationMatcher, MatchAnyOf) { |
292 | DeclarationMatcher YOrZDerivedFromX = cxxRecordDecl( |
293 | anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z")))); |
294 | EXPECT_TRUE(matches("class X {}; class Z : public X {};", YOrZDerivedFromX)); |
295 | EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX)); |
296 | EXPECT_TRUE( |
297 | notMatches("class X {}; class W : public X {};", YOrZDerivedFromX)); |
298 | EXPECT_TRUE(notMatches("class Z {};", YOrZDerivedFromX)); |
299 | |
300 | DeclarationMatcher XOrYOrZOrU = |
301 | recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U"))); |
302 | EXPECT_TRUE(matches("class X {};", XOrYOrZOrU)); |
303 | EXPECT_TRUE(notMatches("class V {};", XOrYOrZOrU)); |
304 | |
305 | DeclarationMatcher XOrYOrZOrUOrV = |
306 | recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U"), |
307 | hasName("V"))); |
308 | EXPECT_TRUE(matches("class X {};", XOrYOrZOrUOrV)); |
309 | EXPECT_TRUE(matches("class Y {};", XOrYOrZOrUOrV)); |
310 | EXPECT_TRUE(matches("class Z {};", XOrYOrZOrUOrV)); |
311 | EXPECT_TRUE(matches("class U {};", XOrYOrZOrUOrV)); |
312 | EXPECT_TRUE(matches("class V {};", XOrYOrZOrUOrV)); |
313 | EXPECT_TRUE(notMatches("class A {};", XOrYOrZOrUOrV)); |
314 | |
315 | StatementMatcher MixedTypes = stmt(anyOf(ifStmt(), binaryOperator())); |
316 | EXPECT_TRUE(matches("int F() { return 1 + 2; }", MixedTypes)); |
317 | EXPECT_TRUE(matches("int F() { if (true) return 1; }", MixedTypes)); |
318 | EXPECT_TRUE(notMatches("int F() { return 1; }", MixedTypes)); |
319 | |
320 | EXPECT_TRUE( |
321 | matches("void f() try { } catch (int) { } catch (...) { }", |
322 | cxxCatchStmt(anyOf(hasDescendant(varDecl()), isCatchAll())))); |
323 | } |
324 | |
325 | TEST(DeclarationMatcher, ClassIsDerived) { |
326 | DeclarationMatcher IsDerivedFromX = cxxRecordDecl(isDerivedFrom("X")); |
327 | |
328 | EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsDerivedFromX)); |
329 | EXPECT_TRUE(notMatches("class X {};", IsDerivedFromX)); |
330 | EXPECT_TRUE(notMatches("class X;", IsDerivedFromX)); |
331 | EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX)); |
332 | EXPECT_TRUE(notMatches("", IsDerivedFromX)); |
333 | |
334 | DeclarationMatcher IsAX = cxxRecordDecl(isSameOrDerivedFrom("X")); |
335 | |
336 | EXPECT_TRUE(matches("class X {}; class Y : public X {};", IsAX)); |
337 | EXPECT_TRUE(matches("class X {};", IsAX)); |
338 | EXPECT_TRUE(matches("class X;", IsAX)); |
339 | EXPECT_TRUE(notMatches("class Y;", IsAX)); |
340 | EXPECT_TRUE(notMatches("", IsAX)); |
341 | |
342 | DeclarationMatcher ZIsDerivedFromX = |
343 | cxxRecordDecl(hasName("Z"), isDerivedFrom("X")); |
344 | EXPECT_TRUE( |
345 | matches("class X {}; class Y : public X {}; class Z : public Y {};", |
346 | ZIsDerivedFromX)); |
347 | EXPECT_TRUE( |
348 | matches("class X {};" |
349 | "template<class T> class Y : public X {};" |
350 | "class Z : public Y<int> {};", ZIsDerivedFromX)); |
351 | EXPECT_TRUE(matches("class X {}; template<class T> class Z : public X {};", |
352 | ZIsDerivedFromX)); |
353 | EXPECT_TRUE( |
354 | matches("template<class T> class X {}; " |
355 | "template<class T> class Z : public X<T> {};", |
356 | ZIsDerivedFromX)); |
357 | EXPECT_TRUE( |
358 | matches("template<class T, class U=T> class X {}; " |
359 | "template<class T> class Z : public X<T> {};", |
360 | ZIsDerivedFromX)); |
361 | EXPECT_TRUE( |
362 | notMatches("template<class X> class A { class Z : public X {}; };", |
363 | ZIsDerivedFromX)); |
364 | EXPECT_TRUE( |
365 | matches("template<class X> class A { public: class Z : public X {}; }; " |
366 | "class X{}; void y() { A<X>::Z z; }", ZIsDerivedFromX)); |
367 | EXPECT_TRUE( |
368 | matches("template <class T> class X {}; " |
369 | "template<class Y> class A { class Z : public X<Y> {}; };", |
370 | ZIsDerivedFromX)); |
371 | EXPECT_TRUE( |
372 | notMatches("template<template<class T> class X> class A { " |
373 | " class Z : public X<int> {}; };", ZIsDerivedFromX)); |
374 | EXPECT_TRUE( |
375 | matches("template<template<class T> class X> class A { " |
376 | " public: class Z : public X<int> {}; }; " |
377 | "template<class T> class X {}; void y() { A<X>::Z z; }", |
378 | ZIsDerivedFromX)); |
379 | EXPECT_TRUE( |
380 | notMatches("template<class X> class A { class Z : public X::D {}; };", |
381 | ZIsDerivedFromX)); |
382 | EXPECT_TRUE( |
383 | matches("template<class X> class A { public: " |
384 | " class Z : public X::D {}; }; " |
385 | "class Y { public: class X {}; typedef X D; }; " |
386 | "void y() { A<Y>::Z z; }", ZIsDerivedFromX)); |
387 | EXPECT_TRUE( |
388 | matches("class X {}; typedef X Y; class Z : public Y {};", |
389 | ZIsDerivedFromX)); |
390 | EXPECT_TRUE( |
391 | matches("template<class T> class Y { typedef typename T::U X; " |
392 | " class Z : public X {}; };", ZIsDerivedFromX)); |
393 | EXPECT_TRUE(matches("class X {}; class Z : public ::X {};", |
394 | ZIsDerivedFromX)); |
395 | EXPECT_TRUE( |
396 | notMatches("template<class T> class X {}; " |
397 | "template<class T> class A { class Z : public X<T>::D {}; };", |
398 | ZIsDerivedFromX)); |
399 | EXPECT_TRUE( |
400 | matches("template<class T> class X { public: typedef X<T> D; }; " |
401 | "template<class T> class A { public: " |
402 | " class Z : public X<T>::D {}; }; void y() { A<int>::Z z; }", |
403 | ZIsDerivedFromX)); |
404 | EXPECT_TRUE( |
405 | notMatches("template<class X> class A { class Z : public X::D::E {}; };", |
406 | ZIsDerivedFromX)); |
407 | EXPECT_TRUE( |
408 | matches("class X {}; typedef X V; typedef V W; class Z : public W {};", |
409 | ZIsDerivedFromX)); |
410 | EXPECT_TRUE( |
411 | matches("class X {}; class Y : public X {}; " |
412 | "typedef Y V; typedef V W; class Z : public W {};", |
413 | ZIsDerivedFromX)); |
414 | EXPECT_TRUE( |
415 | matches("template<class T, class U> class X {}; " |
416 | "template<class T> class A { class Z : public X<T, int> {}; };", |
417 | ZIsDerivedFromX)); |
418 | EXPECT_TRUE( |
419 | notMatches("template<class X> class D { typedef X A; typedef A B; " |
420 | " typedef B C; class Z : public C {}; };", |
421 | ZIsDerivedFromX)); |
422 | EXPECT_TRUE( |
423 | matches("class X {}; typedef X A; typedef A B; " |
424 | "class Z : public B {};", ZIsDerivedFromX)); |
425 | EXPECT_TRUE( |
426 | matches("class X {}; typedef X A; typedef A B; typedef B C; " |
427 | "class Z : public C {};", ZIsDerivedFromX)); |
428 | EXPECT_TRUE( |
429 | matches("class U {}; typedef U X; typedef X V; " |
430 | "class Z : public V {};", ZIsDerivedFromX)); |
431 | EXPECT_TRUE( |
432 | matches("class Base {}; typedef Base X; " |
433 | "class Z : public Base {};", ZIsDerivedFromX)); |
434 | EXPECT_TRUE( |
435 | matches("class Base {}; typedef Base Base2; typedef Base2 X; " |
436 | "class Z : public Base {};", ZIsDerivedFromX)); |
437 | EXPECT_TRUE( |
438 | notMatches("class Base {}; class Base2 {}; typedef Base2 X; " |
439 | "class Z : public Base {};", ZIsDerivedFromX)); |
440 | EXPECT_TRUE( |
441 | matches("class A {}; typedef A X; typedef A Y; " |
442 | "class Z : public Y {};", ZIsDerivedFromX)); |
443 | EXPECT_TRUE( |
444 | notMatches("template <typename T> class Z;" |
445 | "template <> class Z<void> {};" |
446 | "template <typename T> class Z : public Z<void> {};", |
447 | IsDerivedFromX)); |
448 | EXPECT_TRUE( |
449 | matches("template <typename T> class X;" |
450 | "template <> class X<void> {};" |
451 | "template <typename T> class X : public X<void> {};", |
452 | IsDerivedFromX)); |
453 | EXPECT_TRUE(matches( |
454 | "class X {};" |
455 | "template <typename T> class Z;" |
456 | "template <> class Z<void> {};" |
457 | "template <typename T> class Z : public Z<void>, public X {};", |
458 | ZIsDerivedFromX)); |
459 | EXPECT_TRUE( |
460 | notMatches("template<int> struct X;" |
461 | "template<int i> struct X : public X<i-1> {};", |
462 | cxxRecordDecl(isDerivedFrom(recordDecl(hasName("Some")))))); |
463 | EXPECT_TRUE(matches( |
464 | "struct A {};" |
465 | "template<int> struct X;" |
466 | "template<int i> struct X : public X<i-1> {};" |
467 | "template<> struct X<0> : public A {};" |
468 | "struct B : public X<42> {};", |
469 | cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A")))))); |
470 | |
471 | |
472 | |
473 | |
474 | const char *RecursiveTemplateOneParameter = |
475 | "class Base1 {}; class Base2 {};" |
476 | "template <typename T> class Z;" |
477 | "template <> class Z<void> : public Base1 {};" |
478 | "template <> class Z<int> : public Base2 {};" |
479 | "template <> class Z<float> : public Z<void> {};" |
480 | "template <> class Z<double> : public Z<int> {};" |
481 | "template <typename T> class Z : public Z<float>, public Z<double> {};" |
482 | "void f() { Z<float> z_float; Z<double> z_double; Z<char> z_char; }"; |
483 | EXPECT_TRUE(matches( |
484 | RecursiveTemplateOneParameter, |
485 | varDecl(hasName("z_float"), |
486 | hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"))))))); |
487 | EXPECT_TRUE(notMatches( |
488 | RecursiveTemplateOneParameter, |
489 | varDecl(hasName("z_float"), |
490 | hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2"))))))); |
491 | EXPECT_TRUE(matches( |
492 | RecursiveTemplateOneParameter, |
493 | varDecl(hasName("z_char"), |
494 | hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"), |
495 | isDerivedFrom("Base2"))))))); |
496 | |
497 | const char *RecursiveTemplateTwoParameters = |
498 | "class Base1 {}; class Base2 {};" |
499 | "template <typename T1, typename T2> class Z;" |
500 | "template <typename T> class Z<void, T> : public Base1 {};" |
501 | "template <typename T> class Z<int, T> : public Base2 {};" |
502 | "template <typename T> class Z<float, T> : public Z<void, T> {};" |
503 | "template <typename T> class Z<double, T> : public Z<int, T> {};" |
504 | "template <typename T1, typename T2> class Z : " |
505 | " public Z<float, T2>, public Z<double, T2> {};" |
506 | "void f() { Z<float, void> z_float; Z<double, void> z_double; " |
507 | " Z<char, void> z_char; }"; |
508 | EXPECT_TRUE(matches( |
509 | RecursiveTemplateTwoParameters, |
510 | varDecl(hasName("z_float"), |
511 | hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"))))))); |
512 | EXPECT_TRUE(notMatches( |
513 | RecursiveTemplateTwoParameters, |
514 | varDecl(hasName("z_float"), |
515 | hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2"))))))); |
516 | EXPECT_TRUE(matches( |
517 | RecursiveTemplateTwoParameters, |
518 | varDecl(hasName("z_char"), |
519 | hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"), |
520 | isDerivedFrom("Base2"))))))); |
521 | EXPECT_TRUE(matches( |
522 | "namespace ns { class X {}; class Y : public X {}; }", |
523 | cxxRecordDecl(isDerivedFrom("::ns::X")))); |
524 | EXPECT_TRUE(notMatches( |
525 | "class X {}; class Y : public X {};", |
526 | cxxRecordDecl(isDerivedFrom("::ns::X")))); |
527 | |
528 | EXPECT_TRUE(matches( |
529 | "class X {}; class Y : public X {};", |
530 | cxxRecordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test"))))); |
531 | |
532 | EXPECT_TRUE(matches( |
533 | "template<typename T> class X {};" |
534 | "template<typename T> using Z = X<T>;" |
535 | "template <typename T> class Y : Z<T> {};", |
536 | cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X")))))); |
537 | } |
538 | |
539 | TEST(DeclarationMatcher, IsLambda) { |
540 | const auto IsLambda = cxxMethodDecl(ofClass(cxxRecordDecl(isLambda()))); |
541 | EXPECT_TRUE(matches("auto x = []{};", IsLambda)); |
542 | EXPECT_TRUE(notMatches("struct S { void operator()() const; };", IsLambda)); |
543 | } |
544 | |
545 | TEST(Matcher, BindMatchedNodes) { |
546 | DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x")); |
547 | |
548 | EXPECT_TRUE(matchAndVerifyResultTrue("class X {};", |
549 | ClassX, llvm::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("x"))); |
550 | |
551 | EXPECT_TRUE(matchAndVerifyResultFalse("class X {};", |
552 | ClassX, llvm::make_unique<VerifyIdIsBoundTo<CXXRecordDecl>>("other-id"))); |
553 | |
554 | TypeMatcher TypeAHasClassB = hasDeclaration( |
555 | recordDecl(hasName("A"), has(recordDecl(hasName("B")).bind("b")))); |
556 | |
557 | EXPECT_TRUE(matchAndVerifyResultTrue("class A { public: A *a; class B {}; };", |
558 | TypeAHasClassB, |
559 | llvm::make_unique<VerifyIdIsBoundTo<Decl>>("b"))); |
560 | |
561 | StatementMatcher MethodX = |
562 | callExpr(callee(cxxMethodDecl(hasName("x")))).bind("x"); |
563 | |
564 | EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };", |
565 | MethodX, |
566 | llvm::make_unique<VerifyIdIsBoundTo<CXXMemberCallExpr>>("x"))); |
567 | } |
568 | |
569 | TEST(Matcher, BindTheSameNameInAlternatives) { |
570 | StatementMatcher matcher = anyOf( |
571 | binaryOperator(hasOperatorName("+"), |
572 | hasLHS(expr().bind("x")), |
573 | hasRHS(integerLiteral(equals(0)))), |
574 | binaryOperator(hasOperatorName("+"), |
575 | hasLHS(integerLiteral(equals(0))), |
576 | hasRHS(expr().bind("x")))); |
577 | |
578 | EXPECT_TRUE(matchAndVerifyResultTrue( |
579 | |
580 | |
581 | "int f() { return 0 + f(); }", |
582 | matcher, |
583 | llvm::make_unique<VerifyIdIsBoundTo<CallExpr>>("x"))); |
584 | } |
585 | |
586 | TEST(Matcher, BindsIDForMemoizedResults) { |
587 | |
588 | |
589 | DeclarationMatcher ClassX = recordDecl(hasName("X")).bind("x"); |
590 | EXPECT_TRUE(matchAndVerifyResultTrue( |
591 | "class A { class B { class X {}; }; };", |
592 | DeclarationMatcher(anyOf( |
593 | recordDecl(hasName("A"), hasDescendant(ClassX)), |
594 | recordDecl(hasName("B"), hasDescendant(ClassX)))), |
595 | llvm::make_unique<VerifyIdIsBoundTo<Decl>>("x", 2))); |
596 | } |
597 | |
598 | TEST(HasType, MatchesAsString) { |
599 | EXPECT_TRUE( |
600 | matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }", |
601 | cxxMemberCallExpr(on(hasType(asString("class Y *")))))); |
602 | EXPECT_TRUE( |
603 | matches("class X { void x(int x) {} };", |
604 | cxxMethodDecl(hasParameter(0, hasType(asString("int")))))); |
605 | EXPECT_TRUE(matches("namespace ns { struct A {}; } struct B { ns::A a; };", |
606 | fieldDecl(hasType(asString("ns::A"))))); |
607 | EXPECT_TRUE(matches("namespace { struct A {}; } struct B { A a; };", |
608 | fieldDecl(hasType(asString("struct (anonymous namespace)::A"))))); |
609 | } |
610 | |
611 | TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) { |
612 | StatementMatcher OpCallAndAnd = |
613 | cxxOperatorCallExpr(hasOverloadedOperatorName("&&")); |
614 | EXPECT_TRUE(matches("class Y { }; " |
615 | "bool operator&&(Y x, Y y) { return true; }; " |
616 | "Y a; Y b; bool c = a && b;", OpCallAndAnd)); |
617 | StatementMatcher OpCallLessLess = |
618 | cxxOperatorCallExpr(hasOverloadedOperatorName("<<")); |
619 | EXPECT_TRUE(notMatches("class Y { }; " |
620 | "bool operator&&(Y x, Y y) { return true; }; " |
621 | "Y a; Y b; bool c = a && b;", |
622 | OpCallLessLess)); |
623 | StatementMatcher OpStarCall = |
624 | cxxOperatorCallExpr(hasOverloadedOperatorName("*")); |
625 | EXPECT_TRUE(matches("class Y; int operator*(Y &); void f(Y &y) { *y; }", |
626 | OpStarCall)); |
627 | DeclarationMatcher ClassWithOpStar = |
628 | cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*"))); |
629 | EXPECT_TRUE(matches("class Y { int operator*(); };", |
630 | ClassWithOpStar)); |
631 | EXPECT_TRUE(notMatches("class Y { void myOperator(); };", |
632 | ClassWithOpStar)) ; |
633 | DeclarationMatcher AnyOpStar = functionDecl(hasOverloadedOperatorName("*")); |
634 | EXPECT_TRUE(matches("class Y; int operator*(Y &);", AnyOpStar)); |
635 | EXPECT_TRUE(matches("class Y { int operator*(); };", AnyOpStar)); |
636 | } |
637 | |
638 | |
639 | TEST(Matcher, NestedOverloadedOperatorCalls) { |
640 | EXPECT_TRUE(matchAndVerifyResultTrue( |
641 | "class Y { }; " |
642 | "Y& operator&&(Y& x, Y& y) { return x; }; " |
643 | "Y a; Y b; Y c; Y d = a && b && c;", |
644 | cxxOperatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"), |
645 | llvm::make_unique<VerifyIdIsBoundTo<CXXOperatorCallExpr>>("x", 2))); |
646 | EXPECT_TRUE(matches("class Y { }; " |
647 | "Y& operator&&(Y& x, Y& y) { return x; }; " |
648 | "Y a; Y b; Y c; Y d = a && b && c;", |
649 | cxxOperatorCallExpr(hasParent(cxxOperatorCallExpr())))); |
650 | EXPECT_TRUE( |
651 | matches("class Y { }; " |
652 | "Y& operator&&(Y& x, Y& y) { return x; }; " |
653 | "Y a; Y b; Y c; Y d = a && b && c;", |
654 | cxxOperatorCallExpr(hasDescendant(cxxOperatorCallExpr())))); |
655 | } |
656 | |
657 | TEST(Matcher, VarDecl_Storage) { |
658 | auto M = varDecl(hasName("X"), hasLocalStorage()); |
659 | EXPECT_TRUE(matches("void f() { int X; }", M)); |
660 | EXPECT_TRUE(notMatches("int X;", M)); |
661 | EXPECT_TRUE(notMatches("void f() { static int X; }", M)); |
662 | |
663 | M = varDecl(hasName("X"), hasGlobalStorage()); |
664 | EXPECT_TRUE(notMatches("void f() { int X; }", M)); |
665 | EXPECT_TRUE(matches("int X;", M)); |
666 | EXPECT_TRUE(matches("void f() { static int X; }", M)); |
667 | } |
668 | |
669 | TEST(Matcher, VarDecl_IsStaticLocal) { |
670 | auto M = varDecl(isStaticLocal()); |
671 | EXPECT_TRUE(matches("void f() { static int X; }", M)); |
672 | EXPECT_TRUE(notMatches("static int X;", M)); |
673 | EXPECT_TRUE(notMatches("void f() { int X; }", M)); |
674 | EXPECT_TRUE(notMatches("int X;", M)); |
675 | } |
676 | |
677 | TEST(Matcher, VarDecl_StorageDuration) { |
678 | std::string T = |
679 | "void f() { int x; static int y; } int a;static int b;extern int c;"; |
680 | |
681 | EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration()))); |
682 | EXPECT_TRUE( |
683 | notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration()))); |
684 | EXPECT_TRUE( |
685 | notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration()))); |
686 | |
687 | EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration()))); |
688 | EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration()))); |
689 | EXPECT_TRUE(matches(T, varDecl(hasName("b"), hasStaticStorageDuration()))); |
690 | EXPECT_TRUE(matches(T, varDecl(hasName("c"), hasStaticStorageDuration()))); |
691 | EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasStaticStorageDuration()))); |
692 | |
693 | |
694 | |
695 | |
696 | |
697 | EXPECT_TRUE(notMatches(T, varDecl(hasName("x"), hasThreadStorageDuration()))); |
698 | EXPECT_TRUE(notMatches(T, varDecl(hasName("y"), hasThreadStorageDuration()))); |
699 | EXPECT_TRUE(notMatches(T, varDecl(hasName("a"), hasThreadStorageDuration()))); |
700 | } |
701 | |
702 | TEST(Matcher, FindsVarDeclInFunctionParameter) { |
703 | EXPECT_TRUE(matches( |
704 | "void f(int i) {}", |
705 | varDecl(hasName("i")))); |
706 | } |
707 | |
708 | TEST(UnaryExpressionOrTypeTraitExpression, MatchesCorrectType) { |
709 | EXPECT_TRUE(matches("void x() { int a = sizeof(a); }", sizeOfExpr( |
710 | hasArgumentOfType(asString("int"))))); |
711 | EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr( |
712 | hasArgumentOfType(asString("float"))))); |
713 | EXPECT_TRUE(matches( |
714 | "struct A {}; void x() { A a; int b = sizeof(a); }", |
715 | sizeOfExpr(hasArgumentOfType(hasDeclaration(recordDecl(hasName("A"))))))); |
716 | EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr( |
717 | hasArgumentOfType(hasDeclaration(recordDecl(hasName("string"))))))); |
718 | } |
719 | |
720 | TEST(IsInteger, MatchesIntegers) { |
721 | EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isInteger())))); |
722 | EXPECT_TRUE(matches( |
723 | "long long i = 0; void f(long long) { }; void g() {f(i);}", |
724 | callExpr(hasArgument(0, declRefExpr( |
725 | to(varDecl(hasType(isInteger())))))))); |
726 | } |
727 | |
728 | TEST(IsInteger, ReportsNoFalsePositives) { |
729 | EXPECT_TRUE(notMatches("int *i;", varDecl(hasType(isInteger())))); |
730 | EXPECT_TRUE(notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}", |
731 | callExpr(hasArgument(0, declRefExpr( |
732 | to(varDecl(hasType(isInteger())))))))); |
733 | } |
734 | |
735 | TEST(IsSignedInteger, MatchesSignedIntegers) { |
736 | EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isSignedInteger())))); |
737 | EXPECT_TRUE(notMatches("unsigned i = 0;", |
738 | varDecl(hasType(isSignedInteger())))); |
739 | } |
740 | |
741 | TEST(IsUnsignedInteger, MatchesUnsignedIntegers) { |
742 | EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isUnsignedInteger())))); |
743 | EXPECT_TRUE(matches("unsigned i = 0;", |
744 | varDecl(hasType(isUnsignedInteger())))); |
745 | } |
746 | |
747 | TEST(IsAnyPointer, MatchesPointers) { |
748 | EXPECT_TRUE(matches("int* i = nullptr;", varDecl(hasType(isAnyPointer())))); |
749 | } |
750 | |
751 | TEST(IsAnyPointer, MatchesObjcPointer) { |
752 | EXPECT_TRUE(matchesObjC("@interface Foo @end Foo *f;", |
753 | varDecl(hasType(isAnyPointer())))); |
754 | } |
755 | |
756 | TEST(IsAnyPointer, ReportsNoFalsePositives) { |
757 | EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isAnyPointer())))); |
758 | } |
759 | |
760 | TEST(IsAnyCharacter, MatchesCharacters) { |
761 | EXPECT_TRUE(matches("char i = 0;", varDecl(hasType(isAnyCharacter())))); |
762 | } |
763 | |
764 | TEST(IsAnyCharacter, ReportsNoFalsePositives) { |
765 | EXPECT_TRUE(notMatches("int i;", varDecl(hasType(isAnyCharacter())))); |
766 | } |
767 | |
768 | TEST(IsArrow, MatchesMemberVariablesViaArrow) { |
769 | EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };", |
770 | memberExpr(isArrow()))); |
771 | EXPECT_TRUE(matches("class Y { void x() { y; } int y; };", |
772 | memberExpr(isArrow()))); |
773 | EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };", |
774 | memberExpr(isArrow()))); |
775 | EXPECT_TRUE(matches("template <class T> class Y { void x() { this->m; } };", |
776 | cxxDependentScopeMemberExpr(isArrow()))); |
777 | EXPECT_TRUE( |
778 | notMatches("template <class T> class Y { void x() { (*this).m; } };", |
779 | cxxDependentScopeMemberExpr(isArrow()))); |
780 | } |
781 | |
782 | TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) { |
783 | EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };", |
784 | memberExpr(isArrow()))); |
785 | EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };", |
786 | memberExpr(isArrow()))); |
787 | EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } static int y; };", |
788 | memberExpr(isArrow()))); |
789 | } |
790 | |
791 | TEST(IsArrow, MatchesMemberCallsViaArrow) { |
792 | EXPECT_TRUE(matches("class Y { void x() { this->x(); } };", |
793 | memberExpr(isArrow()))); |
794 | EXPECT_TRUE(matches("class Y { void x() { x(); } };", |
795 | memberExpr(isArrow()))); |
796 | EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };", |
797 | memberExpr(isArrow()))); |
798 | EXPECT_TRUE( |
799 | matches("class Y { template <class T> void x() { this->x<T>(); } };", |
800 | unresolvedMemberExpr(isArrow()))); |
801 | EXPECT_TRUE(matches("class Y { template <class T> void x() { x<T>(); } };", |
802 | unresolvedMemberExpr(isArrow()))); |
803 | EXPECT_TRUE( |
804 | notMatches("class Y { template <class T> void x() { (*this).x<T>(); } };", |
805 | unresolvedMemberExpr(isArrow()))); |
806 | } |
807 | |
808 | TEST(ConversionDeclaration, IsExplicit) { |
809 | EXPECT_TRUE(matches("struct S { explicit operator int(); };", |
810 | cxxConversionDecl(isExplicit()))); |
811 | EXPECT_TRUE(notMatches("struct S { operator int(); };", |
812 | cxxConversionDecl(isExplicit()))); |
813 | } |
814 | |
815 | TEST(Matcher, ArgumentCount) { |
816 | StatementMatcher Call1Arg = callExpr(argumentCountIs(1)); |
817 | |
818 | EXPECT_TRUE(matches("void x(int) { x(0); }", Call1Arg)); |
819 | EXPECT_TRUE(matches("class X { void x(int) { x(0); } };", Call1Arg)); |
820 | EXPECT_TRUE(notMatches("void x(int, int) { x(0, 0); }", Call1Arg)); |
821 | } |
822 | |
823 | TEST(Matcher, ParameterCount) { |
824 | DeclarationMatcher Function1Arg = functionDecl(parameterCountIs(1)); |
825 | EXPECT_TRUE(matches("void f(int i) {}", Function1Arg)); |
826 | EXPECT_TRUE(matches("class X { void f(int i) {} };", Function1Arg)); |
827 | EXPECT_TRUE(notMatches("void f() {}", Function1Arg)); |
828 | EXPECT_TRUE(notMatches("void f(int i, int j, int k) {}", Function1Arg)); |
829 | EXPECT_TRUE(matches("void f(int i, ...) {};", Function1Arg)); |
830 | } |
831 | |
832 | TEST(Matcher, References) { |
833 | DeclarationMatcher ReferenceClassX = varDecl( |
834 | hasType(references(recordDecl(hasName("X"))))); |
835 | EXPECT_TRUE(matches("class X {}; void y(X y) { X &x = y; }", |
836 | ReferenceClassX)); |
837 | EXPECT_TRUE( |
838 | matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX)); |
839 | |
840 | |
841 | EXPECT_TRUE( |
842 | matches("class X {}; void y(X y) { X x = y; }", ReferenceClassX)); |
843 | EXPECT_TRUE( |
844 | notMatches("class X {}; extern X x;", ReferenceClassX)); |
845 | EXPECT_TRUE( |
846 | notMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX)); |
847 | } |
848 | |
849 | TEST(QualType, hasLocalQualifiers) { |
850 | EXPECT_TRUE(notMatches("typedef const int const_int; const_int i = 1;", |
851 | varDecl(hasType(hasLocalQualifiers())))); |
852 | EXPECT_TRUE(matches("int *const j = nullptr;", |
853 | varDecl(hasType(hasLocalQualifiers())))); |
854 | EXPECT_TRUE(matches("int *volatile k;", |
855 | varDecl(hasType(hasLocalQualifiers())))); |
856 | EXPECT_TRUE(notMatches("int m;", |
857 | varDecl(hasType(hasLocalQualifiers())))); |
858 | } |
859 | |
860 | TEST(IsExternC, MatchesExternCFunctionDeclarations) { |
861 | EXPECT_TRUE(matches("extern \"C\" void f() {}", functionDecl(isExternC()))); |
862 | EXPECT_TRUE(matches("extern \"C\" { void f() {} }", |
863 | functionDecl(isExternC()))); |
864 | EXPECT_TRUE(notMatches("void f() {}", functionDecl(isExternC()))); |
865 | } |
866 | |
867 | TEST(IsExternC, MatchesExternCVariableDeclarations) { |
868 | EXPECT_TRUE(matches("extern \"C\" int i;", varDecl(isExternC()))); |
869 | EXPECT_TRUE(matches("extern \"C\" { int i; }", varDecl(isExternC()))); |
870 | EXPECT_TRUE(notMatches("int i;", varDecl(isExternC()))); |
871 | } |
872 | |
873 | TEST(IsStaticStorageClass, MatchesStaticDeclarations) { |
874 | EXPECT_TRUE( |
875 | matches("static void f() {}", functionDecl(isStaticStorageClass()))); |
876 | EXPECT_TRUE(matches("static int i = 1;", varDecl(isStaticStorageClass()))); |
877 | EXPECT_TRUE(notMatches("int i = 1;", varDecl(isStaticStorageClass()))); |
878 | EXPECT_TRUE(notMatches("extern int i;", varDecl(isStaticStorageClass()))); |
879 | EXPECT_TRUE(notMatches("void f() {}", functionDecl(isStaticStorageClass()))); |
880 | } |
881 | |
882 | TEST(IsDefaulted, MatchesDefaultedFunctionDeclarations) { |
883 | EXPECT_TRUE(notMatches("class A { ~A(); };", |
884 | functionDecl(hasName("~A"), isDefaulted()))); |
885 | EXPECT_TRUE(matches("class B { ~B() = default; };", |
886 | functionDecl(hasName("~B"), isDefaulted()))); |
887 | } |
888 | |
889 | TEST(IsDeleted, MatchesDeletedFunctionDeclarations) { |
890 | EXPECT_TRUE( |
891 | notMatches("void Func();", functionDecl(hasName("Func"), isDeleted()))); |
892 | EXPECT_TRUE(matches("void Func() = delete;", |
893 | functionDecl(hasName("Func"), isDeleted()))); |
894 | } |
895 | |
896 | TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) { |
897 | EXPECT_TRUE(notMatches("void f();", functionDecl(isNoThrow()))); |
898 | EXPECT_TRUE(notMatches("void f() throw(int);", functionDecl(isNoThrow()))); |
899 | EXPECT_TRUE( |
900 | notMatches("void f() noexcept(false);", functionDecl(isNoThrow()))); |
901 | EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow()))); |
902 | EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow()))); |
903 | |
904 | EXPECT_TRUE(notMatches("void f();", functionProtoType(isNoThrow()))); |
905 | EXPECT_TRUE(notMatches("void f() throw(int);", functionProtoType(isNoThrow()))); |
906 | EXPECT_TRUE( |
907 | notMatches("void f() noexcept(false);", functionProtoType(isNoThrow()))); |
908 | EXPECT_TRUE(matches("void f() throw();", functionProtoType(isNoThrow()))); |
909 | EXPECT_TRUE(matches("void f() noexcept;", functionProtoType(isNoThrow()))); |
910 | } |
911 | |
912 | TEST(isConstexpr, MatchesConstexprDeclarations) { |
913 | EXPECT_TRUE(matches("constexpr int foo = 42;", |
914 | varDecl(hasName("foo"), isConstexpr()))); |
915 | EXPECT_TRUE(matches("constexpr int bar();", |
916 | functionDecl(hasName("bar"), isConstexpr()))); |
917 | EXPECT_TRUE(matchesConditionally("void baz() { if constexpr(1 > 0) {} }", |
918 | ifStmt(isConstexpr()), true, "-std=c++17")); |
919 | EXPECT_TRUE(matchesConditionally("void baz() { if (1 > 0) {} }", |
920 | ifStmt(isConstexpr()), false, "-std=c++17")); |
921 | } |
922 | |
923 | TEST(TemplateArgumentCountIs, Matches) { |
924 | EXPECT_TRUE( |
925 | matches("template<typename T> struct C {}; C<int> c;", |
926 | classTemplateSpecializationDecl(templateArgumentCountIs(1)))); |
927 | EXPECT_TRUE( |
928 | notMatches("template<typename T> struct C {}; C<int> c;", |
929 | classTemplateSpecializationDecl(templateArgumentCountIs(2)))); |
930 | |
931 | EXPECT_TRUE(matches("template<typename T> struct C {}; C<int> c;", |
932 | templateSpecializationType(templateArgumentCountIs(1)))); |
933 | EXPECT_TRUE( |
934 | notMatches("template<typename T> struct C {}; C<int> c;", |
935 | templateSpecializationType(templateArgumentCountIs(2)))); |
936 | } |
937 | |
938 | TEST(IsIntegral, Matches) { |
939 | EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;", |
940 | classTemplateSpecializationDecl( |
941 | hasAnyTemplateArgument(isIntegral())))); |
942 | EXPECT_TRUE(notMatches("template<typename T> struct C {}; C<int> c;", |
943 | classTemplateSpecializationDecl(hasAnyTemplateArgument( |
944 | templateArgument(isIntegral()))))); |
945 | } |
946 | |
947 | TEST(EqualsIntegralValue, Matches) { |
948 | EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;", |
949 | classTemplateSpecializationDecl( |
950 | hasAnyTemplateArgument(equalsIntegralValue("42"))))); |
951 | EXPECT_TRUE(matches("template<int T> struct C {}; C<-42> c;", |
952 | classTemplateSpecializationDecl( |
953 | hasAnyTemplateArgument(equalsIntegralValue("-42"))))); |
954 | EXPECT_TRUE(matches("template<int T> struct C {}; C<-0042> c;", |
955 | classTemplateSpecializationDecl( |
956 | hasAnyTemplateArgument(equalsIntegralValue("-34"))))); |
957 | EXPECT_TRUE(notMatches("template<int T> struct C {}; C<42> c;", |
958 | classTemplateSpecializationDecl(hasAnyTemplateArgument( |
959 | equalsIntegralValue("0042"))))); |
960 | } |
961 | |
962 | TEST(Matcher, MatchesAccessSpecDecls) { |
963 | EXPECT_TRUE(matches("class C { public: int i; };", accessSpecDecl())); |
964 | EXPECT_TRUE( |
965 | matches("class C { public: int i; };", accessSpecDecl(isPublic()))); |
966 | EXPECT_TRUE( |
967 | notMatches("class C { public: int i; };", accessSpecDecl(isProtected()))); |
968 | EXPECT_TRUE( |
969 | notMatches("class C { public: int i; };", accessSpecDecl(isPrivate()))); |
970 | |
971 | EXPECT_TRUE(notMatches("class C { int i; };", accessSpecDecl())); |
972 | } |
973 | |
974 | TEST(Matcher, MatchesFinal) { |
975 | EXPECT_TRUE(matches("class X final {};", cxxRecordDecl(isFinal()))); |
976 | EXPECT_TRUE(matches("class X { virtual void f() final; };", |
977 | cxxMethodDecl(isFinal()))); |
978 | EXPECT_TRUE(notMatches("class X {};", cxxRecordDecl(isFinal()))); |
979 | EXPECT_TRUE( |
980 | notMatches("class X { virtual void f(); };", cxxMethodDecl(isFinal()))); |
981 | } |
982 | |
983 | TEST(Matcher, MatchesVirtualMethod) { |
984 | EXPECT_TRUE(matches("class X { virtual int f(); };", |
985 | cxxMethodDecl(isVirtual(), hasName("::X::f")))); |
986 | EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isVirtual()))); |
987 | } |
988 | |
989 | TEST(Matcher, MatchesVirtualAsWrittenMethod) { |
990 | EXPECT_TRUE(matches("class A { virtual int f(); };" |
991 | "class B : public A { int f(); };", |
992 | cxxMethodDecl(isVirtualAsWritten(), hasName("::A::f")))); |
993 | EXPECT_TRUE( |
994 | notMatches("class A { virtual int f(); };" |
995 | "class B : public A { int f(); };", |
996 | cxxMethodDecl(isVirtualAsWritten(), hasName("::B::f")))); |
997 | } |
998 | |
999 | TEST(Matcher, MatchesPureMethod) { |
1000 | EXPECT_TRUE(matches("class X { virtual int f() = 0; };", |
1001 | cxxMethodDecl(isPure(), hasName("::X::f")))); |
1002 | EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isPure()))); |
1003 | } |
1004 | |
1005 | TEST(Matcher, MatchesCopyAssignmentOperator) { |
1006 | EXPECT_TRUE(matches("class X { X &operator=(X); };", |
1007 | cxxMethodDecl(isCopyAssignmentOperator()))); |
1008 | EXPECT_TRUE(matches("class X { X &operator=(X &); };", |
1009 | cxxMethodDecl(isCopyAssignmentOperator()))); |
1010 | EXPECT_TRUE(matches("class X { X &operator=(const X &); };", |
1011 | cxxMethodDecl(isCopyAssignmentOperator()))); |
1012 | EXPECT_TRUE(matches("class X { X &operator=(volatile X &); };", |
1013 | cxxMethodDecl(isCopyAssignmentOperator()))); |
1014 | EXPECT_TRUE(matches("class X { X &operator=(const volatile X &); };", |
1015 | cxxMethodDecl(isCopyAssignmentOperator()))); |
1016 | EXPECT_TRUE(notMatches("class X { X &operator=(X &&); };", |
1017 | cxxMethodDecl(isCopyAssignmentOperator()))); |
1018 | } |
1019 | |
1020 | TEST(Matcher, MatchesMoveAssignmentOperator) { |
1021 | EXPECT_TRUE(notMatches("class X { X &operator=(X); };", |
1022 | cxxMethodDecl(isMoveAssignmentOperator()))); |
1023 | EXPECT_TRUE(matches("class X { X &operator=(X &&); };", |
1024 | cxxMethodDecl(isMoveAssignmentOperator()))); |
1025 | EXPECT_TRUE(matches("class X { X &operator=(const X &&); };", |
1026 | cxxMethodDecl(isMoveAssignmentOperator()))); |
1027 | EXPECT_TRUE(matches("class X { X &operator=(volatile X &&); };", |
1028 | cxxMethodDecl(isMoveAssignmentOperator()))); |
1029 | EXPECT_TRUE(matches("class X { X &operator=(const volatile X &&); };", |
1030 | cxxMethodDecl(isMoveAssignmentOperator()))); |
1031 | EXPECT_TRUE(notMatches("class X { X &operator=(X &); };", |
1032 | cxxMethodDecl(isMoveAssignmentOperator()))); |
1033 | } |
1034 | |
1035 | TEST(Matcher, MatchesConstMethod) { |
1036 | EXPECT_TRUE( |
1037 | matches("struct A { void foo() const; };", cxxMethodDecl(isConst()))); |
1038 | EXPECT_TRUE( |
1039 | notMatches("struct A { void foo(); };", cxxMethodDecl(isConst()))); |
1040 | } |
1041 | |
1042 | TEST(Matcher, MatchesOverridingMethod) { |
1043 | EXPECT_TRUE(matches("class X { virtual int f(); }; " |
1044 | "class Y : public X { int f(); };", |
1045 | cxxMethodDecl(isOverride(), hasName("::Y::f")))); |
1046 | EXPECT_TRUE(notMatches("class X { virtual int f(); }; " |
1047 | "class Y : public X { int f(); };", |
1048 | cxxMethodDecl(isOverride(), hasName("::X::f")))); |
1049 | EXPECT_TRUE(notMatches("class X { int f(); }; " |
1050 | "class Y : public X { int f(); };", |
1051 | cxxMethodDecl(isOverride()))); |
1052 | EXPECT_TRUE(notMatches("class X { int f(); int f(int); }; ", |
1053 | cxxMethodDecl(isOverride()))); |
1054 | EXPECT_TRUE( |
1055 | matches("template <typename Base> struct Y : Base { void f() override;};", |
1056 | cxxMethodDecl(isOverride(), hasName("::Y::f")))); |
1057 | } |
1058 | |
1059 | TEST(Matcher, ConstructorArgument) { |
1060 | StatementMatcher Constructor = cxxConstructExpr( |
1061 | hasArgument(0, declRefExpr(to(varDecl(hasName("y")))))); |
1062 | |
1063 | EXPECT_TRUE( |
1064 | matches("class X { public: X(int); }; void x() { int y; X x(y); }", |
1065 | Constructor)); |
1066 | EXPECT_TRUE( |
1067 | matches("class X { public: X(int); }; void x() { int y; X x = X(y); }", |
1068 | Constructor)); |
1069 | EXPECT_TRUE( |
1070 | matches("class X { public: X(int); }; void x() { int y; X x = y; }", |
1071 | Constructor)); |
1072 | EXPECT_TRUE( |
1073 | notMatches("class X { public: X(int); }; void x() { int z; X x(z); }", |
1074 | Constructor)); |
1075 | |
1076 | StatementMatcher WrongIndex = cxxConstructExpr( |
1077 | hasArgument(42, declRefExpr(to(varDecl(hasName("y")))))); |
1078 | EXPECT_TRUE( |
1079 | notMatches("class X { public: X(int); }; void x() { int y; X x(y); }", |
1080 | WrongIndex)); |
1081 | } |
1082 | |
1083 | TEST(Matcher, ConstructorArgumentCount) { |
1084 | StatementMatcher Constructor1Arg = cxxConstructExpr(argumentCountIs(1)); |
1085 | |
1086 | EXPECT_TRUE( |
1087 | matches("class X { public: X(int); }; void x() { X x(0); }", |
1088 | Constructor1Arg)); |
1089 | EXPECT_TRUE( |
1090 | matches("class X { public: X(int); }; void x() { X x = X(0); }", |
1091 | Constructor1Arg)); |
1092 | EXPECT_TRUE( |
1093 | matches("class X { public: X(int); }; void x() { X x = 0; }", |
1094 | Constructor1Arg)); |
1095 | EXPECT_TRUE( |
1096 | notMatches("class X { public: X(int, int); }; void x() { X x(0, 0); }", |
1097 | Constructor1Arg)); |
1098 | } |
1099 | |
1100 | TEST(Matcher, ConstructorListInitialization) { |
1101 | StatementMatcher ConstructorListInit = |
1102 | cxxConstructExpr(isListInitialization()); |
1103 | |
1104 | EXPECT_TRUE( |
1105 | matches("class X { public: X(int); }; void x() { X x{0}; }", |
1106 | ConstructorListInit)); |
1107 | EXPECT_FALSE( |
1108 | matches("class X { public: X(int); }; void x() { X x(0); }", |
1109 | ConstructorListInit)); |
1110 | } |
1111 | |
1112 | TEST(ConstructorDeclaration, IsImplicit) { |
1113 | |
1114 | |
1115 | EXPECT_TRUE(notMatches("class Foo { };", |
1116 | cxxConstructorDecl(isImplicit()))); |
1117 | |
1118 | EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();", |
1119 | cxxConstructorDecl(isImplicit()))); |
1120 | EXPECT_TRUE(matches("class Foo { Foo(){} };", |
1121 | cxxConstructorDecl(unless(isImplicit())))); |
1122 | |
1123 | EXPECT_TRUE(matches("struct A { int x; } a = {0}, b = a; void f() { a = b; }", |
1124 | cxxMethodDecl(isImplicit(), hasName("operator=")))); |
1125 | } |
1126 | |
1127 | TEST(ConstructorDeclaration, IsExplicit) { |
1128 | EXPECT_TRUE(matches("struct S { explicit S(int); };", |
1129 | cxxConstructorDecl(isExplicit()))); |
1130 | EXPECT_TRUE(notMatches("struct S { S(int); };", |
1131 | cxxConstructorDecl(isExplicit()))); |
1132 | } |
1133 | |
1134 | TEST(ConstructorDeclaration, Kinds) { |
1135 | EXPECT_TRUE(matches( |
1136 | "struct S { S(); };", |
1137 | cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit())))); |
1138 | EXPECT_TRUE(notMatches( |
1139 | "struct S { S(); };", |
1140 | cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())))); |
1141 | EXPECT_TRUE(notMatches( |
1142 | "struct S { S(); };", |
1143 | cxxConstructorDecl(isMoveConstructor(), unless(isImplicit())))); |
1144 | |
1145 | EXPECT_TRUE(notMatches( |
1146 | "struct S { S(const S&); };", |
1147 | cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit())))); |
1148 | EXPECT_TRUE(matches( |
1149 | "struct S { S(const S&); };", |
1150 | cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())))); |
1151 | EXPECT_TRUE(notMatches( |
1152 | "struct S { S(const S&); };", |
1153 | cxxConstructorDecl(isMoveConstructor(), unless(isImplicit())))); |
1154 | |
1155 | EXPECT_TRUE(notMatches( |
1156 | "struct S { S(S&&); };", |
1157 | cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit())))); |
1158 | EXPECT_TRUE(notMatches( |
1159 | "struct S { S(S&&); };", |
1160 | cxxConstructorDecl(isCopyConstructor(), unless(isImplicit())))); |
1161 | EXPECT_TRUE(matches( |
1162 | "struct S { S(S&&); };", |
1163 | cxxConstructorDecl(isMoveConstructor(), unless(isImplicit())))); |
1164 | } |
1165 | |
1166 | TEST(ConstructorDeclaration, IsUserProvided) { |
1167 | EXPECT_TRUE(notMatches("struct S { int X = 0; };", |
1168 | cxxConstructorDecl(isUserProvided()))); |
1169 | EXPECT_TRUE(notMatches("struct S { S() = default; };", |
1170 | cxxConstructorDecl(isUserProvided()))); |
1171 | EXPECT_TRUE(notMatches("struct S { S() = delete; };", |
1172 | cxxConstructorDecl(isUserProvided()))); |
1173 | EXPECT_TRUE( |
1174 | matches("struct S { S(); };", cxxConstructorDecl(isUserProvided()))); |
1175 | EXPECT_TRUE(matches("struct S { S(); }; S::S(){}", |
1176 | cxxConstructorDecl(isUserProvided()))); |
1177 | } |
1178 | |
1179 | TEST(ConstructorDeclaration, IsDelegatingConstructor) { |
1180 | EXPECT_TRUE(notMatches("struct S { S(); S(int); int X; };", |
1181 | cxxConstructorDecl(isDelegatingConstructor()))); |
1182 | EXPECT_TRUE(notMatches("struct S { S(){} S(int X) : X(X) {} int X; };", |
1183 | cxxConstructorDecl(isDelegatingConstructor()))); |
1184 | EXPECT_TRUE(matches( |
1185 | "struct S { S() : S(0) {} S(int X) : X(X) {} int X; };", |
1186 | cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(0)))); |
1187 | EXPECT_TRUE(matches( |
1188 | "struct S { S(); S(int X); int X; }; S::S(int X) : S() {}", |
1189 | cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(1)))); |
1190 | } |
1191 | |
1192 | TEST(StringLiteral, HasSize) { |
1193 | StatementMatcher Literal = stringLiteral(hasSize(4)); |
1194 | EXPECT_TRUE(matches("const char *s = \"abcd\";", Literal)); |
1195 | |
1196 | EXPECT_TRUE(matches("const wchar_t *s = L\"abcd\";", Literal)); |
1197 | |
1198 | EXPECT_TRUE(matches("const char *s = \"\x05\x06\x07\x08\";", Literal)); |
1199 | |
1200 | EXPECT_TRUE(notMatches("const char *s = \"ab\";", Literal)); |
1201 | } |
1202 | |
1203 | TEST(Matcher, HasNameSupportsNamespaces) { |
1204 | EXPECT_TRUE(matches("namespace a { namespace b { class C; } }", |
1205 | recordDecl(hasName("a::b::C")))); |
1206 | EXPECT_TRUE(matches("namespace a { namespace b { class C; } }", |
1207 | recordDecl(hasName("::a::b::C")))); |
1208 | EXPECT_TRUE(matches("namespace a { namespace b { class C; } }", |
1209 | recordDecl(hasName("b::C")))); |
1210 | EXPECT_TRUE(matches("namespace a { namespace b { class C; } }", |
1211 | recordDecl(hasName("C")))); |
1212 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1213 | recordDecl(hasName("c::b::C")))); |
1214 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1215 | recordDecl(hasName("a::c::C")))); |
1216 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1217 | recordDecl(hasName("a::b::A")))); |
1218 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1219 | recordDecl(hasName("::C")))); |
1220 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1221 | recordDecl(hasName("::b::C")))); |
1222 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1223 | recordDecl(hasName("z::a::b::C")))); |
1224 | EXPECT_TRUE(notMatches("namespace a { namespace b { class C; } }", |
1225 | recordDecl(hasName("a+b::C")))); |
1226 | EXPECT_TRUE(notMatches("namespace a { namespace b { class AC; } }", |
1227 | recordDecl(hasName("C")))); |
1228 | } |
1229 | |
1230 | TEST(Matcher, HasNameSupportsOuterClasses) { |
1231 | EXPECT_TRUE( |
1232 | matches("class A { class B { class C; }; };", |
1233 | recordDecl(hasName("A::B::C")))); |
1234 | EXPECT_TRUE( |
1235 | matches("class A { class B { class C; }; };", |
1236 | recordDecl(hasName("::A::B::C")))); |
1237 | EXPECT_TRUE( |
1238 | matches("class A { class B { class C; }; };", |
1239 | recordDecl(hasName("B::C")))); |
1240 | EXPECT_TRUE( |
1241 | matches("class A { class B { class C; }; };", |
1242 | recordDecl(hasName("C")))); |
1243 | EXPECT_TRUE( |
1244 | notMatches("class A { class B { class C; }; };", |
1245 | recordDecl(hasName("c::B::C")))); |
1246 | EXPECT_TRUE( |
1247 | notMatches("class A { class B { class C; }; };", |
1248 | recordDecl(hasName("A::c::C")))); |
1249 | EXPECT_TRUE( |
1250 | notMatches("class A { class B { class C; }; };", |
1251 | recordDecl(hasName("A::B::A")))); |
1252 | EXPECT_TRUE( |
1253 | notMatches("class A { class B { class C; }; };", |
1254 | recordDecl(hasName("::C")))); |
1255 | EXPECT_TRUE( |
1256 | notMatches("class A { class B { class C; }; };", |
1257 | recordDecl(hasName("::B::C")))); |
1258 | EXPECT_TRUE(notMatches("class A { class B { class C; }; };", |
1259 | recordDecl(hasName("z::A::B::C")))); |
1260 | EXPECT_TRUE( |
1261 | notMatches("class A { class B { class C; }; };", |
1262 | recordDecl(hasName("A+B::C")))); |
1263 | } |
1264 | |
1265 | TEST(Matcher, HasNameSupportsInlinedNamespaces) { |
1266 | std::string code = "namespace a { inline namespace b { class C; } }"; |
1267 | EXPECT_TRUE(matches(code, recordDecl(hasName("a::b::C")))); |
1268 | EXPECT_TRUE(matches(code, recordDecl(hasName("a::C")))); |
1269 | EXPECT_TRUE(matches(code, recordDecl(hasName("::a::b::C")))); |
1270 | EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C")))); |
1271 | } |
1272 | |
1273 | TEST(Matcher, HasNameSupportsAnonymousNamespaces) { |
1274 | std::string code = "namespace a { namespace { class C; } }"; |
1275 | EXPECT_TRUE( |
1276 | matches(code, recordDecl(hasName("a::(anonymous namespace)::C")))); |
1277 | EXPECT_TRUE(matches(code, recordDecl(hasName("a::C")))); |
1278 | EXPECT_TRUE( |
1279 | matches(code, recordDecl(hasName("::a::(anonymous namespace)::C")))); |
1280 | EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C")))); |
1281 | } |
1282 | |
1283 | TEST(Matcher, HasNameSupportsAnonymousOuterClasses) { |
1284 | EXPECT_TRUE(matches("class A { class { class C; } x; };", |
1285 | recordDecl(hasName("A::(anonymous class)::C")))); |
1286 | EXPECT_TRUE(matches("class A { class { class C; } x; };", |
1287 | recordDecl(hasName("::A::(anonymous class)::C")))); |
1288 | EXPECT_FALSE(matches("class A { class { class C; } x; };", |
1289 | recordDecl(hasName("::A::C")))); |
1290 | EXPECT_TRUE(matches("class A { struct { class C; } x; };", |
1291 | recordDecl(hasName("A::(anonymous struct)::C")))); |
1292 | EXPECT_TRUE(matches("class A { struct { class C; } x; };", |
1293 | recordDecl(hasName("::A::(anonymous struct)::C")))); |
1294 | EXPECT_FALSE(matches("class A { struct { class C; } x; };", |
1295 | recordDecl(hasName("::A::C")))); |
1296 | } |
1297 | |
1298 | TEST(Matcher, HasNameSupportsFunctionScope) { |
1299 | std::string code = |
1300 | "namespace a { void F(int a) { struct S { int m; }; int i; } }"; |
1301 | EXPECT_TRUE(matches(code, varDecl(hasName("i")))); |
1302 | EXPECT_FALSE(matches(code, varDecl(hasName("F()::i")))); |
1303 | |
1304 | EXPECT_TRUE(matches(code, fieldDecl(hasName("m")))); |
1305 | EXPECT_TRUE(matches(code, fieldDecl(hasName("S::m")))); |
1306 | EXPECT_TRUE(matches(code, fieldDecl(hasName("F(int)::S::m")))); |
1307 | EXPECT_TRUE(matches(code, fieldDecl(hasName("a::F(int)::S::m")))); |
1308 | EXPECT_TRUE(matches(code, fieldDecl(hasName("::a::F(int)::S::m")))); |
1309 | } |
1310 | |
1311 | TEST(Matcher, HasAnyName) { |
1312 | const std::string Code = "namespace a { namespace b { class C; } }"; |
1313 | |
1314 | EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("XX", "a::b::C")))); |
1315 | EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("a::b::C", "XX")))); |
1316 | EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("XX::C", "a::b::C")))); |
1317 | EXPECT_TRUE(matches(Code, recordDecl(hasAnyName("XX", "C")))); |
1318 | |
1319 | EXPECT_TRUE(notMatches(Code, recordDecl(hasAnyName("::C", "::b::C")))); |
1320 | EXPECT_TRUE( |
1321 | matches(Code, recordDecl(hasAnyName("::C", "::b::C", "::a::b::C")))); |
1322 | |
1323 | std::vector<StringRef> Names = {"::C", "::b::C", "::a::b::C"}; |
1324 | EXPECT_TRUE(matches(Code, recordDecl(hasAnyName(Names)))); |
1325 | } |
1326 | |
1327 | TEST(Matcher, IsDefinition) { |
1328 | DeclarationMatcher DefinitionOfClassA = |
1329 | recordDecl(hasName("A"), isDefinition()); |
1330 | EXPECT_TRUE(matches("class A {};", DefinitionOfClassA)); |
1331 | EXPECT_TRUE(notMatches("class A;", DefinitionOfClassA)); |
1332 | |
1333 | DeclarationMatcher DefinitionOfVariableA = |
1334 | varDecl(hasName("a"), isDefinition()); |
1335 | EXPECT_TRUE(matches("int a;", DefinitionOfVariableA)); |
1336 | EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA)); |
1337 | |
1338 | DeclarationMatcher DefinitionOfMethodA = |
1339 | cxxMethodDecl(hasName("a"), isDefinition()); |
1340 | EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA)); |
1341 | EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA)); |
1342 | |
1343 | DeclarationMatcher DefinitionOfObjCMethodA = |
1344 | objcMethodDecl(hasName("a"), isDefinition()); |
1345 | EXPECT_TRUE(matchesObjC("@interface A @end " |
1346 | "@implementation A; -(void)a {} @end", |
1347 | DefinitionOfObjCMethodA)); |
1348 | EXPECT_TRUE(notMatchesObjC("@interface A; - (void)a; @end", |
1349 | DefinitionOfObjCMethodA)); |
1350 | } |
1351 | |
1352 | TEST(Matcher, HandlesNullQualTypes) { |
1353 | |
1354 | |
1355 | const TypeMatcher AnyType = anything(); |
1356 | |
1357 | |
1358 | |
1359 | EXPECT_TRUE(matches( |
1360 | "struct A { };" |
1361 | "template <typename T>" |
1362 | "void f(T t) {" |
1363 | " T local_t(t /* this becomes a null QualType in the AST */);" |
1364 | "}" |
1365 | "void g() {" |
1366 | " f(0);" |
1367 | "}", |
1368 | expr(hasType(TypeMatcher( |
1369 | anyOf( |
1370 | TypeMatcher(hasDeclaration(anything())), |
1371 | pointsTo(AnyType), |
1372 | references(AnyType) |
1373 | |
1374 | )))))); |
1375 | } |
1376 | |
1377 | TEST(ObjCIvarRefExprMatcher, IvarExpr) { |
1378 | std::string ObjCString = |
1379 | "@interface A @end " |
1380 | "@implementation A { A *x; } - (void) func { x = 0; } @end"; |
1381 | EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr())); |
1382 | EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr( |
1383 | hasDeclaration(namedDecl(hasName("x")))))); |
1384 | EXPECT_FALSE(matchesObjC(ObjCString, objcIvarRefExpr( |
1385 | hasDeclaration(namedDecl(hasName("y")))))); |
1386 | } |
1387 | |
1388 | TEST(BlockExprMatcher, BlockExpr) { |
1389 | EXPECT_TRUE(matchesObjC("void f() { ^{}(); }", blockExpr())); |
1390 | } |
1391 | |
1392 | TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) { |
1393 | EXPECT_TRUE(matches("void f() { }", |
1394 | compoundStmt(statementCountIs(0)))); |
1395 | EXPECT_TRUE(notMatches("void f() {}", |
1396 | compoundStmt(statementCountIs(1)))); |
1397 | } |
1398 | |
1399 | TEST(StatementCountIs, AppearsToMatchOnlyOneCount) { |
1400 | EXPECT_TRUE(matches("void f() { 1; }", |
1401 | compoundStmt(statementCountIs(1)))); |
1402 | EXPECT_TRUE(notMatches("void f() { 1; }", |
1403 | compoundStmt(statementCountIs(0)))); |
1404 | EXPECT_TRUE(notMatches("void f() { 1; }", |
1405 | compoundStmt(statementCountIs(2)))); |
1406 | } |
1407 | |
1408 | TEST(StatementCountIs, WorksWithMultipleStatements) { |
1409 | EXPECT_TRUE(matches("void f() { 1; 2; 3; }", |
1410 | compoundStmt(statementCountIs(3)))); |
1411 | } |
1412 | |
1413 | TEST(StatementCountIs, WorksWithNestedCompoundStatements) { |
1414 | EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }", |
1415 | compoundStmt(statementCountIs(1)))); |
1416 | EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }", |
1417 | compoundStmt(statementCountIs(2)))); |
1418 | EXPECT_TRUE(notMatches("void f() { { 1; } { 1; 2; 3; 4; } }", |
1419 | compoundStmt(statementCountIs(3)))); |
1420 | EXPECT_TRUE(matches("void f() { { 1; } { 1; 2; 3; 4; } }", |
1421 | compoundStmt(statementCountIs(4)))); |
1422 | } |
1423 | |
1424 | TEST(Member, WorksInSimplestCase) { |
1425 | EXPECT_TRUE(matches("struct { int first; } s; int i(s.first);", |
1426 | memberExpr(member(hasName("first"))))); |
1427 | } |
1428 | |
1429 | TEST(Member, DoesNotMatchTheBaseExpression) { |
1430 | |
1431 | |
1432 | EXPECT_TRUE(notMatches("struct { int i; } first; int i(first.i);", |
1433 | memberExpr(member(hasName("first"))))); |
1434 | } |
1435 | |
1436 | TEST(Member, MatchesInMemberFunctionCall) { |
1437 | EXPECT_TRUE(matches("void f() {" |
1438 | " struct { void first() {}; } s;" |
1439 | " s.first();" |
1440 | "};", |
1441 | memberExpr(member(hasName("first"))))); |
1442 | } |
1443 | |
1444 | TEST(Member, MatchesMember) { |
1445 | EXPECT_TRUE(matches( |
1446 | "struct A { int i; }; void f() { A a; a.i = 2; }", |
1447 | memberExpr(hasDeclaration(fieldDecl(hasType(isInteger())))))); |
1448 | EXPECT_TRUE(notMatches( |
1449 | "struct A { float f; }; void f() { A a; a.f = 2.0f; }", |
1450 | memberExpr(hasDeclaration(fieldDecl(hasType(isInteger())))))); |
1451 | } |
1452 | |
1453 | TEST(Member, BitFields) { |
1454 | EXPECT_TRUE(matches("class C { int a : 2; int b; };", |
1455 | fieldDecl(isBitField(), hasName("a")))); |
1456 | EXPECT_TRUE(notMatches("class C { int a : 2; int b; };", |
1457 | fieldDecl(isBitField(), hasName("b")))); |
1458 | EXPECT_TRUE(matches("class C { int a : 2; int b : 4; };", |
1459 | fieldDecl(isBitField(), hasBitWidth(2), hasName("a")))); |
1460 | } |
1461 | |
1462 | TEST(Member, InClassInitializer) { |
1463 | EXPECT_TRUE( |
1464 | matches("class C { int a = 2; int b; };", |
1465 | fieldDecl(hasInClassInitializer(integerLiteral(equals(2))), |
1466 | hasName("a")))); |
1467 | EXPECT_TRUE( |
1468 | notMatches("class C { int a = 2; int b; };", |
1469 | fieldDecl(hasInClassInitializer(anything()), hasName("b")))); |
1470 | } |
1471 | |
1472 | TEST(Member, UnderstandsAccess) { |
1473 | EXPECT_TRUE(matches( |
1474 | "struct A { int i; };", fieldDecl(isPublic(), hasName("i")))); |
1475 | EXPECT_TRUE(notMatches( |
1476 | "struct A { int i; };", fieldDecl(isProtected(), hasName("i")))); |
1477 | EXPECT_TRUE(notMatches( |
1478 | "struct A { int i; };", fieldDecl(isPrivate(), hasName("i")))); |
1479 | |
1480 | EXPECT_TRUE(notMatches( |
1481 | "class A { int i; };", fieldDecl(isPublic(), hasName("i")))); |
1482 | EXPECT_TRUE(notMatches( |
1483 | "class A { int i; };", fieldDecl(isProtected(), hasName("i")))); |
1484 | EXPECT_TRUE(matches( |
1485 | "class A { int i; };", fieldDecl(isPrivate(), hasName("i")))); |
1486 | |
1487 | EXPECT_TRUE(notMatches( |
1488 | "class A { protected: int i; };", fieldDecl(isPublic(), hasName("i")))); |
1489 | EXPECT_TRUE(matches("class A { protected: int i; };", |
1490 | fieldDecl(isProtected(), hasName("i")))); |
1491 | EXPECT_TRUE(notMatches( |
1492 | "class A { protected: int i; };", fieldDecl(isPrivate(), hasName("i")))); |
1493 | |
1494 | |
1495 | EXPECT_TRUE(notMatches("int i;", varDecl(isPublic(), hasName("i")))); |
1496 | EXPECT_TRUE(notMatches("int i;", varDecl(isProtected(), hasName("i")))); |
1497 | EXPECT_TRUE(notMatches("int i;", varDecl(isPrivate(), hasName("i")))); |
1498 | } |
1499 | |
1500 | TEST(hasDynamicExceptionSpec, MatchesDynamicExceptionSpecifications) { |
1501 | EXPECT_TRUE(notMatches("void f();", functionDecl(hasDynamicExceptionSpec()))); |
1502 | EXPECT_TRUE(notMatches("void g() noexcept;", |
1503 | functionDecl(hasDynamicExceptionSpec()))); |
1504 | EXPECT_TRUE(notMatches("void h() noexcept(true);", |
1505 | functionDecl(hasDynamicExceptionSpec()))); |
1506 | EXPECT_TRUE(notMatches("void i() noexcept(false);", |
1507 | functionDecl(hasDynamicExceptionSpec()))); |
1508 | EXPECT_TRUE( |
1509 | matches("void j() throw();", functionDecl(hasDynamicExceptionSpec()))); |
1510 | EXPECT_TRUE( |
1511 | matches("void k() throw(int);", functionDecl(hasDynamicExceptionSpec()))); |
1512 | EXPECT_TRUE( |
1513 | matches("void l() throw(...);", functionDecl(hasDynamicExceptionSpec()))); |
1514 | |
1515 | EXPECT_TRUE(notMatches("void f();", functionProtoType(hasDynamicExceptionSpec()))); |
1516 | EXPECT_TRUE(notMatches("void g() noexcept;", |
1517 | functionProtoType(hasDynamicExceptionSpec()))); |
1518 | EXPECT_TRUE(notMatches("void h() noexcept(true);", |
1519 | functionProtoType(hasDynamicExceptionSpec()))); |
1520 | EXPECT_TRUE(notMatches("void i() noexcept(false);", |
1521 | functionProtoType(hasDynamicExceptionSpec()))); |
1522 | EXPECT_TRUE( |
1523 | matches("void j() throw();", functionProtoType(hasDynamicExceptionSpec()))); |
1524 | EXPECT_TRUE( |
1525 | matches("void k() throw(int);", functionProtoType(hasDynamicExceptionSpec()))); |
1526 | EXPECT_TRUE( |
1527 | matches("void l() throw(...);", functionProtoType(hasDynamicExceptionSpec()))); |
1528 | } |
1529 | |
1530 | TEST(HasObjectExpression, DoesNotMatchMember) { |
1531 | EXPECT_TRUE(notMatches( |
1532 | "class X {}; struct Z { X m; }; void f(Z z) { z.m; }", |
1533 | memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))); |
1534 | } |
1535 | |
1536 | TEST(HasObjectExpression, MatchesBaseOfVariable) { |
1537 | EXPECT_TRUE(matches( |
1538 | "struct X { int m; }; void f(X x) { x.m; }", |
1539 | memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))); |
1540 | EXPECT_TRUE(matches( |
1541 | "struct X { int m; }; void f(X* x) { x->m; }", |
1542 | memberExpr(hasObjectExpression( |
1543 | hasType(pointsTo(recordDecl(hasName("X")))))))); |
1544 | EXPECT_TRUE(matches("template <class T> struct X { void f() { T t; t.m; } };", |
1545 | cxxDependentScopeMemberExpr(hasObjectExpression( |
1546 | declRefExpr(to(namedDecl(hasName("t")))))))); |
1547 | EXPECT_TRUE( |
1548 | matches("template <class T> struct X { void f() { T t; t->m; } };", |
1549 | cxxDependentScopeMemberExpr(hasObjectExpression( |
1550 | declRefExpr(to(namedDecl(hasName("t")))))))); |
1551 | } |
1552 | |
1553 | TEST(HasObjectExpression, MatchesBaseOfMemberFunc) { |
1554 | EXPECT_TRUE(matches( |
1555 | "struct X { void f(); }; void g(X x) { x.f(); }", |
1556 | memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X"))))))); |
1557 | EXPECT_TRUE(matches("struct X { template <class T> void f(); };" |
1558 | "template <class T> void g(X x) { x.f<T>(); }", |
1559 | unresolvedMemberExpr(hasObjectExpression( |
1560 | hasType(recordDecl(hasName("X"))))))); |
1561 | EXPECT_TRUE(matches("template <class T> void f(T t) { t.g(); }", |
1562 | cxxDependentScopeMemberExpr(hasObjectExpression( |
1563 | declRefExpr(to(namedDecl(hasName("t")))))))); |
1564 | } |
1565 | |
1566 | TEST(HasObjectExpression, |
1567 | MatchesObjectExpressionOfImplicitlyFormedMemberExpression) { |
1568 | EXPECT_TRUE(matches( |
1569 | "class X {}; struct S { X m; void f() { this->m; } };", |
1570 | memberExpr(hasObjectExpression( |
1571 | hasType(pointsTo(recordDecl(hasName("S")))))))); |
1572 | EXPECT_TRUE(matches( |
1573 | "class X {}; struct S { X m; void f() { m; } };", |
1574 | memberExpr(hasObjectExpression( |
1575 | hasType(pointsTo(recordDecl(hasName("S")))))))); |
1576 | } |
1577 | |
1578 | TEST(Field, DoesNotMatchNonFieldMembers) { |
1579 | EXPECT_TRUE(notMatches("class X { void m(); };", fieldDecl(hasName("m")))); |
1580 | EXPECT_TRUE(notMatches("class X { class m {}; };", fieldDecl(hasName("m")))); |
1581 | EXPECT_TRUE(notMatches("class X { enum { m }; };", fieldDecl(hasName("m")))); |
1582 | EXPECT_TRUE(notMatches("class X { enum m {}; };", fieldDecl(hasName("m")))); |
1583 | } |
1584 | |
1585 | TEST(Field, MatchesField) { |
1586 | EXPECT_TRUE(matches("class X { int m; };", fieldDecl(hasName("m")))); |
1587 | } |
1588 | |
1589 | TEST(IsVolatileQualified, QualifiersMatch) { |
1590 | EXPECT_TRUE(matches("volatile int i = 42;", |
1591 | varDecl(hasType(isVolatileQualified())))); |
1592 | EXPECT_TRUE(notMatches("volatile int *i;", |
1593 | varDecl(hasType(isVolatileQualified())))); |
1594 | EXPECT_TRUE(matches("typedef volatile int v_int; v_int i = 42;", |
1595 | varDecl(hasType(isVolatileQualified())))); |
1596 | } |
1597 | |
1598 | TEST(IsConstQualified, MatchesConstInt) { |
1599 | EXPECT_TRUE(matches("const int i = 42;", |
1600 | varDecl(hasType(isConstQualified())))); |
1601 | } |
1602 | |
1603 | TEST(IsConstQualified, MatchesConstPointer) { |
1604 | EXPECT_TRUE(matches("int i = 42; int* const p(&i);", |
1605 | varDecl(hasType(isConstQualified())))); |
1606 | } |
1607 | |
1608 | TEST(IsConstQualified, MatchesThroughTypedef) { |
1609 | EXPECT_TRUE(matches("typedef const int const_int; const_int i = 42;", |
1610 | varDecl(hasType(isConstQualified())))); |
1611 | EXPECT_TRUE(matches("typedef int* int_ptr; const int_ptr p(0);", |
1612 | varDecl(hasType(isConstQualified())))); |
1613 | } |
1614 | |
1615 | TEST(IsConstQualified, DoesNotMatchInappropriately) { |
1616 | EXPECT_TRUE(notMatches("typedef int nonconst_int; nonconst_int i = 42;", |
1617 | varDecl(hasType(isConstQualified())))); |
1618 | EXPECT_TRUE(notMatches("int const* p;", |
1619 | varDecl(hasType(isConstQualified())))); |
1620 | } |
1621 | |
1622 | TEST(DeclCount, DeclCountIsCorrect) { |
1623 | EXPECT_TRUE(matches("void f() {int i,j;}", |
1624 | declStmt(declCountIs(2)))); |
1625 | EXPECT_TRUE(notMatches("void f() {int i,j; int k;}", |
1626 | declStmt(declCountIs(3)))); |
1627 | EXPECT_TRUE(notMatches("void f() {int i,j, k, l;}", |
1628 | declStmt(declCountIs(3)))); |
1629 | } |
1630 | |
1631 | |
1632 | TEST(EachOf, TriggersForEachMatch) { |
1633 | EXPECT_TRUE(matchAndVerifyResultTrue( |
1634 | "class A { int a; int b; };", |
1635 | recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), |
1636 | has(fieldDecl(hasName("b")).bind("v")))), |
1637 | llvm::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 2))); |
1638 | } |
1639 | |
1640 | TEST(EachOf, BehavesLikeAnyOfUnlessBothMatch) { |
1641 | EXPECT_TRUE(matchAndVerifyResultTrue( |
1642 | "class A { int a; int c; };", |
1643 | recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), |
1644 | has(fieldDecl(hasName("b")).bind("v")))), |
1645 | llvm::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 1))); |
1646 | EXPECT_TRUE(matchAndVerifyResultTrue( |
1647 | "class A { int c; int b; };", |
1648 | recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), |
1649 | has(fieldDecl(hasName("b")).bind("v")))), |
1650 | llvm::make_unique<VerifyIdIsBoundTo<FieldDecl>>("v", 1))); |
1651 | EXPECT_TRUE(notMatches( |
1652 | "class A { int c; int d; };", |
1653 | recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), |
1654 | has(fieldDecl(hasName("b")).bind("v")))))); |
1655 | } |
1656 | |
1657 | TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) { |
1658 | |
1659 | |
1660 | |
1661 | EXPECT_TRUE(matches( |
1662 | "template <typename T> class X {}; class A {}; X<A> x;", |
1663 | cxxRecordDecl(hasName("::X"), isTemplateInstantiation()))); |
1664 | |
1665 | EXPECT_TRUE(matches( |
1666 | "template <typename T> class X { T t; }; class A {}; X<A> x;", |
1667 | cxxRecordDecl(isTemplateInstantiation(), hasDescendant( |
1668 | fieldDecl(hasType(recordDecl(hasName("A")))))))); |
1669 | } |
1670 | |
1671 | TEST(IsTemplateInstantiation, MatchesImplicitFunctionTemplateInstantiation) { |
1672 | EXPECT_TRUE(matches( |
1673 | "template <typename T> void f(T t) {} class A {}; void g() { f(A()); }", |
1674 | functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))), |
1675 | isTemplateInstantiation()))); |
1676 | } |
1677 | |
1678 | TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) { |
1679 | EXPECT_TRUE(matches( |
1680 | "template <typename T> class X { T t; }; class A {};" |
1681 | "template class X<A>;", |
1682 | cxxRecordDecl(isTemplateInstantiation(), hasDescendant( |
1683 | fieldDecl(hasType(recordDecl(hasName("A")))))))); |
1684 | |
1685 | |
1686 | |
1687 | EXPECT_TRUE( |
1688 | matches("template <typename T> class X { void f() { T t; } };" |
1689 | "extern template class X<int>;", |
1690 | cxxRecordDecl(isTemplateInstantiation(), |
1691 | unless(hasDescendant(varDecl(hasName("t"))))))); |
1692 | } |
1693 | |
1694 | TEST(IsTemplateInstantiation, |
1695 | MatchesInstantiationOfPartiallySpecializedClassTemplate) { |
1696 | EXPECT_TRUE(matches( |
1697 | "template <typename T> class X {};" |
1698 | "template <typename T> class X<T*> {}; class A {}; X<A*> x;", |
1699 | cxxRecordDecl(hasName("::X"), isTemplateInstantiation()))); |
1700 | } |
1701 | |
1702 | TEST(IsTemplateInstantiation, |
1703 | MatchesInstantiationOfClassTemplateNestedInNonTemplate) { |
1704 | EXPECT_TRUE(matches( |
1705 | "class A {};" |
1706 | "class X {" |
1707 | " template <typename U> class Y { U u; };" |
1708 | " Y<A> y;" |
1709 | "};", |
1710 | cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation()))); |
1711 | } |
1712 | |
1713 | TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) { |
1714 | |
1715 | |
1716 | |
1717 | EXPECT_TRUE(matches( |
1718 | "class A {};" |
1719 | "template <typename T> class X {" |
1720 | " template <typename U> class Y { U u; };" |
1721 | " Y<T> y;" |
1722 | "}; X<A> x;", |
1723 | cxxRecordDecl(hasName("::X<A>::Y"), unless(isTemplateInstantiation())))); |
1724 | } |
1725 | |
1726 | TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) { |
1727 | EXPECT_TRUE(notMatches( |
1728 | "template <typename T> class X {}; class A {};" |
1729 | "template <> class X<A> {}; X<A> x;", |
1730 | cxxRecordDecl(hasName("::X"), isTemplateInstantiation()))); |
1731 | } |
1732 | |
1733 | TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) { |
1734 | EXPECT_TRUE(notMatches( |
1735 | "class A {}; class Y { A a; };", |
1736 | cxxRecordDecl(isTemplateInstantiation()))); |
1737 | } |
1738 | |
1739 | TEST(IsInstantiated, MatchesInstantiation) { |
1740 | EXPECT_TRUE( |
1741 | matches("template<typename T> class A { T i; }; class Y { A<int> a; };", |
1742 | cxxRecordDecl(isInstantiated()))); |
1743 | } |
1744 | |
1745 | TEST(IsInstantiated, NotMatchesDefinition) { |
1746 | EXPECT_TRUE(notMatches("template<typename T> class A { T i; };", |
1747 | cxxRecordDecl(isInstantiated()))); |
1748 | } |
1749 | |
1750 | TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) { |
1751 | EXPECT_TRUE(matches("template<typename T> struct A { A() { T i; } };" |
1752 | "class Y { A<int> a; }; Y y;", |
1753 | declStmt(isInTemplateInstantiation()))); |
1754 | } |
1755 | |
1756 | TEST(IsInTemplateInstantiation, NotMatchesDefinitionStmt) { |
1757 | EXPECT_TRUE(notMatches("template<typename T> struct A { void x() { T i; } };", |
1758 | declStmt(isInTemplateInstantiation()))); |
1759 | } |
1760 | |
1761 | TEST(IsInstantiated, MatchesFunctionInstantiation) { |
1762 | EXPECT_TRUE( |
1763 | matches("template<typename T> void A(T t) { T i; } void x() { A(0); }", |
1764 | functionDecl(isInstantiated()))); |
1765 | } |
1766 | |
1767 | TEST(IsInstantiated, NotMatchesFunctionDefinition) { |
1768 | EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }", |
1769 | varDecl(isInstantiated()))); |
1770 | } |
1771 | |
1772 | TEST(IsInTemplateInstantiation, MatchesFunctionInstantiationStmt) { |
1773 | EXPECT_TRUE( |
1774 | matches("template<typename T> void A(T t) { T i; } void x() { A(0); }", |
1775 | declStmt(isInTemplateInstantiation()))); |
1776 | } |
1777 | |
1778 | TEST(IsInTemplateInstantiation, NotMatchesFunctionDefinitionStmt) { |
1779 | EXPECT_TRUE(notMatches("template<typename T> void A(T t) { T i; }", |
1780 | declStmt(isInTemplateInstantiation()))); |
1781 | } |
1782 | |
1783 | TEST(IsInTemplateInstantiation, Sharing) { |
1784 | auto Matcher = binaryOperator(unless(isInTemplateInstantiation())); |
1785 | |
1786 | |
1787 | EXPECT_TRUE(notMatches( |
1788 | "int j; template<typename T> void A(T t) { j += 42; } void x() { A(0); }", |
1789 | Matcher)); |
1790 | EXPECT_TRUE(matches( |
1791 | "int j; template<typename T> void A(T t) { j += t; } void x() { A(0); }", |
1792 | Matcher)); |
1793 | } |
1794 | |
1795 | TEST(IsInstantiationDependent, MatchesNonValueTypeDependent) { |
1796 | EXPECT_TRUE(matches( |
1797 | "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }", |
1798 | expr(isInstantiationDependent()))); |
1799 | } |
1800 | |
1801 | TEST(IsInstantiationDependent, MatchesValueDependent) { |
1802 | EXPECT_TRUE(matches("template<int T> int f() { return T; }", |
1803 | expr(isInstantiationDependent()))); |
1804 | } |
1805 | |
1806 | TEST(IsInstantiationDependent, MatchesTypeDependent) { |
1807 | EXPECT_TRUE(matches("template<typename T> T f() { return T(); }", |
1808 | expr(isInstantiationDependent()))); |
1809 | } |
1810 | |
1811 | TEST(IsTypeDependent, MatchesTypeDependent) { |
1812 | EXPECT_TRUE(matches("template<typename T> T f() { return T(); }", |
1813 | expr(isTypeDependent()))); |
1814 | } |
1815 | |
1816 | TEST(IsTypeDependent, NotMatchesValueDependent) { |
1817 | EXPECT_TRUE(notMatches("template<int T> int f() { return T; }", |
1818 | expr(isTypeDependent()))); |
1819 | } |
1820 | |
1821 | TEST(IsValueDependent, MatchesValueDependent) { |
1822 | EXPECT_TRUE(matches("template<int T> int f() { return T; }", |
1823 | expr(isValueDependent()))); |
1824 | } |
1825 | |
1826 | TEST(IsValueDependent, MatchesTypeDependent) { |
1827 | EXPECT_TRUE(matches("template<typename T> T f() { return T(); }", |
1828 | expr(isValueDependent()))); |
1829 | } |
1830 | |
1831 | TEST(IsValueDependent, MatchesInstantiationDependent) { |
1832 | EXPECT_TRUE(matches( |
1833 | "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }", |
1834 | expr(isValueDependent()))); |
1835 | } |
1836 | |
1837 | TEST(IsExplicitTemplateSpecialization, |
1838 | DoesNotMatchPrimaryTemplate) { |
1839 | EXPECT_TRUE(notMatches( |
1840 | "template <typename T> class X {};", |
1841 | cxxRecordDecl(isExplicitTemplateSpecialization()))); |
1842 | EXPECT_TRUE(notMatches( |
1843 | "template <typename T> void f(T t);", |
1844 | functionDecl(isExplicitTemplateSpecialization()))); |
1845 | } |
1846 | |
1847 | TEST(IsExplicitTemplateSpecialization, |
1848 | DoesNotMatchExplicitTemplateInstantiations) { |
1849 | EXPECT_TRUE(notMatches( |
1850 | "template <typename T> class X {};" |
1851 | "template class X<int>; extern template class X<long>;", |
1852 | cxxRecordDecl(isExplicitTemplateSpecialization()))); |
1853 | EXPECT_TRUE(notMatches( |
1854 | "template <typename T> void f(T t) {}" |
1855 | "template void f(int t); extern template void f(long t);", |
1856 | functionDecl(isExplicitTemplateSpecialization()))); |
1857 | } |
1858 | |
1859 | TEST(IsExplicitTemplateSpecialization, |
1860 | DoesNotMatchImplicitTemplateInstantiations) { |
1861 | EXPECT_TRUE(notMatches( |
1862 | "template <typename T> class X {}; X<int> x;", |
1863 | cxxRecordDecl(isExplicitTemplateSpecialization()))); |
1864 | EXPECT_TRUE(notMatches( |
1865 | "template <typename T> void f(T t); void g() { f(10); }", |
1866 | functionDecl(isExplicitTemplateSpecialization()))); |
1867 | } |
1868 | |
1869 | TEST(IsExplicitTemplateSpecialization, |
1870 | MatchesExplicitTemplateSpecializations) { |
1871 | EXPECT_TRUE(matches( |
1872 | "template <typename T> class X {};" |
1873 | "template<> class X<int> {};", |
1874 | cxxRecordDecl(isExplicitTemplateSpecialization()))); |
1875 | EXPECT_TRUE(matches( |
1876 | "template <typename T> void f(T t) {}" |
1877 | "template<> void f(int t) {}", |
1878 | functionDecl(isExplicitTemplateSpecialization()))); |
1879 | } |
1880 | |
1881 | TEST(TypeMatching, MatchesNoReturn) { |
1882 | EXPECT_TRUE(notMatches("void func();", functionDecl(isNoReturn()))); |
1883 | EXPECT_TRUE(notMatches("void func() {}", functionDecl(isNoReturn()))); |
1884 | |
1885 | EXPECT_TRUE(notMatchesC("void func();", functionDecl(isNoReturn()))); |
1886 | EXPECT_TRUE(notMatchesC("void func() {}", functionDecl(isNoReturn()))); |
1887 | |
1888 | EXPECT_TRUE( |
1889 | notMatches("struct S { void func(); };", functionDecl(isNoReturn()))); |
1890 | EXPECT_TRUE( |
1891 | notMatches("struct S { void func() {} };", functionDecl(isNoReturn()))); |
1892 | |
1893 | EXPECT_TRUE(notMatches("struct S { static void func(); };", |
1894 | functionDecl(isNoReturn()))); |
1895 | EXPECT_TRUE(notMatches("struct S { static void func() {} };", |
1896 | functionDecl(isNoReturn()))); |
1897 | |
1898 | EXPECT_TRUE(notMatches("struct S { S(); };", functionDecl(isNoReturn()))); |
1899 | EXPECT_TRUE(notMatches("struct S { S() {} };", functionDecl(isNoReturn()))); |
1900 | |
1901 | |
1902 | |
1903 | EXPECT_TRUE(matches("[[noreturn]] void func();", functionDecl(isNoReturn()))); |
1904 | EXPECT_TRUE( |
1905 | matches("[[noreturn]] void func() {}", functionDecl(isNoReturn()))); |
1906 | |
1907 | EXPECT_TRUE(matches("struct S { [[noreturn]] void func(); };", |
1908 | functionDecl(isNoReturn()))); |
1909 | EXPECT_TRUE(matches("struct S { [[noreturn]] void func() {} };", |
1910 | functionDecl(isNoReturn()))); |
1911 | |
1912 | EXPECT_TRUE(matches("struct S { [[noreturn]] static void func(); };", |
1913 | functionDecl(isNoReturn()))); |
1914 | EXPECT_TRUE(matches("struct S { [[noreturn]] static void func() {} };", |
1915 | functionDecl(isNoReturn()))); |
1916 | |
1917 | EXPECT_TRUE( |
1918 | matches("struct S { [[noreturn]] S(); };", functionDecl(isNoReturn()))); |
1919 | EXPECT_TRUE(matches("struct S { [[noreturn]] S() {} };", |
1920 | functionDecl(isNoReturn()))); |
1921 | |
1922 | |
1923 | |
1924 | EXPECT_TRUE(matches("__attribute__((noreturn)) void func();", |
1925 | functionDecl(isNoReturn()))); |
1926 | EXPECT_TRUE(matches("__attribute__((noreturn)) void func() {}", |
1927 | functionDecl(isNoReturn()))); |
1928 | |
1929 | EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func(); };", |
1930 | functionDecl(isNoReturn()))); |
1931 | EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) void func() {} };", |
1932 | functionDecl(isNoReturn()))); |
1933 | |
1934 | EXPECT_TRUE( |
1935 | matches("struct S { __attribute__((noreturn)) static void func(); };", |
1936 | functionDecl(isNoReturn()))); |
1937 | EXPECT_TRUE( |
1938 | matches("struct S { __attribute__((noreturn)) static void func() {} };", |
1939 | functionDecl(isNoReturn()))); |
1940 | |
1941 | EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S(); };", |
1942 | functionDecl(isNoReturn()))); |
1943 | EXPECT_TRUE(matches("struct S { __attribute__((noreturn)) S() {} };", |
1944 | functionDecl(isNoReturn()))); |
1945 | |
1946 | |
1947 | |
1948 | EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func();", |
1949 | functionDecl(isNoReturn()))); |
1950 | EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func() {}", |
1951 | functionDecl(isNoReturn()))); |
1952 | |
1953 | EXPECT_TRUE(matchesC("_Noreturn void func();", |
1954 | functionDecl(isNoReturn()))); |
1955 | EXPECT_TRUE(matchesC("_Noreturn void func() {}", |
1956 | functionDecl(isNoReturn()))); |
1957 | } |
1958 | |
1959 | TEST(TypeMatching, MatchesBool) { |
1960 | EXPECT_TRUE(matches("struct S { bool func(); };", |
1961 | cxxMethodDecl(returns(booleanType())))); |
1962 | EXPECT_TRUE(notMatches("struct S { void func(); };", |
1963 | cxxMethodDecl(returns(booleanType())))); |
1964 | } |
1965 | |
1966 | TEST(TypeMatching, MatchesVoid) { |
1967 | EXPECT_TRUE(matches("struct S { void func(); };", |
1968 | cxxMethodDecl(returns(voidType())))); |
1969 | } |
1970 | |
1971 | TEST(TypeMatching, MatchesRealFloats) { |
1972 | EXPECT_TRUE(matches("struct S { float func(); };", |
1973 | cxxMethodDecl(returns(realFloatingPointType())))); |
1974 | EXPECT_TRUE(notMatches("struct S { int func(); };", |
1975 | cxxMethodDecl(returns(realFloatingPointType())))); |
1976 | EXPECT_TRUE(matches("struct S { long double func(); };", |
1977 | cxxMethodDecl(returns(realFloatingPointType())))); |
1978 | } |
1979 | |
1980 | TEST(TypeMatching, MatchesArrayTypes) { |
1981 | EXPECT_TRUE(matches("int a[] = {2,3};", arrayType())); |
1982 | EXPECT_TRUE(matches("int a[42];", arrayType())); |
1983 | EXPECT_TRUE(matches("void f(int b) { int a[b]; }", arrayType())); |
1984 | |
1985 | EXPECT_TRUE(notMatches("struct A {}; A a[7];", |
1986 | arrayType(hasElementType(builtinType())))); |
1987 | |
1988 | EXPECT_TRUE(matches( |
1989 | "int const a[] = { 2, 3 };", |
1990 | qualType(arrayType(hasElementType(builtinType()))))); |
1991 | EXPECT_TRUE(matches( |
1992 | "int const a[] = { 2, 3 };", |
1993 | qualType(isConstQualified(), arrayType(hasElementType(builtinType()))))); |
1994 | EXPECT_TRUE(matches( |
1995 | "typedef const int T; T x[] = { 1, 2 };", |
1996 | qualType(isConstQualified(), arrayType()))); |
1997 | |
1998 | EXPECT_TRUE(notMatches( |
1999 | "int a[] = { 2, 3 };", |
2000 | qualType(isConstQualified(), arrayType(hasElementType(builtinType()))))); |
2001 | EXPECT_TRUE(notMatches( |
2002 | "int a[] = { 2, 3 };", |
2003 | qualType(arrayType(hasElementType(isConstQualified(), builtinType()))))); |
2004 | EXPECT_TRUE(notMatches( |
2005 | "int const a[] = { 2, 3 };", |
2006 | qualType(arrayType(hasElementType(builtinType())), |
2007 | unless(isConstQualified())))); |
2008 | |
2009 | EXPECT_TRUE(matches("int a[2];", |
2010 | constantArrayType(hasElementType(builtinType())))); |
2011 | EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger()))); |
2012 | } |
2013 | |
2014 | TEST(TypeMatching, DecayedType) { |
2015 | EXPECT_TRUE(matches("void f(int i[]);", valueDecl(hasType(decayedType(hasDecayedType(pointerType())))))); |
2016 | EXPECT_TRUE(notMatches("int i[7];", decayedType())); |
2017 | } |
2018 | |
2019 | TEST(TypeMatching, MatchesComplexTypes) { |
2020 | EXPECT_TRUE(matches("_Complex float f;", complexType())); |
2021 | EXPECT_TRUE(matches( |
2022 | "_Complex float f;", |
2023 | complexType(hasElementType(builtinType())))); |
2024 | EXPECT_TRUE(notMatches( |
2025 | "_Complex float f;", |
2026 | complexType(hasElementType(isInteger())))); |
2027 | } |
2028 | |
2029 | TEST(NS, Anonymous) { |
2030 | EXPECT_TRUE(notMatches("namespace N {}", namespaceDecl(isAnonymous()))); |
2031 | EXPECT_TRUE(matches("namespace {}", namespaceDecl(isAnonymous()))); |
2032 | } |
2033 | |
2034 | TEST(EqualsBoundNodeMatcher, QualType) { |
2035 | EXPECT_TRUE(matches( |
2036 | "int i = 1;", varDecl(hasType(qualType().bind("type")), |
2037 | hasInitializer(ignoringParenImpCasts( |
2038 | hasType(qualType(equalsBoundNode("type")))))))); |
2039 | EXPECT_TRUE(notMatches("int i = 1.f;", |
2040 | varDecl(hasType(qualType().bind("type")), |
2041 | hasInitializer(ignoringParenImpCasts(hasType( |
2042 | qualType(equalsBoundNode("type")))))))); |
2043 | } |
2044 | |
2045 | TEST(EqualsBoundNodeMatcher, NonMatchingTypes) { |
2046 | EXPECT_TRUE(notMatches( |
2047 | "int i = 1;", varDecl(namedDecl(hasName("i")).bind("name"), |
2048 | hasInitializer(ignoringParenImpCasts( |
2049 | hasType(qualType(equalsBoundNode("type")))))))); |
2050 | } |
2051 | |
2052 | TEST(EqualsBoundNodeMatcher, Stmt) { |
2053 | EXPECT_TRUE( |
2054 | matches("void f() { if(true) {} }", |
2055 | stmt(allOf(ifStmt().bind("if"), |
2056 | hasParent(stmt(has(stmt(equalsBoundNode("if"))))))))); |
2057 | |
2058 | EXPECT_TRUE(notMatches( |
2059 | "void f() { if(true) { if (true) {} } }", |
2060 | stmt(allOf(ifStmt().bind("if"), has(stmt(equalsBoundNode("if"))))))); |
2061 | } |
2062 | |
2063 | TEST(EqualsBoundNodeMatcher, Decl) { |
2064 | EXPECT_TRUE(matches( |
2065 | "class X { class Y {}; };", |
2066 | decl(allOf(recordDecl(hasName("::X::Y")).bind("record"), |
2067 | hasParent(decl(has(decl(equalsBoundNode("record"))))))))); |
2068 | |
2069 | EXPECT_TRUE(notMatches("class X { class Y {}; };", |
2070 | decl(allOf(recordDecl(hasName("::X")).bind("record"), |
2071 | has(decl(equalsBoundNode("record"))))))); |
2072 | } |
2073 | |
2074 | TEST(EqualsBoundNodeMatcher, Type) { |
2075 | EXPECT_TRUE(matches( |
2076 | "class X { int a; int b; };", |
2077 | recordDecl( |
2078 | has(fieldDecl(hasName("a"), hasType(type().bind("t")))), |
2079 | has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t")))))))); |
2080 | |
2081 | EXPECT_TRUE(notMatches( |
2082 | "class X { int a; double b; };", |
2083 | recordDecl( |
2084 | has(fieldDecl(hasName("a"), hasType(type().bind("t")))), |
2085 | has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t")))))))); |
2086 | } |
2087 | |
2088 | TEST(EqualsBoundNodeMatcher, UsingForEachDescendant) { |
2089 | EXPECT_TRUE(matchAndVerifyResultTrue( |
2090 | "int f() {" |
2091 | " if (1) {" |
2092 | " int i = 9;" |
2093 | " }" |
2094 | " int j = 10;" |
2095 | " {" |
2096 | " float k = 9.0;" |
2097 | " }" |
2098 | " return 0;" |
2099 | "}", |
2100 | |
2101 | |
2102 | functionDecl(returns(qualType().bind("type")), |
2103 | forEachDescendant(varDecl(hasType( |
2104 | qualType(equalsBoundNode("type")))).bind("decl"))), |
2105 | |
2106 | llvm::make_unique<VerifyIdIsBoundTo<VarDecl>>("decl", 2))); |
2107 | } |
2108 | |
2109 | TEST(EqualsBoundNodeMatcher, FiltersMatchedCombinations) { |
2110 | EXPECT_TRUE(matchAndVerifyResultTrue( |
2111 | "void f() {" |
2112 | " int x;" |
2113 | " double d;" |
2114 | " x = d + x - d + x;" |
2115 | "}", |
2116 | functionDecl( |
2117 | hasName("f"), forEachDescendant(varDecl().bind("d")), |
2118 | forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))), |
2119 | llvm::make_unique<VerifyIdIsBoundTo<VarDecl>>("d", 5))); |
2120 | } |
2121 | |
2122 | TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) { |
2123 | EXPECT_TRUE(matchAndVerifyResultTrue( |
2124 | "struct StringRef { int size() const; const char* data() const; };" |
2125 | "void f(StringRef v) {" |
2126 | " v.data();" |
2127 | "}", |
2128 | cxxMemberCallExpr( |
2129 | callee(cxxMethodDecl(hasName("data"))), |
2130 | on(declRefExpr(to( |
2131 | varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))), |
2132 | unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr( |
2133 | callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))), |
2134 | on(declRefExpr(to(varDecl(equalsBoundNode("var"))))))))))) |
2135 | .bind("data"), |
2136 | llvm::make_unique<VerifyIdIsBoundTo<Expr>>("data", 1))); |
2137 | |
2138 | EXPECT_FALSE(matches( |
2139 | "struct StringRef { int size() const; const char* data() const; };" |
2140 | "void f(StringRef v) {" |
2141 | " v.data();" |
2142 | " v.size();" |
2143 | "}", |
2144 | cxxMemberCallExpr( |
2145 | callee(cxxMethodDecl(hasName("data"))), |
2146 | on(declRefExpr(to( |
2147 | varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))), |
2148 | unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr( |
2149 | callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))), |
2150 | on(declRefExpr(to(varDecl(equalsBoundNode("var"))))))))))) |
2151 | .bind("data"))); |
2152 | } |
2153 | |
2154 | TEST(NullPointerConstants, Basic) { |
2155 | EXPECT_TRUE(matches("#define NULL ((void *)0)\n" |
2156 | "void *v1 = NULL;", expr(nullPointerConstant()))); |
2157 | EXPECT_TRUE(matches("void *v2 = nullptr;", expr(nullPointerConstant()))); |
2158 | EXPECT_TRUE(matches("void *v3 = __null;", expr(nullPointerConstant()))); |
2159 | EXPECT_TRUE(matches("char *cp = (char *)0;", expr(nullPointerConstant()))); |
2160 | EXPECT_TRUE(matches("int *ip = 0;", expr(nullPointerConstant()))); |
2161 | EXPECT_TRUE(notMatches("int i = 0;", expr(nullPointerConstant()))); |
2162 | } |
2163 | |
2164 | TEST(HasExternalFormalLinkage, Basic) { |
2165 | EXPECT_TRUE(matches("int a = 0;", namedDecl(hasExternalFormalLinkage()))); |
2166 | EXPECT_TRUE( |
2167 | notMatches("static int a = 0;", namedDecl(hasExternalFormalLinkage()))); |
2168 | EXPECT_TRUE(notMatches("static void f(void) { int a = 0; }", |
2169 | namedDecl(hasExternalFormalLinkage()))); |
2170 | EXPECT_TRUE(matches("void f(void) { int a = 0; }", |
2171 | namedDecl(hasExternalFormalLinkage()))); |
2172 | |
2173 | |
2174 | |
2175 | |
2176 | EXPECT_TRUE(matches("namespace { int a = 0; }", |
2177 | namedDecl(hasExternalFormalLinkage()))); |
2178 | } |
2179 | |
2180 | TEST(HasDefaultArgument, Basic) { |
2181 | EXPECT_TRUE(matches("void x(int val = 0) {}", |
2182 | parmVarDecl(hasDefaultArgument()))); |
2183 | EXPECT_TRUE(notMatches("void x(int val) {}", |
2184 | parmVarDecl(hasDefaultArgument()))); |
2185 | } |
2186 | |
2187 | TEST(IsArray, Basic) { |
2188 | EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];", |
2189 | cxxNewExpr(isArray()))); |
2190 | } |
2191 | |
2192 | TEST(HasArraySize, Basic) { |
2193 | EXPECT_TRUE(matches("struct MyClass {}; MyClass *p1 = new MyClass[10];", |
2194 | cxxNewExpr(hasArraySize(integerLiteral(equals(10)))))); |
2195 | } |
2196 | |
2197 | TEST(HasDefinition, MatchesStructDefinition) { |
2198 | EXPECT_TRUE(matches("struct x {};", |
2199 | cxxRecordDecl(hasDefinition()))); |
2200 | EXPECT_TRUE(notMatches("struct x;", |
2201 | cxxRecordDecl(hasDefinition()))); |
2202 | } |
2203 | |
2204 | TEST(HasDefinition, MatchesClassDefinition) { |
2205 | EXPECT_TRUE(matches("class x {};", |
2206 | cxxRecordDecl(hasDefinition()))); |
2207 | EXPECT_TRUE(notMatches("class x;", |
2208 | cxxRecordDecl(hasDefinition()))); |
2209 | } |
2210 | |
2211 | TEST(HasDefinition, MatchesUnionDefinition) { |
2212 | EXPECT_TRUE(matches("union x {};", |
2213 | cxxRecordDecl(hasDefinition()))); |
2214 | EXPECT_TRUE(notMatches("union x;", |
2215 | cxxRecordDecl(hasDefinition()))); |
2216 | } |
2217 | |
2218 | TEST(IsScopedEnum, MatchesScopedEnum) { |
2219 | EXPECT_TRUE(matches("enum class X {};", enumDecl(isScoped()))); |
2220 | EXPECT_TRUE(notMatches("enum X {};", enumDecl(isScoped()))); |
2221 | } |
2222 | |
2223 | TEST(HasTrailingReturn, MatchesTrailingReturn) { |
2224 | EXPECT_TRUE(matches("auto Y() -> int { return 0; }", |
2225 | functionDecl(hasTrailingReturn()))); |
2226 | EXPECT_TRUE(matches("auto X() -> int;", functionDecl(hasTrailingReturn()))); |
2227 | EXPECT_TRUE(notMatches("int X() { return 0; }", |
2228 | functionDecl(hasTrailingReturn()))); |
2229 | EXPECT_TRUE(notMatches("int X();", functionDecl(hasTrailingReturn()))); |
2230 | EXPECT_TRUE(notMatchesC("void X();", functionDecl(hasTrailingReturn()))); |
2231 | } |
2232 | |
2233 | TEST(HasTrailingReturn, MatchesLambdaTrailingReturn) { |
2234 | EXPECT_TRUE(matches( |
2235 | "auto lambda2 = [](double x, double y) -> double {return x + y;};", |
2236 | functionDecl(hasTrailingReturn()))); |
2237 | EXPECT_TRUE(notMatches( |
2238 | "auto lambda2 = [](double x, double y) {return x + y;};", |
2239 | functionDecl(hasTrailingReturn()))); |
2240 | } |
2241 | |
2242 | TEST(IsAssignmentOperator, Basic) { |
2243 | StatementMatcher BinAsgmtOperator = binaryOperator(isAssignmentOperator()); |
2244 | StatementMatcher CXXAsgmtOperator = |
2245 | cxxOperatorCallExpr(isAssignmentOperator()); |
2246 | |
2247 | EXPECT_TRUE(matches("void x() { int a; a += 1; }", BinAsgmtOperator)); |
2248 | EXPECT_TRUE(matches("void x() { int a; a = 2; }", BinAsgmtOperator)); |
2249 | EXPECT_TRUE(matches("void x() { int a; a &= 3; }", BinAsgmtOperator)); |
2250 | EXPECT_TRUE(matches("struct S { S& operator=(const S&); };" |
2251 | "void x() { S s1, s2; s1 = s2; }", |
2252 | CXXAsgmtOperator)); |
2253 | EXPECT_TRUE( |
2254 | notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator)); |
2255 | } |
2256 | |
2257 | TEST(HasInit, Basic) { |
2258 | EXPECT_TRUE( |
2259 | matches("int x{0};", |
2260 | initListExpr(hasInit(0, expr())))); |
2261 | EXPECT_FALSE( |
2262 | matches("int x{0};", |
2263 | initListExpr(hasInit(1, expr())))); |
2264 | EXPECT_FALSE( |
2265 | matches("int x;", |
2266 | initListExpr(hasInit(0, expr())))); |
2267 | } |
2268 | |
2269 | TEST(Matcher, isMain) { |
2270 | EXPECT_TRUE( |
2271 | matches("int main() {}", functionDecl(isMain()))); |
2272 | |
2273 | EXPECT_TRUE( |
2274 | notMatches("int main2() {}", functionDecl(isMain()))); |
2275 | } |
2276 | |
2277 | TEST(OMPExecutableDirective, isStandaloneDirective) { |
2278 | auto Matcher = ompExecutableDirective(isStandaloneDirective()); |
2279 | |
2280 | const std::string Source0 = R"( |
2281 | void x() { |
2282 | #pragma omp parallel |
2283 | ; |
2284 | })"; |
2285 | EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); |
2286 | |
2287 | const std::string Source1 = R"( |
2288 | void x() { |
2289 | #pragma omp taskyield |
2290 | })"; |
2291 | EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher)); |
2292 | } |
2293 | |
2294 | TEST(Stmt, isOMPStructuredBlock) { |
2295 | const std::string Source0 = R"( |
2296 | void x() { |
2297 | #pragma omp parallel |
2298 | ; |
2299 | })"; |
2300 | EXPECT_TRUE( |
2301 | matchesWithOpenMP(Source0, stmt(nullStmt(), isOMPStructuredBlock()))); |
2302 | |
2303 | const std::string Source1 = R"( |
2304 | void x() { |
2305 | #pragma omp parallel |
2306 | {;} |
2307 | })"; |
2308 | EXPECT_TRUE( |
2309 | notMatchesWithOpenMP(Source1, stmt(nullStmt(), isOMPStructuredBlock()))); |
2310 | EXPECT_TRUE( |
2311 | matchesWithOpenMP(Source1, stmt(compoundStmt(), isOMPStructuredBlock()))); |
2312 | } |
2313 | |
2314 | TEST(OMPExecutableDirective, hasStructuredBlock) { |
2315 | const std::string Source0 = R"( |
2316 | void x() { |
2317 | #pragma omp parallel |
2318 | ; |
2319 | })"; |
2320 | EXPECT_TRUE(matchesWithOpenMP( |
2321 | Source0, ompExecutableDirective(hasStructuredBlock(nullStmt())))); |
2322 | |
2323 | const std::string Source1 = R"( |
2324 | void x() { |
2325 | #pragma omp parallel |
2326 | {;} |
2327 | })"; |
2328 | EXPECT_TRUE(notMatchesWithOpenMP( |
2329 | Source1, ompExecutableDirective(hasStructuredBlock(nullStmt())))); |
2330 | EXPECT_TRUE(matchesWithOpenMP( |
2331 | Source1, ompExecutableDirective(hasStructuredBlock(compoundStmt())))); |
2332 | |
2333 | const std::string Source2 = R"( |
2334 | void x() { |
2335 | #pragma omp taskyield |
2336 | {;} |
2337 | })"; |
2338 | EXPECT_TRUE(notMatchesWithOpenMP( |
2339 | Source2, ompExecutableDirective(hasStructuredBlock(anything())))); |
2340 | } |
2341 | |
2342 | TEST(OMPExecutableDirective, hasClause) { |
2343 | auto Matcher = ompExecutableDirective(hasAnyClause(anything())); |
2344 | |
2345 | const std::string Source0 = R"( |
2346 | void x() { |
2347 | ; |
2348 | })"; |
2349 | EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); |
2350 | |
2351 | const std::string Source1 = R"( |
2352 | void x() { |
2353 | #pragma omp parallel |
2354 | ; |
2355 | })"; |
2356 | EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher)); |
2357 | |
2358 | const std::string Source2 = R"( |
2359 | void x() { |
2360 | #pragma omp parallel default(none) |
2361 | ; |
2362 | })"; |
2363 | EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher)); |
2364 | |
2365 | const std::string Source3 = R"( |
2366 | void x() { |
2367 | #pragma omp parallel default(shared) |
2368 | ; |
2369 | })"; |
2370 | EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher)); |
2371 | |
2372 | const std::string Source4 = R"( |
2373 | void x(int x) { |
2374 | #pragma omp parallel num_threads(x) |
2375 | ; |
2376 | })"; |
2377 | EXPECT_TRUE(matchesWithOpenMP(Source4, Matcher)); |
2378 | } |
2379 | |
2380 | TEST(OMPDefaultClause, isNoneKind) { |
2381 | auto Matcher = |
2382 | ompExecutableDirective(hasAnyClause(ompDefaultClause(isNoneKind()))); |
2383 | |
2384 | const std::string Source0 = R"( |
2385 | void x() { |
2386 | ; |
2387 | })"; |
2388 | EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); |
2389 | |
2390 | const std::string Source1 = R"( |
2391 | void x() { |
2392 | #pragma omp parallel |
2393 | ; |
2394 | })"; |
2395 | EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher)); |
2396 | |
2397 | const std::string Source2 = R"( |
2398 | void x() { |
2399 | #pragma omp parallel default(none) |
2400 | ; |
2401 | })"; |
2402 | EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher)); |
2403 | |
2404 | const std::string Source3 = R"( |
2405 | void x() { |
2406 | #pragma omp parallel default(shared) |
2407 | ; |
2408 | })"; |
2409 | EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher)); |
2410 | |
2411 | const std::string Source4 = R"( |
2412 | void x(int x) { |
2413 | #pragma omp parallel num_threads(x) |
2414 | ; |
2415 | })"; |
2416 | EXPECT_TRUE(notMatchesWithOpenMP(Source4, Matcher)); |
2417 | } |
2418 | |
2419 | TEST(OMPDefaultClause, isSharedKind) { |
2420 | auto Matcher = |
2421 | ompExecutableDirective(hasAnyClause(ompDefaultClause(isSharedKind()))); |
2422 | |
2423 | const std::string Source0 = R"( |
2424 | void x() { |
2425 | ; |
2426 | })"; |
2427 | EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); |
2428 | |
2429 | const std::string Source1 = R"( |
2430 | void x() { |
2431 | #pragma omp parallel |
2432 | ; |
2433 | })"; |
2434 | EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher)); |
2435 | |
2436 | const std::string Source2 = R"( |
2437 | void x() { |
2438 | #pragma omp parallel default(shared) |
2439 | ; |
2440 | })"; |
2441 | EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher)); |
2442 | |
2443 | const std::string Source3 = R"( |
2444 | void x() { |
2445 | #pragma omp parallel default(none) |
2446 | ; |
2447 | })"; |
2448 | EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher)); |
2449 | |
2450 | const std::string Source4 = R"( |
2451 | void x(int x) { |
2452 | #pragma omp parallel num_threads(x) |
2453 | ; |
2454 | })"; |
2455 | EXPECT_TRUE(notMatchesWithOpenMP(Source4, Matcher)); |
2456 | } |
2457 | |
2458 | TEST(OMPExecutableDirective, isAllowedToContainClauseKind) { |
2459 | auto Matcher = |
2460 | ompExecutableDirective(isAllowedToContainClauseKind(OMPC_default)); |
2461 | |
2462 | const std::string Source0 = R"( |
2463 | void x() { |
2464 | ; |
2465 | })"; |
2466 | EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher)); |
2467 | |
2468 | const std::string Source1 = R"( |
2469 | void x() { |
2470 | #pragma omp parallel |
2471 | ; |
2472 | })"; |
2473 | EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher)); |
2474 | |
2475 | const std::string Source2 = R"( |
2476 | void x() { |
2477 | #pragma omp parallel default(none) |
2478 | ; |
2479 | })"; |
2480 | EXPECT_TRUE(matchesWithOpenMP(Source2, Matcher)); |
2481 | |
2482 | const std::string Source3 = R"( |
2483 | void x() { |
2484 | #pragma omp parallel default(shared) |
2485 | ; |
2486 | })"; |
2487 | EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher)); |
2488 | |
2489 | const std::string Source4 = R"( |
2490 | void x(int x) { |
2491 | #pragma omp parallel num_threads(x) |
2492 | ; |
2493 | })"; |
2494 | EXPECT_TRUE(matchesWithOpenMP(Source4, Matcher)); |
2495 | |
2496 | const std::string Source5 = R"( |
2497 | void x() { |
2498 | #pragma omp taskyield |
2499 | })"; |
2500 | EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher)); |
2501 | |
2502 | const std::string Source6 = R"( |
2503 | void x() { |
2504 | #pragma omp task |
2505 | ; |
2506 | })"; |
2507 | EXPECT_TRUE(matchesWithOpenMP(Source6, Matcher)); |
2508 | } |
2509 | |
2510 | } |
2511 | } |
2512 | |