blob: 323476766e9291e4254d7084fdd6a61c70c1d551 [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"
Manuel Klimekfad7f852012-04-19 08:48:53 +000011
James Dennett49007d72013-07-10 18:29:15 +000012#include <stack>
13
Manuel Klimekfad7f852012-04-19 08:48:53 +000014namespace clang {
15
Manuel Klimekfad7f852012-04-19 08:48:53 +000016class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
17public:
18 bool VisitTypeLoc(TypeLoc TypeLocation) {
19 Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
20 return true;
21 }
22};
23
24class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
25public:
26 bool VisitDeclRefExpr(DeclRefExpr *Reference) {
27 Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
28 return true;
29 }
30};
31
Daniel Jasper52ec0c02012-06-13 07:12:33 +000032class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
33public:
34 bool VisitVarDecl(VarDecl *Variable) {
35 Match(Variable->getNameAsString(), Variable->getLocStart());
36 return true;
37 }
38};
39
Michael Han4b6730d2013-09-11 15:53:29 +000040class ParmVarDeclVisitorForImplicitCode :
41 public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
42public:
43 bool shouldVisitImplicitCode() const { return true; }
44
45 bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
46 Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
47 return true;
48 }
49};
50
Manuel Klimekfad7f852012-04-19 08:48:53 +000051class CXXMemberCallVisitor
52 : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
53public:
54 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
55 Match(Call->getMethodDecl()->getQualifiedNameAsString(),
56 Call->getLocStart());
57 return true;
58 }
59};
60
Richard Smitha313b2f2012-04-25 22:57:25 +000061class NamedDeclVisitor
62 : public ExpectedLocationVisitor<NamedDeclVisitor> {
63public:
64 bool VisitNamedDecl(NamedDecl *Decl) {
65 std::string NameWithTemplateArgs;
Benjamin Kramer5eada842013-02-22 15:46:01 +000066 llvm::raw_string_ostream OS(NameWithTemplateArgs);
67 Decl->getNameForDiagnostic(OS,
Richard Smitha313b2f2012-04-25 22:57:25 +000068 Decl->getASTContext().getPrintingPolicy(),
69 true);
Benjamin Kramer5eada842013-02-22 15:46:01 +000070 Match(OS.str(), Decl->getLocation());
Richard Smitha313b2f2012-04-25 22:57:25 +000071 return true;
72 }
73};
74
Richard Smithc8c22282012-05-02 00:30:48 +000075class CXXOperatorCallExprTraverser
76 : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
77public:
78 // Use Traverse, not Visit, to check that data recursion optimization isn't
79 // bypassing the call of this function.
80 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
81 Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
82 return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
83 TraverseCXXOperatorCallExpr(CE);
84 }
85};
86
87class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
88public:
89 bool VisitParenExpr(ParenExpr *Parens) {
90 Match("", Parens->getExprLoc());
91 return true;
92 }
93};
94
James Dennett89faf862013-06-30 03:13:35 +000095class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
96public:
97 bool VisitLambdaExpr(LambdaExpr *Lambda) {
James Dennett49007d72013-07-10 18:29:15 +000098 PendingBodies.push(Lambda);
James Dennett89faf862013-06-30 03:13:35 +000099 Match("", Lambda->getIntroducerRange().getBegin());
100 return true;
101 }
James Dennett49007d72013-07-10 18:29:15 +0000102 /// For each call to VisitLambdaExpr, we expect a subsequent call (with
103 /// proper nesting) to TraverseLambdaBody.
104 bool TraverseLambdaBody(LambdaExpr *Lambda) {
105 EXPECT_FALSE(PendingBodies.empty());
106 EXPECT_EQ(PendingBodies.top(), Lambda);
107 PendingBodies.pop();
108 return TraverseStmt(Lambda->getBody());
109 }
110 /// Determine whether TraverseLambdaBody has been called for every call to
111 /// VisitLambdaExpr.
112 bool allBodiesHaveBeenTraversed() const {
113 return PendingBodies.empty();
114 }
115private:
James Dennettf68af642013-08-09 23:08:25 +0000116 std::stack<LambdaExpr *> PendingBodies;
117};
118
119// Matches the (optional) capture-default of a lambda-introducer.
120class LambdaDefaultCaptureVisitor
121 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
122public:
123 bool VisitLambdaExpr(LambdaExpr *Lambda) {
124 if (Lambda->getCaptureDefault() != LCD_None) {
125 Match("", Lambda->getCaptureDefaultLoc());
126 }
127 return true;
128 }
James Dennett89faf862013-06-30 03:13:35 +0000129};
130
Richard Smith6fada8e2012-05-30 23:55:51 +0000131class TemplateArgumentLocTraverser
132 : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
133public:
134 bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
135 std::string ArgStr;
136 llvm::raw_string_ostream Stream(ArgStr);
137 const TemplateArgument &Arg = ArgLoc.getArgument();
138
139 Arg.print(Context->getPrintingPolicy(), Stream);
140 Match(Stream.str(), ArgLoc.getLocation());
141 return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
142 TraverseTemplateArgumentLoc(ArgLoc);
143 }
144};
145
146class CXXBoolLiteralExprVisitor
147 : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
148public:
149 bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
150 if (BE->getValue())
151 Match("true", BE->getLocation());
152 else
153 Match("false", BE->getLocation());
154 return true;
155 }
156};
157
Michael Han4b6730d2013-09-11 15:53:29 +0000158// Test RAV visits parameter variable declaration of the implicit
Michael Han0bb3ca32013-09-12 20:59:33 +0000159// copy assignment operator and implicit copy constructor.
Michael Han4b6730d2013-09-11 15:53:29 +0000160TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
161 ParmVarDeclVisitorForImplicitCode Visitor;
Michael Han0bb3ca32013-09-12 20:59:33 +0000162 // Match parameter variable name of implicit copy assignment operator and
163 // implicit copy constructor.
Michael Han4b6730d2013-09-11 15:53:29 +0000164 // This parameter name does not have a valid IdentifierInfo, and shares
165 // same SourceLocation with its class declaration, so we match an empty name
166 // with the class' source location.
167 Visitor.ExpectMatch("", 1, 7);
Michael Han0bb3ca32013-09-12 20:59:33 +0000168 Visitor.ExpectMatch("", 3, 7);
Michael Han4b6730d2013-09-11 15:53:29 +0000169 EXPECT_TRUE(Visitor.runOver(
170 "class X {};\n"
Michael Han0bb3ca32013-09-12 20:59:33 +0000171 "void foo(X a, X b) {a = b;}\n"
172 "class Y {};\n"
173 "void bar(Y a) {Y b = a;}"));
Michael Han4b6730d2013-09-11 15:53:29 +0000174}
175
Manuel Klimekfad7f852012-04-19 08:48:53 +0000176TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
177 TypeLocVisitor Visitor;
178 Visitor.ExpectMatch("class X", 1, 30);
179 EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
180}
181
Manuel Klimek9f99d062012-04-23 16:40:40 +0000182TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) {
183 TypeLocVisitor Visitor;
184 Visitor.ExpectMatch("class X", 3, 18);
185 EXPECT_TRUE(Visitor.runOver(
186 "class Y;\n"
187 "class X {};\n"
188 "class Y : public X {};"));
189}
190
191TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) {
192 TypeLocVisitor Visitor;
193 Visitor.ExpectMatch("class X", 2, 18);
194 EXPECT_TRUE(Visitor.runOver(
195 "class X {};\n"
196 "class Y : public X { class Z; };"));
197}
198
199TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) {
200 TypeLocVisitor Visitor;
201 Visitor.ExpectMatch("X<class Y>", 2, 18);
202 EXPECT_TRUE(Visitor.runOver(
203 "template<typename T> class X {};\n"
204 "class Y : public X<Y> {};"));
205}
206
Manuel Klimekfad7f852012-04-19 08:48:53 +0000207TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
208 DeclRefExprVisitor Visitor;
209 Visitor.ExpectMatch("x", 2, 3);
210 EXPECT_TRUE(Visitor.runOver(
211 "void x(); template <void (*T)()> class X {};\nX<x> y;"));
212}
213
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000214TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
215 DeclRefExprVisitor Visitor;
216 Visitor.ExpectMatch("x", 2, 25);
Daniel Jasper1071ba92012-06-21 08:50:04 +0000217 Visitor.ExpectMatch("x", 2, 30);
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000218 EXPECT_TRUE(Visitor.runOver(
219 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000220 "void f() { for (int i : x) { x[0] = 1; } }",
221 DeclRefExprVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000222}
223
224TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
225 VarDeclVisitor Visitor;
226 Visitor.ExpectMatch("i", 2, 17);
227 EXPECT_TRUE(Visitor.runOver(
228 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000229 "void f() { for (int i : x) {} }",
230 VarDeclVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000231}
232
Manuel Klimekfad7f852012-04-19 08:48:53 +0000233TEST(RecursiveASTVisitor, VisitsCallExpr) {
234 DeclRefExprVisitor Visitor;
235 Visitor.ExpectMatch("x", 1, 22);
236 EXPECT_TRUE(Visitor.runOver(
237 "void x(); void y() { x(); }"));
238}
239
240TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
241 CXXMemberCallVisitor Visitor;
242 Visitor.ExpectMatch("Y::x", 3, 3);
243 EXPECT_TRUE(Visitor.runOver(
244 "struct Y { void x(); };\n"
245 "template<typename T> void y(T t) {\n"
246 " t.x();\n"
247 "}\n"
248 "void foo() { y<Y>(Y()); }"));
249}
250
Richard Smith5482dc32012-04-24 20:39:49 +0000251TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
Manuel Klimekfad7f852012-04-19 08:48:53 +0000252 CXXMemberCallVisitor Visitor;
253 Visitor.ExpectMatch("Y::x", 4, 5);
254 EXPECT_TRUE(Visitor.runOver(
255 "struct Y { void x(); };\n"
256 "template<typename T> struct Z {\n"
257 " template<typename U> static void f() {\n"
258 " T().x();\n"
259 " }\n"
260 "};\n"
261 "void foo() { Z<Y>::f<int>(); }"));
262}
Richard Smith5482dc32012-04-24 20:39:49 +0000263
264TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
265 CXXMemberCallVisitor Visitor;
266 Visitor.ExpectMatch("A::x", 5, 7);
267 EXPECT_TRUE(Visitor.runOver(
268 "template <typename T1> struct X {\n"
269 " template <typename T2> struct Y {\n"
270 " void f() {\n"
271 " T2 y;\n"
272 " y.x();\n"
273 " }\n"
274 " };\n"
275 "};\n"
276 "struct A { void x(); };\n"
277 "int main() {\n"
278 " (new X<A>::Y<A>())->f();\n"
279 "}"));
280}
Manuel Klimekfad7f852012-04-19 08:48:53 +0000281
282/* FIXME: According to Richard Smith this is a bug in the AST.
283TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
284 DeclRefExprVisitor Visitor;
285 Visitor.ExpectMatch("x", 3, 43);
286 EXPECT_TRUE(Visitor.runOver(
287 "template <typename T> void x();\n"
288 "template <void (*T)()> class X {};\n"
289 "template <typename T> class Y : public X< x<T> > {};\n"
290 "Y<int> y;"));
291}
292*/
293
Richard Smitha313b2f2012-04-25 22:57:25 +0000294TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
295 CXXMemberCallVisitor Visitor;
296 Visitor.ExpectMatch("A::x", 6, 20);
297 EXPECT_TRUE(Visitor.runOver(
298 "template <typename T1> struct X {\n"
299 " template <typename T2, bool B> struct Y { void g(); };\n"
300 "};\n"
301 "template <typename T1> template <typename T2>\n"
302 "struct X<T1>::Y<T2, true> {\n"
303 " void f() { T2 y; y.x(); }\n"
304 "};\n"
305 "struct A { void x(); };\n"
306 "int main() {\n"
307 " (new X<A>::Y<A, true>())->f();\n"
308 "}\n"));
309}
310
Richard Smith06cd51a2012-05-09 23:51:36 +0000311TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
312 CXXMemberCallVisitor Visitor;
313 Visitor.ExpectMatch("A::f", 4, 5);
314 EXPECT_TRUE(Visitor.runOver(
315 "struct A {\n"
316 " void f() const {}\n"
317 " template<class T> void g(const T& t) const {\n"
318 " t.f();\n"
319 " }\n"
320 "};\n"
321 "template void A::g(const A& a) const;\n"));
322}
323
Richard Smitha313b2f2012-04-25 22:57:25 +0000324TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
325 // From cfe-commits/Week-of-Mon-20100830/033998.html
Daniel Jaspere966bea2012-05-30 04:30:08 +0000326 // Contrary to the approach suggested in that email, we visit all
Richard Smitha313b2f2012-04-25 22:57:25 +0000327 // specializations when we visit the primary template. Visiting them when we
328 // visit the associated specialization is problematic for specializations of
329 // template members of class templates.
330 NamedDeclVisitor Visitor;
331 Visitor.ExpectMatch("A<bool>", 1, 26);
332 Visitor.ExpectMatch("A<char *>", 2, 26);
333 EXPECT_TRUE(Visitor.runOver(
334 "template <class T> class A {};\n"
335 "template <class T> class A<T*> {};\n"
336 "A<bool> ab;\n"
337 "A<char*> acp;\n"));
338}
339
340TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
341 NamedDeclVisitor Visitor;
342 Visitor.ExpectMatch("A<int>", 1, 29);
343 EXPECT_TRUE(Visitor.runOver(
344 "template<typename T> struct A;\n"
345 "A<int> *p;\n"));
346}
347
348TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
349 NamedDeclVisitor Visitor;
350 Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
351 EXPECT_TRUE(Visitor.runOver(
352 "template<typename T> struct A {\n"
353 " template<typename U> struct B;\n"
354 "};\n"
355 "A<int>::B<char> *p;\n"));
356}
357
358TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
359 NamedDeclVisitor Visitor;
360 Visitor.ExpectMatch("A<int>", 1, 26);
361 EXPECT_TRUE(Visitor.runOver(
362 "template<typename T> int A();\n"
363 "int k = A<int>();\n"));
364}
365
366TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
367 NamedDeclVisitor Visitor;
368 Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
369 EXPECT_TRUE(Visitor.runOver(
370 "template<typename T> struct A {\n"
371 " template<typename U> static int B();\n"
372 "};\n"
373 "int k = A<int>::B<char>();\n"));
374}
375
376TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
377 // From cfe-commits/Week-of-Mon-20100830/033977.html
378 NamedDeclVisitor Visitor;
379 Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
380 EXPECT_TRUE(Visitor.runOver(
381 "template<typename Container>\n"
382 "class vector_iterator {\n"
383 " template <typename C> friend class vector_iterator;\n"
384 "};\n"
385 "vector_iterator<int> it_int;\n"));
386}
387
Richard Smithc8c22282012-05-02 00:30:48 +0000388TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
389 CXXOperatorCallExprTraverser Visitor;
390 Visitor.ExpectMatch("()", 4, 9);
391 EXPECT_TRUE(Visitor.runOver(
392 "struct A {\n"
393 " int operator()();\n"
394 "} a;\n"
395 "int k = a();\n"));
396}
397
398TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
399 ParenExprVisitor Visitor;
400 Visitor.ExpectMatch("", 1, 9);
401 EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
402}
403
Richard Smith6fada8e2012-05-30 23:55:51 +0000404TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
405 CXXBoolLiteralExprVisitor Visitor;
406 Visitor.ExpectMatch("true", 2, 19);
407 EXPECT_TRUE(Visitor.runOver(
408 "template<bool B> class X;\n"
409 "template<bool B = true> class Y;\n"
410 "template<bool B> class Y {};\n"));
411}
412
413TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) {
414 TypeLocVisitor Visitor;
415 Visitor.ExpectMatch("class X", 2, 23);
416 EXPECT_TRUE(Visitor.runOver(
417 "class X;\n"
418 "template<typename T = X> class Y;\n"
419 "template<typename T> class Y {};\n"));
420}
421
422TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
423 TemplateArgumentLocTraverser Visitor;
424 Visitor.ExpectMatch("X", 2, 40);
425 EXPECT_TRUE(Visitor.runOver(
426 "template<typename T> class X;\n"
427 "template<template <typename> class T = X> class Y;\n"
428 "template<template <typename> class T> class Y {};\n"));
429}
430
Richard Smithc28a3352012-06-05 16:18:26 +0000431// A visitor that visits implicit declarations and matches constructors.
432class ImplicitCtorVisitor
433 : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
434public:
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000435 bool shouldVisitImplicitCode() const { return true; }
Richard Smithc28a3352012-06-05 16:18:26 +0000436
437 bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
438 if (Ctor->isImplicit()) { // Was not written in source code
439 if (const CXXRecordDecl* Class = Ctor->getParent()) {
440 Match(Class->getName(), Ctor->getLocation());
441 }
442 }
443 return true;
444 }
445};
446
447TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
448 ImplicitCtorVisitor Visitor;
449 Visitor.ExpectMatch("Simple", 2, 8);
450 // Note: Clang lazily instantiates implicit declarations, so we need
451 // to use them in order to force them to appear in the AST.
452 EXPECT_TRUE(Visitor.runOver(
453 "struct WithCtor { WithCtor(); }; \n"
454 "struct Simple { Simple(); WithCtor w; }; \n"
455 "int main() { Simple s; Simple t(s); }\n"));
456}
457
James Dennett8268fe72012-08-24 06:59:51 +0000458/// \brief A visitor that optionally includes implicit code and matches
459/// CXXConstructExpr.
460///
461/// The name recorded for the match is the name of the class whose constructor
462/// is invoked by the CXXConstructExpr, not the name of the class whose
463/// constructor the CXXConstructExpr is contained in.
464class ConstructExprVisitor
465 : public ExpectedLocationVisitor<ConstructExprVisitor> {
466public:
467 ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
468
469 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
470
471 void setShouldVisitImplicitCode(bool NewValue) {
472 ShouldVisitImplicitCode = NewValue;
473 }
474
475 bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
476 if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
477 if (const CXXRecordDecl* Class = Ctor->getParent()) {
478 Match(Class->getName(), Expr->getLocation());
479 }
480 }
481 return true;
482 }
483
484 private:
485 bool ShouldVisitImplicitCode;
486};
487
488TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
489 ConstructExprVisitor Visitor;
490 Visitor.setShouldVisitImplicitCode(true);
491 Visitor.ExpectMatch("WithCtor", 2, 8);
492 // Simple has a constructor that implicitly initializes 'w'. Test
493 // that a visitor that visits implicit code visits that initialization.
494 // Note: Clang lazily instantiates implicit declarations, so we need
495 // to use them in order to force them to appear in the AST.
496 EXPECT_TRUE(Visitor.runOver(
497 "struct WithCtor { WithCtor(); }; \n"
498 "struct Simple { WithCtor w; }; \n"
499 "int main() { Simple s; }\n"));
500}
501
502// The same as CanVisitImplicitMemberInitializations, but checking that the
503// visits are omitted when the visitor does not include implicit code.
504TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
505 ConstructExprVisitor Visitor;
506 Visitor.setShouldVisitImplicitCode(false);
507 Visitor.DisallowMatch("WithCtor", 2, 8);
508 // Simple has a constructor that implicitly initializes 'w'. Test
509 // that a visitor that skips implicit code skips that initialization.
510 // Note: Clang lazily instantiates implicit declarations, so we need
511 // to use them in order to force them to appear in the AST.
512 EXPECT_TRUE(Visitor.runOver(
513 "struct WithCtor { WithCtor(); }; \n"
514 "struct Simple { WithCtor w; }; \n"
515 "int main() { Simple s; }\n"));
516}
517
Richard Smith0652c352012-08-17 03:20:55 +0000518TEST(RecursiveASTVisitor, VisitsExtension) {
519 DeclRefExprVisitor Visitor;
520 Visitor.ExpectMatch("s", 1, 24);
521 EXPECT_TRUE(Visitor.runOver(
522 "int s = __extension__ (s);\n"));
523}
524
Richard Smith82b45502012-08-17 21:23:17 +0000525TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) {
526 TypeLocVisitor Visitor;
527 Visitor.ExpectMatch("struct S", 1, 26);
528 EXPECT_TRUE(Visitor.runOver(
529 "int f() { return (struct S { int a; }){.a = 0}.a; }",
530 TypeLocVisitor::Lang_C));
531}
532
James Dennett89faf862013-06-30 03:13:35 +0000533TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
534 LambdaExprVisitor Visitor;
535 Visitor.ExpectMatch("", 1, 12);
536 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
537 LambdaExprVisitor::Lang_CXX11));
538}
539
James Dennett49007d72013-07-10 18:29:15 +0000540TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
541 LambdaExprVisitor Visitor;
542 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
543 LambdaExprVisitor::Lang_CXX11));
544 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
545}
546
James Dennettf68af642013-08-09 23:08:25 +0000547TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
548 LambdaDefaultCaptureVisitor Visitor;
549 Visitor.ExpectMatch("", 1, 20);
550 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
551 LambdaDefaultCaptureVisitor::Lang_CXX11));
552}
553
James Dennette3efec22013-09-05 17:46:21 +0000554// Checks for lambda classes that are not marked as implicitly-generated.
555// (There should be none.)
556class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
557public:
558 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
559 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
560 if (record->isLambda() && !record->isImplicit())
561 SawNonImplicitLambdaClass = true;
562 return true;
563 }
564
565 bool sawOnlyImplicitLambdaClasses() const {
566 return !SawNonImplicitLambdaClass;
567 }
568
569private:
570 bool SawNonImplicitLambdaClass;
571};
572
573TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
574 ClassVisitor Visitor;
575 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};",
576 ClassVisitor::Lang_CXX11));
577 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
578}
579
Manuel Klimekfad7f852012-04-19 08:48:53 +0000580} // end namespace clang