blob: b1d6f4a37c07177b46ca2d74dc7a46ad5407d9e1 [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
Manuel Klimekfad7f852012-04-19 08:48:53 +000040class CXXMemberCallVisitor
41 : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
42public:
43 bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
44 Match(Call->getMethodDecl()->getQualifiedNameAsString(),
45 Call->getLocStart());
46 return true;
47 }
48};
49
Richard Smitha313b2f2012-04-25 22:57:25 +000050class NamedDeclVisitor
51 : public ExpectedLocationVisitor<NamedDeclVisitor> {
52public:
53 bool VisitNamedDecl(NamedDecl *Decl) {
54 std::string NameWithTemplateArgs;
Benjamin Kramer5eada842013-02-22 15:46:01 +000055 llvm::raw_string_ostream OS(NameWithTemplateArgs);
56 Decl->getNameForDiagnostic(OS,
Richard Smitha313b2f2012-04-25 22:57:25 +000057 Decl->getASTContext().getPrintingPolicy(),
58 true);
Benjamin Kramer5eada842013-02-22 15:46:01 +000059 Match(OS.str(), Decl->getLocation());
Richard Smitha313b2f2012-04-25 22:57:25 +000060 return true;
61 }
62};
63
Richard Smithc8c22282012-05-02 00:30:48 +000064class CXXOperatorCallExprTraverser
65 : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
66public:
67 // Use Traverse, not Visit, to check that data recursion optimization isn't
68 // bypassing the call of this function.
69 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
70 Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
71 return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
72 TraverseCXXOperatorCallExpr(CE);
73 }
74};
75
76class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
77public:
78 bool VisitParenExpr(ParenExpr *Parens) {
79 Match("", Parens->getExprLoc());
80 return true;
81 }
82};
83
James Dennett89faf862013-06-30 03:13:35 +000084class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
85public:
86 bool VisitLambdaExpr(LambdaExpr *Lambda) {
James Dennett49007d72013-07-10 18:29:15 +000087 PendingBodies.push(Lambda);
James Dennett89faf862013-06-30 03:13:35 +000088 Match("", Lambda->getIntroducerRange().getBegin());
89 return true;
90 }
James Dennett49007d72013-07-10 18:29:15 +000091 /// For each call to VisitLambdaExpr, we expect a subsequent call (with
92 /// proper nesting) to TraverseLambdaBody.
93 bool TraverseLambdaBody(LambdaExpr *Lambda) {
94 EXPECT_FALSE(PendingBodies.empty());
95 EXPECT_EQ(PendingBodies.top(), Lambda);
96 PendingBodies.pop();
97 return TraverseStmt(Lambda->getBody());
98 }
99 /// Determine whether TraverseLambdaBody has been called for every call to
100 /// VisitLambdaExpr.
101 bool allBodiesHaveBeenTraversed() const {
102 return PendingBodies.empty();
103 }
104private:
James Dennettf68af642013-08-09 23:08:25 +0000105 std::stack<LambdaExpr *> PendingBodies;
106};
107
108// Matches the (optional) capture-default of a lambda-introducer.
109class LambdaDefaultCaptureVisitor
110 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
111public:
112 bool VisitLambdaExpr(LambdaExpr *Lambda) {
113 if (Lambda->getCaptureDefault() != LCD_None) {
114 Match("", Lambda->getCaptureDefaultLoc());
115 }
116 return true;
117 }
James Dennett89faf862013-06-30 03:13:35 +0000118};
119
Richard Smith6fada8e2012-05-30 23:55:51 +0000120class TemplateArgumentLocTraverser
121 : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
122public:
123 bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
124 std::string ArgStr;
125 llvm::raw_string_ostream Stream(ArgStr);
126 const TemplateArgument &Arg = ArgLoc.getArgument();
127
128 Arg.print(Context->getPrintingPolicy(), Stream);
129 Match(Stream.str(), ArgLoc.getLocation());
130 return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
131 TraverseTemplateArgumentLoc(ArgLoc);
132 }
133};
134
135class CXXBoolLiteralExprVisitor
136 : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
137public:
138 bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
139 if (BE->getValue())
140 Match("true", BE->getLocation());
141 else
142 Match("false", BE->getLocation());
143 return true;
144 }
145};
146
Manuel Klimekfad7f852012-04-19 08:48:53 +0000147TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
148 TypeLocVisitor Visitor;
149 Visitor.ExpectMatch("class X", 1, 30);
150 EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
151}
152
Manuel Klimek9f99d062012-04-23 16:40:40 +0000153TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) {
154 TypeLocVisitor Visitor;
155 Visitor.ExpectMatch("class X", 3, 18);
156 EXPECT_TRUE(Visitor.runOver(
157 "class Y;\n"
158 "class X {};\n"
159 "class Y : public X {};"));
160}
161
162TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) {
163 TypeLocVisitor Visitor;
164 Visitor.ExpectMatch("class X", 2, 18);
165 EXPECT_TRUE(Visitor.runOver(
166 "class X {};\n"
167 "class Y : public X { class Z; };"));
168}
169
170TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) {
171 TypeLocVisitor Visitor;
172 Visitor.ExpectMatch("X<class Y>", 2, 18);
173 EXPECT_TRUE(Visitor.runOver(
174 "template<typename T> class X {};\n"
175 "class Y : public X<Y> {};"));
176}
177
Manuel Klimekfad7f852012-04-19 08:48:53 +0000178TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
179 DeclRefExprVisitor Visitor;
180 Visitor.ExpectMatch("x", 2, 3);
181 EXPECT_TRUE(Visitor.runOver(
182 "void x(); template <void (*T)()> class X {};\nX<x> y;"));
183}
184
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000185TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
186 DeclRefExprVisitor Visitor;
187 Visitor.ExpectMatch("x", 2, 25);
Daniel Jasper1071ba92012-06-21 08:50:04 +0000188 Visitor.ExpectMatch("x", 2, 30);
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000189 EXPECT_TRUE(Visitor.runOver(
190 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000191 "void f() { for (int i : x) { x[0] = 1; } }",
192 DeclRefExprVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000193}
194
195TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
196 VarDeclVisitor Visitor;
197 Visitor.ExpectMatch("i", 2, 17);
198 EXPECT_TRUE(Visitor.runOver(
199 "int x[5];\n"
James Dennett89faf862013-06-30 03:13:35 +0000200 "void f() { for (int i : x) {} }",
201 VarDeclVisitor::Lang_CXX11));
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000202}
203
Manuel Klimekfad7f852012-04-19 08:48:53 +0000204TEST(RecursiveASTVisitor, VisitsCallExpr) {
205 DeclRefExprVisitor Visitor;
206 Visitor.ExpectMatch("x", 1, 22);
207 EXPECT_TRUE(Visitor.runOver(
208 "void x(); void y() { x(); }"));
209}
210
211TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
212 CXXMemberCallVisitor Visitor;
213 Visitor.ExpectMatch("Y::x", 3, 3);
214 EXPECT_TRUE(Visitor.runOver(
215 "struct Y { void x(); };\n"
216 "template<typename T> void y(T t) {\n"
217 " t.x();\n"
218 "}\n"
219 "void foo() { y<Y>(Y()); }"));
220}
221
Richard Smith5482dc32012-04-24 20:39:49 +0000222TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
Manuel Klimekfad7f852012-04-19 08:48:53 +0000223 CXXMemberCallVisitor Visitor;
224 Visitor.ExpectMatch("Y::x", 4, 5);
225 EXPECT_TRUE(Visitor.runOver(
226 "struct Y { void x(); };\n"
227 "template<typename T> struct Z {\n"
228 " template<typename U> static void f() {\n"
229 " T().x();\n"
230 " }\n"
231 "};\n"
232 "void foo() { Z<Y>::f<int>(); }"));
233}
Richard Smith5482dc32012-04-24 20:39:49 +0000234
235TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
236 CXXMemberCallVisitor Visitor;
237 Visitor.ExpectMatch("A::x", 5, 7);
238 EXPECT_TRUE(Visitor.runOver(
239 "template <typename T1> struct X {\n"
240 " template <typename T2> struct Y {\n"
241 " void f() {\n"
242 " T2 y;\n"
243 " y.x();\n"
244 " }\n"
245 " };\n"
246 "};\n"
247 "struct A { void x(); };\n"
248 "int main() {\n"
249 " (new X<A>::Y<A>())->f();\n"
250 "}"));
251}
Manuel Klimekfad7f852012-04-19 08:48:53 +0000252
253/* FIXME: According to Richard Smith this is a bug in the AST.
254TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
255 DeclRefExprVisitor Visitor;
256 Visitor.ExpectMatch("x", 3, 43);
257 EXPECT_TRUE(Visitor.runOver(
258 "template <typename T> void x();\n"
259 "template <void (*T)()> class X {};\n"
260 "template <typename T> class Y : public X< x<T> > {};\n"
261 "Y<int> y;"));
262}
263*/
264
Richard Smitha313b2f2012-04-25 22:57:25 +0000265TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
266 CXXMemberCallVisitor Visitor;
267 Visitor.ExpectMatch("A::x", 6, 20);
268 EXPECT_TRUE(Visitor.runOver(
269 "template <typename T1> struct X {\n"
270 " template <typename T2, bool B> struct Y { void g(); };\n"
271 "};\n"
272 "template <typename T1> template <typename T2>\n"
273 "struct X<T1>::Y<T2, true> {\n"
274 " void f() { T2 y; y.x(); }\n"
275 "};\n"
276 "struct A { void x(); };\n"
277 "int main() {\n"
278 " (new X<A>::Y<A, true>())->f();\n"
279 "}\n"));
280}
281
Richard Smith06cd51a2012-05-09 23:51:36 +0000282TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
283 CXXMemberCallVisitor Visitor;
284 Visitor.ExpectMatch("A::f", 4, 5);
285 EXPECT_TRUE(Visitor.runOver(
286 "struct A {\n"
287 " void f() const {}\n"
288 " template<class T> void g(const T& t) const {\n"
289 " t.f();\n"
290 " }\n"
291 "};\n"
292 "template void A::g(const A& a) const;\n"));
293}
294
Richard Smitha313b2f2012-04-25 22:57:25 +0000295TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
296 // From cfe-commits/Week-of-Mon-20100830/033998.html
Daniel Jaspere966bea2012-05-30 04:30:08 +0000297 // Contrary to the approach suggested in that email, we visit all
Richard Smitha313b2f2012-04-25 22:57:25 +0000298 // specializations when we visit the primary template. Visiting them when we
299 // visit the associated specialization is problematic for specializations of
300 // template members of class templates.
301 NamedDeclVisitor Visitor;
302 Visitor.ExpectMatch("A<bool>", 1, 26);
303 Visitor.ExpectMatch("A<char *>", 2, 26);
304 EXPECT_TRUE(Visitor.runOver(
305 "template <class T> class A {};\n"
306 "template <class T> class A<T*> {};\n"
307 "A<bool> ab;\n"
308 "A<char*> acp;\n"));
309}
310
311TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
312 NamedDeclVisitor Visitor;
313 Visitor.ExpectMatch("A<int>", 1, 29);
314 EXPECT_TRUE(Visitor.runOver(
315 "template<typename T> struct A;\n"
316 "A<int> *p;\n"));
317}
318
319TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
320 NamedDeclVisitor Visitor;
321 Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
322 EXPECT_TRUE(Visitor.runOver(
323 "template<typename T> struct A {\n"
324 " template<typename U> struct B;\n"
325 "};\n"
326 "A<int>::B<char> *p;\n"));
327}
328
329TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
330 NamedDeclVisitor Visitor;
331 Visitor.ExpectMatch("A<int>", 1, 26);
332 EXPECT_TRUE(Visitor.runOver(
333 "template<typename T> int A();\n"
334 "int k = A<int>();\n"));
335}
336
337TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
338 NamedDeclVisitor Visitor;
339 Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
340 EXPECT_TRUE(Visitor.runOver(
341 "template<typename T> struct A {\n"
342 " template<typename U> static int B();\n"
343 "};\n"
344 "int k = A<int>::B<char>();\n"));
345}
346
347TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
348 // From cfe-commits/Week-of-Mon-20100830/033977.html
349 NamedDeclVisitor Visitor;
350 Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
351 EXPECT_TRUE(Visitor.runOver(
352 "template<typename Container>\n"
353 "class vector_iterator {\n"
354 " template <typename C> friend class vector_iterator;\n"
355 "};\n"
356 "vector_iterator<int> it_int;\n"));
357}
358
Richard Smithc8c22282012-05-02 00:30:48 +0000359TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
360 CXXOperatorCallExprTraverser Visitor;
361 Visitor.ExpectMatch("()", 4, 9);
362 EXPECT_TRUE(Visitor.runOver(
363 "struct A {\n"
364 " int operator()();\n"
365 "} a;\n"
366 "int k = a();\n"));
367}
368
369TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
370 ParenExprVisitor Visitor;
371 Visitor.ExpectMatch("", 1, 9);
372 EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
373}
374
Richard Smith6fada8e2012-05-30 23:55:51 +0000375TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
376 CXXBoolLiteralExprVisitor Visitor;
377 Visitor.ExpectMatch("true", 2, 19);
378 EXPECT_TRUE(Visitor.runOver(
379 "template<bool B> class X;\n"
380 "template<bool B = true> class Y;\n"
381 "template<bool B> class Y {};\n"));
382}
383
384TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) {
385 TypeLocVisitor Visitor;
386 Visitor.ExpectMatch("class X", 2, 23);
387 EXPECT_TRUE(Visitor.runOver(
388 "class X;\n"
389 "template<typename T = X> class Y;\n"
390 "template<typename T> class Y {};\n"));
391}
392
393TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
394 TemplateArgumentLocTraverser Visitor;
395 Visitor.ExpectMatch("X", 2, 40);
396 EXPECT_TRUE(Visitor.runOver(
397 "template<typename T> class X;\n"
398 "template<template <typename> class T = X> class Y;\n"
399 "template<template <typename> class T> class Y {};\n"));
400}
401
Richard Smithc28a3352012-06-05 16:18:26 +0000402// A visitor that visits implicit declarations and matches constructors.
403class ImplicitCtorVisitor
404 : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
405public:
Daniel Jasper52ec0c02012-06-13 07:12:33 +0000406 bool shouldVisitImplicitCode() const { return true; }
Richard Smithc28a3352012-06-05 16:18:26 +0000407
408 bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
409 if (Ctor->isImplicit()) { // Was not written in source code
410 if (const CXXRecordDecl* Class = Ctor->getParent()) {
411 Match(Class->getName(), Ctor->getLocation());
412 }
413 }
414 return true;
415 }
416};
417
418TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
419 ImplicitCtorVisitor Visitor;
420 Visitor.ExpectMatch("Simple", 2, 8);
421 // Note: Clang lazily instantiates implicit declarations, so we need
422 // to use them in order to force them to appear in the AST.
423 EXPECT_TRUE(Visitor.runOver(
424 "struct WithCtor { WithCtor(); }; \n"
425 "struct Simple { Simple(); WithCtor w; }; \n"
426 "int main() { Simple s; Simple t(s); }\n"));
427}
428
James Dennett8268fe72012-08-24 06:59:51 +0000429/// \brief A visitor that optionally includes implicit code and matches
430/// CXXConstructExpr.
431///
432/// The name recorded for the match is the name of the class whose constructor
433/// is invoked by the CXXConstructExpr, not the name of the class whose
434/// constructor the CXXConstructExpr is contained in.
435class ConstructExprVisitor
436 : public ExpectedLocationVisitor<ConstructExprVisitor> {
437public:
438 ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
439
440 bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
441
442 void setShouldVisitImplicitCode(bool NewValue) {
443 ShouldVisitImplicitCode = NewValue;
444 }
445
446 bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
447 if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
448 if (const CXXRecordDecl* Class = Ctor->getParent()) {
449 Match(Class->getName(), Expr->getLocation());
450 }
451 }
452 return true;
453 }
454
455 private:
456 bool ShouldVisitImplicitCode;
457};
458
459TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
460 ConstructExprVisitor Visitor;
461 Visitor.setShouldVisitImplicitCode(true);
462 Visitor.ExpectMatch("WithCtor", 2, 8);
463 // Simple has a constructor that implicitly initializes 'w'. Test
464 // that a visitor that visits implicit code visits that initialization.
465 // Note: Clang lazily instantiates implicit declarations, so we need
466 // to use them in order to force them to appear in the AST.
467 EXPECT_TRUE(Visitor.runOver(
468 "struct WithCtor { WithCtor(); }; \n"
469 "struct Simple { WithCtor w; }; \n"
470 "int main() { Simple s; }\n"));
471}
472
473// The same as CanVisitImplicitMemberInitializations, but checking that the
474// visits are omitted when the visitor does not include implicit code.
475TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
476 ConstructExprVisitor Visitor;
477 Visitor.setShouldVisitImplicitCode(false);
478 Visitor.DisallowMatch("WithCtor", 2, 8);
479 // Simple has a constructor that implicitly initializes 'w'. Test
480 // that a visitor that skips implicit code skips that initialization.
481 // Note: Clang lazily instantiates implicit declarations, so we need
482 // to use them in order to force them to appear in the AST.
483 EXPECT_TRUE(Visitor.runOver(
484 "struct WithCtor { WithCtor(); }; \n"
485 "struct Simple { WithCtor w; }; \n"
486 "int main() { Simple s; }\n"));
487}
488
Richard Smith0652c352012-08-17 03:20:55 +0000489TEST(RecursiveASTVisitor, VisitsExtension) {
490 DeclRefExprVisitor Visitor;
491 Visitor.ExpectMatch("s", 1, 24);
492 EXPECT_TRUE(Visitor.runOver(
493 "int s = __extension__ (s);\n"));
494}
495
Richard Smith82b45502012-08-17 21:23:17 +0000496TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) {
497 TypeLocVisitor Visitor;
498 Visitor.ExpectMatch("struct S", 1, 26);
499 EXPECT_TRUE(Visitor.runOver(
500 "int f() { return (struct S { int a; }){.a = 0}.a; }",
501 TypeLocVisitor::Lang_C));
502}
503
James Dennett89faf862013-06-30 03:13:35 +0000504TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
505 LambdaExprVisitor Visitor;
506 Visitor.ExpectMatch("", 1, 12);
507 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
508 LambdaExprVisitor::Lang_CXX11));
509}
510
James Dennett49007d72013-07-10 18:29:15 +0000511TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
512 LambdaExprVisitor Visitor;
513 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
514 LambdaExprVisitor::Lang_CXX11));
515 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
516}
517
James Dennettf68af642013-08-09 23:08:25 +0000518TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
519 LambdaDefaultCaptureVisitor Visitor;
520 Visitor.ExpectMatch("", 1, 20);
521 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
522 LambdaDefaultCaptureVisitor::Lang_CXX11));
523}
524
James Dennette3efec22013-09-05 17:46:21 +0000525// Checks for lambda classes that are not marked as implicitly-generated.
526// (There should be none.)
527class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
528public:
529 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
530 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
531 if (record->isLambda() && !record->isImplicit())
532 SawNonImplicitLambdaClass = true;
533 return true;
534 }
535
536 bool sawOnlyImplicitLambdaClasses() const {
537 return !SawNonImplicitLambdaClass;
538 }
539
540private:
541 bool SawNonImplicitLambdaClass;
542};
543
544TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
545 ClassVisitor Visitor;
546 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};",
547 ClassVisitor::Lang_CXX11));
548 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
549}
550
Manuel Klimekfad7f852012-04-19 08:48:53 +0000551} // end namespace clang