xref: /minix3/external/bsd/llvm/dist/clang/unittests/Tooling/RecursiveASTVisitorTest.cpp (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1 //===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===//
2 //
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 
10 #include "TestVisitor.h"
11 
12 #include <stack>
13 
14 namespace clang {
15 
16 class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
17 public:
18   bool VisitTypeLoc(TypeLoc TypeLocation) {
19     Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
20     return true;
21   }
22 };
23 
24 class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
25 public:
26   bool VisitDeclRefExpr(DeclRefExpr *Reference) {
27     Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
28     return true;
29   }
30 };
31 
32 class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
33 public:
34  bool VisitVarDecl(VarDecl *Variable) {
35    Match(Variable->getNameAsString(), Variable->getLocStart());
36    return true;
37  }
38 };
39 
40 class ParmVarDeclVisitorForImplicitCode :
41   public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
42 public:
43   bool shouldVisitImplicitCode() const { return true; }
44 
45   bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
46     Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
47     return true;
48   }
49 };
50 
51 class CXXMemberCallVisitor
52   : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
53 public:
54   bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
55     Match(Call->getMethodDecl()->getQualifiedNameAsString(),
56           Call->getLocStart());
57     return true;
58   }
59 };
60 
61 class NamedDeclVisitor
62   : public ExpectedLocationVisitor<NamedDeclVisitor> {
63 public:
64   bool VisitNamedDecl(NamedDecl *Decl) {
65     std::string NameWithTemplateArgs;
66     llvm::raw_string_ostream OS(NameWithTemplateArgs);
67     Decl->getNameForDiagnostic(OS,
68                                Decl->getASTContext().getPrintingPolicy(),
69                                true);
70     Match(OS.str(), Decl->getLocation());
71     return true;
72   }
73 };
74 
75 class CXXOperatorCallExprTraverser
76   : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
77 public:
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 
87 class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
88 public:
89   bool VisitParenExpr(ParenExpr *Parens) {
90     Match("", Parens->getExprLoc());
91     return true;
92   }
93 };
94 
95 class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
96 public:
97   bool VisitLambdaExpr(LambdaExpr *Lambda) {
98     PendingBodies.push(Lambda);
99     Match("", Lambda->getIntroducerRange().getBegin());
100     return true;
101   }
102   /// 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   }
115 private:
116   std::stack<LambdaExpr *> PendingBodies;
117 };
118 
119 // Matches the (optional) capture-default of a lambda-introducer.
120 class LambdaDefaultCaptureVisitor
121   : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
122 public:
123   bool VisitLambdaExpr(LambdaExpr *Lambda) {
124     if (Lambda->getCaptureDefault() != LCD_None) {
125       Match("", Lambda->getCaptureDefaultLoc());
126     }
127     return true;
128   }
129 };
130 
131 class TemplateArgumentLocTraverser
132   : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
133 public:
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 
146 class CXXBoolLiteralExprVisitor
147   : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
148 public:
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 
158 // Test RAV visits parameter variable declaration of the implicit
159 // copy assignment operator and implicit copy constructor.
160 TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
161   ParmVarDeclVisitorForImplicitCode Visitor;
162   // Match parameter variable name of implicit copy assignment operator and
163   // implicit copy constructor.
164   // 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);
168   Visitor.ExpectMatch("", 3, 7);
169   EXPECT_TRUE(Visitor.runOver(
170     "class X {};\n"
171     "void foo(X a, X b) {a = b;}\n"
172     "class Y {};\n"
173     "void bar(Y a) {Y b = a;}"));
174 }
175 
176 TEST(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 
182 TEST(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 
191 TEST(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 
199 TEST(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 
207 TEST(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 
214 TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
215   DeclRefExprVisitor Visitor;
216   Visitor.ExpectMatch("x", 2, 25);
217   Visitor.ExpectMatch("x", 2, 30);
218   EXPECT_TRUE(Visitor.runOver(
219     "int x[5];\n"
220     "void f() { for (int i : x) { x[0] = 1; } }",
221     DeclRefExprVisitor::Lang_CXX11));
222 }
223 
224 TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
225   VarDeclVisitor Visitor;
226   Visitor.ExpectMatch("i", 2, 17);
227   EXPECT_TRUE(Visitor.runOver(
228     "int x[5];\n"
229     "void f() { for (int i : x) {} }",
230     VarDeclVisitor::Lang_CXX11));
231 }
232 
233 TEST(RecursiveASTVisitor, VisitsCallExpr) {
234   DeclRefExprVisitor Visitor;
235   Visitor.ExpectMatch("x", 1, 22);
236   EXPECT_TRUE(Visitor.runOver(
237     "void x(); void y() { x(); }"));
238 }
239 
240 TEST(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 
251 TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
252   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 }
263 
264 TEST(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 }
281 
282 /* FIXME: According to Richard Smith this is a bug in the AST.
283 TEST(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 
294 TEST(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 
311 TEST(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 
324 TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
325   // From cfe-commits/Week-of-Mon-20100830/033998.html
326   // Contrary to the approach suggested in that email, we visit all
327   // 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 
340 TEST(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 
348 TEST(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 
358 TEST(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 
366 TEST(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 
376 TEST(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 
388 TEST(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 
398 TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
399   ParenExprVisitor Visitor;
400   Visitor.ExpectMatch("", 1, 9);
401   EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
402 }
403 
404 TEST(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 
413 TEST(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 
422 TEST(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 
431 // A visitor that visits implicit declarations and matches constructors.
432 class ImplicitCtorVisitor
433     : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
434 public:
435   bool shouldVisitImplicitCode() const { return true; }
436 
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 
447 TEST(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 
458 /// \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.
464 class ConstructExprVisitor
465     : public ExpectedLocationVisitor<ConstructExprVisitor> {
466 public:
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 
488 TEST(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.
504 TEST(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 
518 TEST(RecursiveASTVisitor, VisitsExtension) {
519   DeclRefExprVisitor Visitor;
520   Visitor.ExpectMatch("s", 1, 24);
521   EXPECT_TRUE(Visitor.runOver(
522     "int s = __extension__ (s);\n"));
523 }
524 
525 TEST(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 
533 TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
534   LambdaExprVisitor Visitor;
535   Visitor.ExpectMatch("", 1, 12);
536   EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
537 			      LambdaExprVisitor::Lang_CXX11));
538 }
539 
540 TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
541   LambdaExprVisitor Visitor;
542   EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
543 			      LambdaExprVisitor::Lang_CXX11));
544   EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
545 }
546 
547 TEST(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 
554 // Checks for lambda classes that are not marked as implicitly-generated.
555 // (There should be none.)
556 class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
557 public:
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 
569 private:
570   bool SawNonImplicitLambdaClass;
571 };
572 
573 TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
574   ClassVisitor Visitor;
575   EXPECT_TRUE(Visitor.runOver("auto lambda = []{};",
576 			      ClassVisitor::Lang_CXX11));
577   EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
578 }
579 
580 } // end namespace clang
581