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