blob: b3a8915a59de5718979659cd23c0027790ba9802 [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
159// copy assignment operator.
160TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
161 ParmVarDeclVisitorForImplicitCode Visitor;
162 // Match parameter variable name of implicit copy assignment operator.
163 // 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);
167 EXPECT_TRUE(Visitor.runOver(
168 "class X {};\n"
169 "void foo(X a, X b) {a = b;}"));
170}
171
Manuel Klimekfad7f852012-04-19 08:48:53 +0000172TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
173 TypeLocVisitor Visitor;
174 Visitor.ExpectMatch("class X", 1, 30);
175 EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
176}
177
Manuel Klimek9f99d062012-04-23 16:40:40 +0000178TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) {
179 TypeLocVisitor Visitor;
180 Visitor.ExpectMatch("class X", 3, 18);
181 EXPECT_TRUE(Visitor.runOver(
182 "class Y;\n"
183 "class X {};\n"
184 "class Y : public X {};"));
185}
186
187TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) {
188 TypeLocVisitor Visitor;
189 Visitor.ExpectMatch("class X", 2, 18);
190 EXPECT_TRUE(Visitor.runOver(
191 "class X {};\n"
192 "class Y : public X { class Z; };"));
193}
194
195TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) {
196 TypeLocVisitor Visitor;
197 Visitor.ExpectMatch("X<class Y>", 2, 18);
198 EXPECT_TRUE(Visitor.runOver(
199 "template<typename T> class X {};\n"
200 "class Y : public X<Y> {};"));
201}
202
Manuel Klimekfad7f852012-04-19 08:48:53 +0000203TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
204 DeclRefExprVisitor Visitor;
205 Visitor.ExpectMatch("x", 2, 3);
206 EXPECT_TRUE(Visitor.runOver(
207 "void x(); template <void (*T)()> class X {};\nX<x> y;"));
208}
209
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000210TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
211 DeclRefExprVisitor Visitor;
212 Visitor.ExpectMatch("x", 2, 25);
Daniel Jasper1071ba92012-06-21 08:50:04 +0000213 Visitor.ExpectMatch("x", 2, 30);
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000214 EXPECT_TRUE(Visitor.runOver(
215 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000216 "void f() { for (int i : x) { x[0] = 1; } }",
217 DeclRefExprVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000218}
219
220TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
221 VarDeclVisitor Visitor;
222 Visitor.ExpectMatch("i", 2, 17);
223 EXPECT_TRUE(Visitor.runOver(
224 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000225 "void f() { for (int i : x) {} }",
226 VarDeclVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000227}
228
Manuel Klimekfad7f852012-04-19 08:48:53 +0000229TEST(RecursiveASTVisitor, VisitsCallExpr) {
230 DeclRefExprVisitor Visitor;
231 Visitor.ExpectMatch("x", 1, 22);
232 EXPECT_TRUE(Visitor.runOver(
233 "void x(); void y() { x(); }"));
234}
235
236TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
237 CXXMemberCallVisitor Visitor;
238 Visitor.ExpectMatch("Y::x", 3, 3);
239 EXPECT_TRUE(Visitor.runOver(
240 "struct Y { void x(); };\n"
241 "template<typename T> void y(T t) {\n"
242 " t.x();\n"
243 "}\n"
244 "void foo() { y<Y>(Y()); }"));
245}
246
Richard Smith5482dc32012-04-24 20:39:49 +0000247TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
Manuel Klimekfad7f852012-04-19 08:48:53 +0000248 CXXMemberCallVisitor Visitor;
249 Visitor.ExpectMatch("Y::x", 4, 5);
250 EXPECT_TRUE(Visitor.runOver(
251 "struct Y { void x(); };\n"
252 "template<typename T> struct Z {\n"
253 " template<typename U> static void f() {\n"
254 " T().x();\n"
255 " }\n"
256 "};\n"
257 "void foo() { Z<Y>::f<int>(); }"));
258}
Richard Smith5482dc32012-04-24 20:39:49 +0000259
260TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
261 CXXMemberCallVisitor Visitor;
262 Visitor.ExpectMatch("A::x", 5, 7);
263 EXPECT_TRUE(Visitor.runOver(
264 "template <typename T1> struct X {\n"
265 " template <typename T2> struct Y {\n"
266 " void f() {\n"
267 " T2 y;\n"
268 " y.x();\n"
269 " }\n"
270 " };\n"
271 "};\n"
272 "struct A { void x(); };\n"
273 "int main() {\n"
274 " (new X<A>::Y<A>())->f();\n"
275 "}"));
276}
Manuel Klimekfad7f852012-04-19 08:48:53 +0000277
278/* FIXME: According to Richard Smith this is a bug in the AST.
279TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
280 DeclRefExprVisitor Visitor;
281 Visitor.ExpectMatch("x", 3, 43);
282 EXPECT_TRUE(Visitor.runOver(
283 "template <typename T> void x();\n"
284 "template <void (*T)()> class X {};\n"
285 "template <typename T> class Y : public X< x<T> > {};\n"
286 "Y<int> y;"));
287}
288*/
289
Richard Smitha313b2f2012-04-25 22:57:25 +0000290TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
291 CXXMemberCallVisitor Visitor;
292 Visitor.ExpectMatch("A::x", 6, 20);
293 EXPECT_TRUE(Visitor.runOver(
294 "template <typename T1> struct X {\n"
295 " template <typename T2, bool B> struct Y { void g(); };\n"
296 "};\n"
297 "template <typename T1> template <typename T2>\n"
298 "struct X<T1>::Y<T2, true> {\n"
299 " void f() { T2 y; y.x(); }\n"
300 "};\n"
301 "struct A { void x(); };\n"
302 "int main() {\n"
303 " (new X<A>::Y<A, true>())->f();\n"
304 "}\n"));
305}
306
Richard Smith06cd51a2012-05-09 23:51:36 +0000307TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
308 CXXMemberCallVisitor Visitor;
309 Visitor.ExpectMatch("A::f", 4, 5);
310 EXPECT_TRUE(Visitor.runOver(
311 "struct A {\n"
312 " void f() const {}\n"
313 " template<class T> void g(const T& t) const {\n"
314 " t.f();\n"
315 " }\n"
316 "};\n"
317 "template void A::g(const A& a) const;\n"));
318}
319
Richard Smitha313b2f2012-04-25 22:57:25 +0000320TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
321 // From cfe-commits/Week-of-Mon-20100830/033998.html
Daniel Jaspere966bea2012-05-30 04:30:08 +0000322 // Contrary to the approach suggested in that email, we visit all
Richard Smitha313b2f2012-04-25 22:57:25 +0000323 // specializations when we visit the primary template. Visiting them when we
324 // visit the associated specialization is problematic for specializations of
325 // template members of class templates.
326 NamedDeclVisitor Visitor;
327 Visitor.ExpectMatch("A<bool>", 1, 26);
328 Visitor.ExpectMatch("A<char *>", 2, 26);
329 EXPECT_TRUE(Visitor.runOver(
330 "template <class T> class A {};\n"
331 "template <class T> class A<T*> {};\n"
332 "A<bool> ab;\n"
333 "A<char*> acp;\n"));
334}
335
336TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
337 NamedDeclVisitor Visitor;
338 Visitor.ExpectMatch("A<int>", 1, 29);
339 EXPECT_TRUE(Visitor.runOver(
340 "template<typename T> struct A;\n"
341 "A<int> *p;\n"));
342}
343
344TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
345 NamedDeclVisitor Visitor;
346 Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
347 EXPECT_TRUE(Visitor.runOver(
348 "template<typename T> struct A {\n"
349 " template<typename U> struct B;\n"
350 "};\n"
351 "A<int>::B<char> *p;\n"));
352}
353
354TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
355 NamedDeclVisitor Visitor;
356 Visitor.ExpectMatch("A<int>", 1, 26);
357 EXPECT_TRUE(Visitor.runOver(
358 "template<typename T> int A();\n"
359 "int k = A<int>();\n"));
360}
361
362TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
363 NamedDeclVisitor Visitor;
364 Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
365 EXPECT_TRUE(Visitor.runOver(
366 "template<typename T> struct A {\n"
367 " template<typename U> static int B();\n"
368 "};\n"
369 "int k = A<int>::B<char>();\n"));
370}
371
372TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
373 // From cfe-commits/Week-of-Mon-20100830/033977.html
374 NamedDeclVisitor Visitor;
375 Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
376 EXPECT_TRUE(Visitor.runOver(
377 "template<typename Container>\n"
378 "class vector_iterator {\n"
379 " template <typename C> friend class vector_iterator;\n"
380 "};\n"
381 "vector_iterator<int> it_int;\n"));
382}
383
Richard Smithc8c22282012-05-02 00:30:48 +0000384TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
385 CXXOperatorCallExprTraverser Visitor;
386 Visitor.ExpectMatch("()", 4, 9);
387 EXPECT_TRUE(Visitor.runOver(
388 "struct A {\n"
389 " int operator()();\n"
390 "} a;\n"
391 "int k = a();\n"));
392}
393
394TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
395 ParenExprVisitor Visitor;
396 Visitor.ExpectMatch("", 1, 9);
397 EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
398}
399
Richard Smith6fada8e2012-05-30 23:55:51 +0000400TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
401 CXXBoolLiteralExprVisitor Visitor;
402 Visitor.ExpectMatch("true", 2, 19);
403 EXPECT_TRUE(Visitor.runOver(
404 "template<bool B> class X;\n"
405 "template<bool B = true> class Y;\n"
406 "template<bool B> class Y {};\n"));
407}
408
409TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) {
410 TypeLocVisitor Visitor;
411 Visitor.ExpectMatch("class X", 2, 23);
412 EXPECT_TRUE(Visitor.runOver(
413 "class X;\n"
414 "template<typename T = X> class Y;\n"
415 "template<typename T> class Y {};\n"));
416}
417
418TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
419 TemplateArgumentLocTraverser Visitor;
420 Visitor.ExpectMatch("X", 2, 40);
421 EXPECT_TRUE(Visitor.runOver(
422 "template<typename T> class X;\n"
423 "template<template <typename> class T = X> class Y;\n"
424 "template<template <typename> class T> class Y {};\n"));
425}
426
Richard Smithc28a3352012-06-05 16:18:26 +0000427// A visitor that visits implicit declarations and matches constructors.
428class ImplicitCtorVisitor
429 : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
430public:
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000431 bool shouldVisitImplicitCode() const { return true; }
Richard Smithc28a3352012-06-05 16:18:26 +0000432
433 bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
434 if (Ctor->isImplicit()) { // Was not written in source code
435 if (const CXXRecordDecl* Class = Ctor->getParent()) {
436 Match(Class->getName(), Ctor->getLocation());
437 }
438 }
439 return true;
440 }
441};
442
443TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
444 ImplicitCtorVisitor Visitor;
445 Visitor.ExpectMatch("Simple", 2, 8);
446 // Note: Clang lazily instantiates implicit declarations, so we need
447 // to use them in order to force them to appear in the AST.
448 EXPECT_TRUE(Visitor.runOver(
449 "struct WithCtor { WithCtor(); }; \n"
450 "struct Simple { Simple(); WithCtor w; }; \n"
451 "int main() { Simple s; Simple t(s); }\n"));
452}
453
James Dennett8268fe72012-08-24 06:59:51 +0000454/// \brief A visitor that optionally includes implicit code and matches
455/// CXXConstructExpr.
456///
457/// The name recorded for the match is the name of the class whose constructor
458/// is invoked by the CXXConstructExpr, not the name of the class whose
459/// constructor the CXXConstructExpr is contained in.
460class ConstructExprVisitor
461 : public ExpectedLocationVisitor<ConstructExprVisitor> {
462public:
463 ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
464
465 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
466
467 void setShouldVisitImplicitCode(bool NewValue) {
468 ShouldVisitImplicitCode = NewValue;
469 }
470
471 bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
472 if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
473 if (const CXXRecordDecl* Class = Ctor->getParent()) {
474 Match(Class->getName(), Expr->getLocation());
475 }
476 }
477 return true;
478 }
479
480 private:
481 bool ShouldVisitImplicitCode;
482};
483
484TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
485 ConstructExprVisitor Visitor;
486 Visitor.setShouldVisitImplicitCode(true);
487 Visitor.ExpectMatch("WithCtor", 2, 8);
488 // Simple has a constructor that implicitly initializes 'w'. Test
489 // that a visitor that visits implicit code visits that initialization.
490 // Note: Clang lazily instantiates implicit declarations, so we need
491 // to use them in order to force them to appear in the AST.
492 EXPECT_TRUE(Visitor.runOver(
493 "struct WithCtor { WithCtor(); }; \n"
494 "struct Simple { WithCtor w; }; \n"
495 "int main() { Simple s; }\n"));
496}
497
498// The same as CanVisitImplicitMemberInitializations, but checking that the
499// visits are omitted when the visitor does not include implicit code.
500TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
501 ConstructExprVisitor Visitor;
502 Visitor.setShouldVisitImplicitCode(false);
503 Visitor.DisallowMatch("WithCtor", 2, 8);
504 // Simple has a constructor that implicitly initializes 'w'. Test
505 // that a visitor that skips implicit code skips that initialization.
506 // Note: Clang lazily instantiates implicit declarations, so we need
507 // to use them in order to force them to appear in the AST.
508 EXPECT_TRUE(Visitor.runOver(
509 "struct WithCtor { WithCtor(); }; \n"
510 "struct Simple { WithCtor w; }; \n"
511 "int main() { Simple s; }\n"));
512}
513
Richard Smith0652c352012-08-17 03:20:55 +0000514TEST(RecursiveASTVisitor, VisitsExtension) {
515 DeclRefExprVisitor Visitor;
516 Visitor.ExpectMatch("s", 1, 24);
517 EXPECT_TRUE(Visitor.runOver(
518 "int s = __extension__ (s);\n"));
519}
520
Richard Smith82b45502012-08-17 21:23:17 +0000521TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) {
522 TypeLocVisitor Visitor;
523 Visitor.ExpectMatch("struct S", 1, 26);
524 EXPECT_TRUE(Visitor.runOver(
525 "int f() { return (struct S { int a; }){.a = 0}.a; }",
526 TypeLocVisitor::Lang_C));
527}
528
James Dennett89faf862013-06-30 03:13:35 +0000529TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
530 LambdaExprVisitor Visitor;
531 Visitor.ExpectMatch("", 1, 12);
532 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
533 LambdaExprVisitor::Lang_CXX11));
534}
535
James Dennett49007d72013-07-10 18:29:15 +0000536TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
537 LambdaExprVisitor Visitor;
538 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
539 LambdaExprVisitor::Lang_CXX11));
540 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
541}
542
James Dennettf68af642013-08-09 23:08:25 +0000543TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
544 LambdaDefaultCaptureVisitor Visitor;
545 Visitor.ExpectMatch("", 1, 20);
546 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
547 LambdaDefaultCaptureVisitor::Lang_CXX11));
548}
549
James Dennette3efec22013-09-05 17:46:21 +0000550// Checks for lambda classes that are not marked as implicitly-generated.
551// (There should be none.)
552class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
553public:
554 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
555 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
556 if (record->isLambda() && !record->isImplicit())
557 SawNonImplicitLambdaClass = true;
558 return true;
559 }
560
561 bool sawOnlyImplicitLambdaClasses() const {
562 return !SawNonImplicitLambdaClass;
563 }
564
565private:
566 bool SawNonImplicitLambdaClass;
567};
568
569TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
570 ClassVisitor Visitor;
571 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};",
572 ClassVisitor::Lang_CXX11));
573 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
574}
575
Manuel Klimekfad7f852012-04-19 08:48:53 +0000576} // end namespace clang