blob: a5f85ffa9235000c666f626ffc48292668d09359 [file] [log] [blame]
David Blaikiee0026312012-04-26 20:39:46 +00001//===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===//
Manuel Klimekfad7f852012-04-19 08:48:53 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Richard Smithbc9e5582012-06-24 23:56:26 +000010#include "TestVisitor.h"
James Dennett49007d72013-07-10 18:29:15 +000011#include <stack>
12
Manuel Klimekfad7f852012-04-19 08:48:53 +000013namespace clang {
14
Manuel Klimekfad7f852012-04-19 08:48:53 +000015class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
16public:
17 bool VisitTypeLoc(TypeLoc TypeLocation) {
18 Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
19 return true;
20 }
21};
22
23class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
24public:
25 bool VisitDeclRefExpr(DeclRefExpr *Reference) {
26 Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
27 return true;
28 }
29};
30
Daniel Jasper52ec0c02012-06-13 07:12:33 +000031class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
32public:
33 bool VisitVarDecl(VarDecl *Variable) {
34 Match(Variable->getNameAsString(), Variable->getLocStart());
35 return true;
36 }
37};
38
Michael Han4b6730d2013-09-11 15:53:29 +000039class ParmVarDeclVisitorForImplicitCode :
40 public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
41public:
42 bool shouldVisitImplicitCode() const { return true; }
43
44 bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
45 Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
46 return true;
47 }
48};
49
Manuel Klimekfad7f852012-04-19 08:48:53 +000050class CXXMemberCallVisitor
51 : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
52public:
53 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
54 Match(Call->getMethodDecl()->getQualifiedNameAsString(),
55 Call->getLocStart());
56 return true;
57 }
58};
59
Richard Smitha313b2f2012-04-25 22:57:25 +000060class NamedDeclVisitor
61 : public ExpectedLocationVisitor<NamedDeclVisitor> {
62public:
63 bool VisitNamedDecl(NamedDecl *Decl) {
64 std::string NameWithTemplateArgs;
Benjamin Kramer5eada842013-02-22 15:46:01 +000065 llvm::raw_string_ostream OS(NameWithTemplateArgs);
66 Decl->getNameForDiagnostic(OS,
Richard Smitha313b2f2012-04-25 22:57:25 +000067 Decl->getASTContext().getPrintingPolicy(),
68 true);
Benjamin Kramer5eada842013-02-22 15:46:01 +000069 Match(OS.str(), Decl->getLocation());
Richard Smitha313b2f2012-04-25 22:57:25 +000070 return true;
71 }
72};
73
Richard Smithc8c22282012-05-02 00:30:48 +000074class CXXOperatorCallExprTraverser
75 : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
76public:
77 // Use Traverse, not Visit, to check that data recursion optimization isn't
78 // bypassing the call of this function.
79 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
80 Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
81 return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
82 TraverseCXXOperatorCallExpr(CE);
83 }
84};
85
86class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
87public:
88 bool VisitParenExpr(ParenExpr *Parens) {
89 Match("", Parens->getExprLoc());
90 return true;
91 }
92};
93
James Dennett89faf862013-06-30 03:13:35 +000094class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
95public:
96 bool VisitLambdaExpr(LambdaExpr *Lambda) {
James Dennett49007d72013-07-10 18:29:15 +000097 PendingBodies.push(Lambda);
James Dennett89faf862013-06-30 03:13:35 +000098 Match("", Lambda->getIntroducerRange().getBegin());
99 return true;
100 }
James Dennett49007d72013-07-10 18:29:15 +0000101 /// For each call to VisitLambdaExpr, we expect a subsequent call (with
102 /// proper nesting) to TraverseLambdaBody.
103 bool TraverseLambdaBody(LambdaExpr *Lambda) {
104 EXPECT_FALSE(PendingBodies.empty());
105 EXPECT_EQ(PendingBodies.top(), Lambda);
106 PendingBodies.pop();
107 return TraverseStmt(Lambda->getBody());
108 }
109 /// Determine whether TraverseLambdaBody has been called for every call to
110 /// VisitLambdaExpr.
111 bool allBodiesHaveBeenTraversed() const {
112 return PendingBodies.empty();
113 }
114private:
James Dennettf68af642013-08-09 23:08:25 +0000115 std::stack<LambdaExpr *> PendingBodies;
116};
117
118// Matches the (optional) capture-default of a lambda-introducer.
119class LambdaDefaultCaptureVisitor
120 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
121public:
122 bool VisitLambdaExpr(LambdaExpr *Lambda) {
123 if (Lambda->getCaptureDefault() != LCD_None) {
124 Match("", Lambda->getCaptureDefaultLoc());
125 }
126 return true;
127 }
James Dennett89faf862013-06-30 03:13:35 +0000128};
129
Richard Smith6fada8e2012-05-30 23:55:51 +0000130class TemplateArgumentLocTraverser
131 : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
132public:
133 bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
134 std::string ArgStr;
135 llvm::raw_string_ostream Stream(ArgStr);
136 const TemplateArgument &Arg = ArgLoc.getArgument();
137
138 Arg.print(Context->getPrintingPolicy(), Stream);
139 Match(Stream.str(), ArgLoc.getLocation());
140 return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
141 TraverseTemplateArgumentLoc(ArgLoc);
142 }
143};
144
145class CXXBoolLiteralExprVisitor
146 : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
147public:
148 bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
149 if (BE->getValue())
150 Match("true", BE->getLocation());
151 else
152 Match("false", BE->getLocation());
153 return true;
154 }
155};
156
Michael Han4b6730d2013-09-11 15:53:29 +0000157// Test RAV visits parameter variable declaration of the implicit
Michael Han0bb3ca32013-09-12 20:59:33 +0000158// copy assignment operator and implicit copy constructor.
Michael Han4b6730d2013-09-11 15:53:29 +0000159TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
160 ParmVarDeclVisitorForImplicitCode Visitor;
Michael Han0bb3ca32013-09-12 20:59:33 +0000161 // Match parameter variable name of implicit copy assignment operator and
162 // implicit copy constructor.
Michael Han4b6730d2013-09-11 15:53:29 +0000163 // This parameter name does not have a valid IdentifierInfo, and shares
164 // same SourceLocation with its class declaration, so we match an empty name
165 // with the class' source location.
166 Visitor.ExpectMatch("", 1, 7);
Michael Han0bb3ca32013-09-12 20:59:33 +0000167 Visitor.ExpectMatch("", 3, 7);
Michael Han4b6730d2013-09-11 15:53:29 +0000168 EXPECT_TRUE(Visitor.runOver(
169 "class X {};\n"
Michael Han0bb3ca32013-09-12 20:59:33 +0000170 "void foo(X a, X b) {a = b;}\n"
171 "class Y {};\n"
172 "void bar(Y a) {Y b = a;}"));
Michael Han4b6730d2013-09-11 15:53:29 +0000173}
174
Manuel Klimekfad7f852012-04-19 08:48:53 +0000175TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
176 TypeLocVisitor Visitor;
177 Visitor.ExpectMatch("class X", 1, 30);
178 EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
179}
180
Manuel Klimek9f99d062012-04-23 16:40:40 +0000181TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) {
182 TypeLocVisitor Visitor;
183 Visitor.ExpectMatch("class X", 3, 18);
184 EXPECT_TRUE(Visitor.runOver(
185 "class Y;\n"
186 "class X {};\n"
187 "class Y : public X {};"));
188}
189
190TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) {
191 TypeLocVisitor Visitor;
192 Visitor.ExpectMatch("class X", 2, 18);
193 EXPECT_TRUE(Visitor.runOver(
194 "class X {};\n"
195 "class Y : public X { class Z; };"));
196}
197
198TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) {
199 TypeLocVisitor Visitor;
200 Visitor.ExpectMatch("X<class Y>", 2, 18);
201 EXPECT_TRUE(Visitor.runOver(
202 "template<typename T> class X {};\n"
203 "class Y : public X<Y> {};"));
204}
205
Manuel Klimekfad7f852012-04-19 08:48:53 +0000206TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
207 DeclRefExprVisitor Visitor;
208 Visitor.ExpectMatch("x", 2, 3);
209 EXPECT_TRUE(Visitor.runOver(
210 "void x(); template <void (*T)()> class X {};\nX<x> y;"));
211}
212
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000213TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
214 DeclRefExprVisitor Visitor;
215 Visitor.ExpectMatch("x", 2, 25);
Daniel Jasper1071ba92012-06-21 08:50:04 +0000216 Visitor.ExpectMatch("x", 2, 30);
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000217 EXPECT_TRUE(Visitor.runOver(
218 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000219 "void f() { for (int i : x) { x[0] = 1; } }",
220 DeclRefExprVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000221}
222
223TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
224 VarDeclVisitor Visitor;
225 Visitor.ExpectMatch("i", 2, 17);
226 EXPECT_TRUE(Visitor.runOver(
227 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000228 "void f() { for (int i : x) {} }",
229 VarDeclVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000230}
231
Manuel Klimekfad7f852012-04-19 08:48:53 +0000232TEST(RecursiveASTVisitor, VisitsCallExpr) {
233 DeclRefExprVisitor Visitor;
234 Visitor.ExpectMatch("x", 1, 22);
235 EXPECT_TRUE(Visitor.runOver(
236 "void x(); void y() { x(); }"));
237}
238
239TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
240 CXXMemberCallVisitor Visitor;
241 Visitor.ExpectMatch("Y::x", 3, 3);
242 EXPECT_TRUE(Visitor.runOver(
243 "struct Y { void x(); };\n"
244 "template<typename T> void y(T t) {\n"
245 " t.x();\n"
246 "}\n"
247 "void foo() { y<Y>(Y()); }"));
248}
249
Richard Smith5482dc32012-04-24 20:39:49 +0000250TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
Manuel Klimekfad7f852012-04-19 08:48:53 +0000251 CXXMemberCallVisitor Visitor;
252 Visitor.ExpectMatch("Y::x", 4, 5);
253 EXPECT_TRUE(Visitor.runOver(
254 "struct Y { void x(); };\n"
255 "template<typename T> struct Z {\n"
256 " template<typename U> static void f() {\n"
257 " T().x();\n"
258 " }\n"
259 "};\n"
260 "void foo() { Z<Y>::f<int>(); }"));
261}
Richard Smith5482dc32012-04-24 20:39:49 +0000262
263TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
264 CXXMemberCallVisitor Visitor;
265 Visitor.ExpectMatch("A::x", 5, 7);
266 EXPECT_TRUE(Visitor.runOver(
267 "template <typename T1> struct X {\n"
268 " template <typename T2> struct Y {\n"
269 " void f() {\n"
270 " T2 y;\n"
271 " y.x();\n"
272 " }\n"
273 " };\n"
274 "};\n"
275 "struct A { void x(); };\n"
276 "int main() {\n"
277 " (new X<A>::Y<A>())->f();\n"
278 "}"));
279}
Manuel Klimekfad7f852012-04-19 08:48:53 +0000280
281/* FIXME: According to Richard Smith this is a bug in the AST.
282TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
283 DeclRefExprVisitor Visitor;
284 Visitor.ExpectMatch("x", 3, 43);
285 EXPECT_TRUE(Visitor.runOver(
286 "template <typename T> void x();\n"
287 "template <void (*T)()> class X {};\n"
288 "template <typename T> class Y : public X< x<T> > {};\n"
289 "Y<int> y;"));
290}
291*/
292
Richard Smitha313b2f2012-04-25 22:57:25 +0000293TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
294 CXXMemberCallVisitor Visitor;
295 Visitor.ExpectMatch("A::x", 6, 20);
296 EXPECT_TRUE(Visitor.runOver(
297 "template <typename T1> struct X {\n"
298 " template <typename T2, bool B> struct Y { void g(); };\n"
299 "};\n"
300 "template <typename T1> template <typename T2>\n"
301 "struct X<T1>::Y<T2, true> {\n"
302 " void f() { T2 y; y.x(); }\n"
303 "};\n"
304 "struct A { void x(); };\n"
305 "int main() {\n"
306 " (new X<A>::Y<A, true>())->f();\n"
307 "}\n"));
308}
309
Richard Smith06cd51a2012-05-09 23:51:36 +0000310TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
311 CXXMemberCallVisitor Visitor;
312 Visitor.ExpectMatch("A::f", 4, 5);
313 EXPECT_TRUE(Visitor.runOver(
314 "struct A {\n"
315 " void f() const {}\n"
316 " template<class T> void g(const T& t) const {\n"
317 " t.f();\n"
318 " }\n"
319 "};\n"
320 "template void A::g(const A& a) const;\n"));
321}
322
Richard Smitha313b2f2012-04-25 22:57:25 +0000323TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
324 // From cfe-commits/Week-of-Mon-20100830/033998.html
Daniel Jaspere966bea2012-05-30 04:30:08 +0000325 // Contrary to the approach suggested in that email, we visit all
Richard Smitha313b2f2012-04-25 22:57:25 +0000326 // specializations when we visit the primary template. Visiting them when we
327 // visit the associated specialization is problematic for specializations of
328 // template members of class templates.
329 NamedDeclVisitor Visitor;
330 Visitor.ExpectMatch("A<bool>", 1, 26);
331 Visitor.ExpectMatch("A<char *>", 2, 26);
332 EXPECT_TRUE(Visitor.runOver(
333 "template <class T> class A {};\n"
334 "template <class T> class A<T*> {};\n"
335 "A<bool> ab;\n"
336 "A<char*> acp;\n"));
337}
338
339TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
340 NamedDeclVisitor Visitor;
341 Visitor.ExpectMatch("A<int>", 1, 29);
342 EXPECT_TRUE(Visitor.runOver(
343 "template<typename T> struct A;\n"
344 "A<int> *p;\n"));
345}
346
347TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
348 NamedDeclVisitor Visitor;
349 Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
350 EXPECT_TRUE(Visitor.runOver(
351 "template<typename T> struct A {\n"
352 " template<typename U> struct B;\n"
353 "};\n"
354 "A<int>::B<char> *p;\n"));
355}
356
357TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
358 NamedDeclVisitor Visitor;
359 Visitor.ExpectMatch("A<int>", 1, 26);
360 EXPECT_TRUE(Visitor.runOver(
361 "template<typename T> int A();\n"
362 "int k = A<int>();\n"));
363}
364
365TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
366 NamedDeclVisitor Visitor;
367 Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
368 EXPECT_TRUE(Visitor.runOver(
369 "template<typename T> struct A {\n"
370 " template<typename U> static int B();\n"
371 "};\n"
372 "int k = A<int>::B<char>();\n"));
373}
374
375TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
376 // From cfe-commits/Week-of-Mon-20100830/033977.html
377 NamedDeclVisitor Visitor;
378 Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
379 EXPECT_TRUE(Visitor.runOver(
380 "template<typename Container>\n"
381 "class vector_iterator {\n"
382 " template <typename C> friend class vector_iterator;\n"
383 "};\n"
384 "vector_iterator<int> it_int;\n"));
385}
386
Richard Smithc8c22282012-05-02 00:30:48 +0000387TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
388 CXXOperatorCallExprTraverser Visitor;
389 Visitor.ExpectMatch("()", 4, 9);
390 EXPECT_TRUE(Visitor.runOver(
391 "struct A {\n"
392 " int operator()();\n"
393 "} a;\n"
394 "int k = a();\n"));
395}
396
397TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
398 ParenExprVisitor Visitor;
399 Visitor.ExpectMatch("", 1, 9);
400 EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
401}
402
Richard Smith6fada8e2012-05-30 23:55:51 +0000403TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
404 CXXBoolLiteralExprVisitor Visitor;
405 Visitor.ExpectMatch("true", 2, 19);
406 EXPECT_TRUE(Visitor.runOver(
407 "template<bool B> class X;\n"
408 "template<bool B = true> class Y;\n"
409 "template<bool B> class Y {};\n"));
410}
411
412TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) {
413 TypeLocVisitor Visitor;
414 Visitor.ExpectMatch("class X", 2, 23);
415 EXPECT_TRUE(Visitor.runOver(
416 "class X;\n"
417 "template<typename T = X> class Y;\n"
418 "template<typename T> class Y {};\n"));
419}
420
421TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
422 TemplateArgumentLocTraverser Visitor;
423 Visitor.ExpectMatch("X", 2, 40);
424 EXPECT_TRUE(Visitor.runOver(
425 "template<typename T> class X;\n"
426 "template<template <typename> class T = X> class Y;\n"
427 "template<template <typename> class T> class Y {};\n"));
428}
429
Richard Smithc28a3352012-06-05 16:18:26 +0000430// A visitor that visits implicit declarations and matches constructors.
431class ImplicitCtorVisitor
432 : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
433public:
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000434 bool shouldVisitImplicitCode() const { return true; }
Richard Smithc28a3352012-06-05 16:18:26 +0000435
436 bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
437 if (Ctor->isImplicit()) { // Was not written in source code
438 if (const CXXRecordDecl* Class = Ctor->getParent()) {
439 Match(Class->getName(), Ctor->getLocation());
440 }
441 }
442 return true;
443 }
444};
445
446TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
447 ImplicitCtorVisitor Visitor;
448 Visitor.ExpectMatch("Simple", 2, 8);
449 // Note: Clang lazily instantiates implicit declarations, so we need
450 // to use them in order to force them to appear in the AST.
451 EXPECT_TRUE(Visitor.runOver(
452 "struct WithCtor { WithCtor(); }; \n"
453 "struct Simple { Simple(); WithCtor w; }; \n"
454 "int main() { Simple s; Simple t(s); }\n"));
455}
456
James Dennett8268fe72012-08-24 06:59:51 +0000457/// \brief A visitor that optionally includes implicit code and matches
458/// CXXConstructExpr.
459///
460/// The name recorded for the match is the name of the class whose constructor
461/// is invoked by the CXXConstructExpr, not the name of the class whose
462/// constructor the CXXConstructExpr is contained in.
463class ConstructExprVisitor
464 : public ExpectedLocationVisitor<ConstructExprVisitor> {
465public:
466 ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
467
468 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
469
470 void setShouldVisitImplicitCode(bool NewValue) {
471 ShouldVisitImplicitCode = NewValue;
472 }
473
474 bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
475 if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
476 if (const CXXRecordDecl* Class = Ctor->getParent()) {
477 Match(Class->getName(), Expr->getLocation());
478 }
479 }
480 return true;
481 }
482
483 private:
484 bool ShouldVisitImplicitCode;
485};
486
487TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
488 ConstructExprVisitor Visitor;
489 Visitor.setShouldVisitImplicitCode(true);
490 Visitor.ExpectMatch("WithCtor", 2, 8);
491 // Simple has a constructor that implicitly initializes 'w'. Test
492 // that a visitor that visits implicit code visits that initialization.
493 // Note: Clang lazily instantiates implicit declarations, so we need
494 // to use them in order to force them to appear in the AST.
495 EXPECT_TRUE(Visitor.runOver(
496 "struct WithCtor { WithCtor(); }; \n"
497 "struct Simple { WithCtor w; }; \n"
498 "int main() { Simple s; }\n"));
499}
500
501// The same as CanVisitImplicitMemberInitializations, but checking that the
502// visits are omitted when the visitor does not include implicit code.
503TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
504 ConstructExprVisitor Visitor;
505 Visitor.setShouldVisitImplicitCode(false);
506 Visitor.DisallowMatch("WithCtor", 2, 8);
507 // Simple has a constructor that implicitly initializes 'w'. Test
508 // that a visitor that skips implicit code skips that initialization.
509 // Note: Clang lazily instantiates implicit declarations, so we need
510 // to use them in order to force them to appear in the AST.
511 EXPECT_TRUE(Visitor.runOver(
512 "struct WithCtor { WithCtor(); }; \n"
513 "struct Simple { WithCtor w; }; \n"
514 "int main() { Simple s; }\n"));
515}
516
Richard Smith0652c352012-08-17 03:20:55 +0000517TEST(RecursiveASTVisitor, VisitsExtension) {
518 DeclRefExprVisitor Visitor;
519 Visitor.ExpectMatch("s", 1, 24);
520 EXPECT_TRUE(Visitor.runOver(
521 "int s = __extension__ (s);\n"));
522}
523
Richard Smith82b45502012-08-17 21:23:17 +0000524TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) {
525 TypeLocVisitor Visitor;
526 Visitor.ExpectMatch("struct S", 1, 26);
527 EXPECT_TRUE(Visitor.runOver(
528 "int f() { return (struct S { int a; }){.a = 0}.a; }",
529 TypeLocVisitor::Lang_C));
530}
531
James Dennett89faf862013-06-30 03:13:35 +0000532TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
533 LambdaExprVisitor Visitor;
534 Visitor.ExpectMatch("", 1, 12);
535 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
536 LambdaExprVisitor::Lang_CXX11));
537}
538
James Dennett49007d72013-07-10 18:29:15 +0000539TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
540 LambdaExprVisitor Visitor;
541 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
542 LambdaExprVisitor::Lang_CXX11));
543 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
544}
545
James Dennettf68af642013-08-09 23:08:25 +0000546TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
547 LambdaDefaultCaptureVisitor Visitor;
548 Visitor.ExpectMatch("", 1, 20);
549 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
550 LambdaDefaultCaptureVisitor::Lang_CXX11));
551}
552
James Dennette3efec22013-09-05 17:46:21 +0000553// Checks for lambda classes that are not marked as implicitly-generated.
554// (There should be none.)
555class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
556public:
557 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
558 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
559 if (record->isLambda() && !record->isImplicit())
560 SawNonImplicitLambdaClass = true;
561 return true;
562 }
563
564 bool sawOnlyImplicitLambdaClasses() const {
565 return !SawNonImplicitLambdaClass;
566 }
567
568private:
569 bool SawNonImplicitLambdaClass;
570};
571
572TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
573 ClassVisitor Visitor;
574 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};",
575 ClassVisitor::Lang_CXX11));
576 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
577}
578
Stephen Hines651f13c2014-04-23 16:59:28 -0700579
580
581// Check to ensure that attributes and expressions within them are being
582// visited.
583class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
584public:
585 bool VisitMemberExpr(MemberExpr *ME) {
586 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
587 return true;
588 }
589 bool VisitAttr(Attr *A) {
590 Match("Attr", A->getLocation());
591 return true;
592 }
593 bool VisitGuardedByAttr(GuardedByAttr *A) {
594 Match("guarded_by", A->getLocation());
595 return true;
596 }
597};
598
599
600TEST(RecursiveASTVisitor, AttributesAreVisited) {
601 AttrVisitor Visitor;
602 Visitor.ExpectMatch("Attr", 4, 24);
603 Visitor.ExpectMatch("guarded_by", 4, 24);
604 Visitor.ExpectMatch("mu1", 4, 35);
605 Visitor.ExpectMatch("Attr", 5, 29);
606 Visitor.ExpectMatch("mu1", 5, 54);
607 Visitor.ExpectMatch("mu2", 5, 59);
608 EXPECT_TRUE(Visitor.runOver(
609 "class Foo {\n"
610 " int mu1;\n"
611 " int mu2;\n"
612 " int a __attribute__((guarded_by(mu1)));\n"
613 " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n"
614 "};\n"));
615}
616
617
Manuel Klimekfad7f852012-04-19 08:48:53 +0000618} // end namespace clang