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 LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> { 18 public: 19 bool VisitLambdaExpr(LambdaExpr *Lambda) { 20 PendingBodies.push(Lambda); 21 Match("", Lambda->getIntroducerRange().getBegin()); 22 return true; 23 } 24 /// For each call to VisitLambdaExpr, we expect a subsequent call (with 25 /// proper nesting) to TraverseLambdaBody. 26 bool TraverseLambdaBody(LambdaExpr *Lambda) { 27 EXPECT_FALSE(PendingBodies.empty()); 28 EXPECT_EQ(PendingBodies.top(), Lambda); 29 PendingBodies.pop(); 30 return TraverseStmt(Lambda->getBody()); 31 } 32 /// Determine whether TraverseLambdaBody has been called for every call to 33 /// VisitLambdaExpr. 34 bool allBodiesHaveBeenTraversed() const { 35 return PendingBodies.empty(); 36 } 37 private: 38 std::stack<LambdaExpr *> PendingBodies; 39 }; 40 41 TEST(RecursiveASTVisitor, VisitsLambdaExpr) { 42 LambdaExprVisitor Visitor; 43 Visitor.ExpectMatch("", 1, 12); 44 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }", 45 LambdaExprVisitor::Lang_CXX11)); 46 } 47 48 TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) { 49 LambdaExprVisitor Visitor; 50 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }", 51 LambdaExprVisitor::Lang_CXX11)); 52 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed()); 53 } 54 55 // Matches the (optional) capture-default of a lambda-introducer. 56 class LambdaDefaultCaptureVisitor 57 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> { 58 public: 59 bool VisitLambdaExpr(LambdaExpr *Lambda) { 60 if (Lambda->getCaptureDefault() != LCD_None) { 61 Match("", Lambda->getCaptureDefaultLoc()); 62 } 63 return true; 64 } 65 }; 66 67 TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) { 68 LambdaDefaultCaptureVisitor Visitor; 69 Visitor.ExpectMatch("", 1, 20); 70 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }", 71 LambdaDefaultCaptureVisitor::Lang_CXX11)); 72 } 73 74 // Checks for lambda classes that are not marked as implicitly-generated. 75 // (There should be none.) 76 class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> { 77 public: 78 ClassVisitor() : SawNonImplicitLambdaClass(false) {} 79 bool VisitCXXRecordDecl(CXXRecordDecl* record) { 80 if (record->isLambda() && !record->isImplicit()) 81 SawNonImplicitLambdaClass = true; 82 return true; 83 } 84 85 bool sawOnlyImplicitLambdaClasses() const { 86 return !SawNonImplicitLambdaClass; 87 } 88 89 private: 90 bool SawNonImplicitLambdaClass; 91 }; 92 93 TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) { 94 ClassVisitor Visitor; 95 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};", ClassVisitor::Lang_CXX11)); 96 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses()); 97 } 98 99 100 // Check to ensure that attributes and expressions within them are being 101 // visited. 102 class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> { 103 public: 104 bool VisitMemberExpr(MemberExpr *ME) { 105 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart()); 106 return true; 107 } 108 bool VisitAttr(Attr *A) { 109 Match("Attr", A->getLocation()); 110 return true; 111 } 112 bool VisitGuardedByAttr(GuardedByAttr *A) { 113 Match("guarded_by", A->getLocation()); 114 return true; 115 } 116 }; 117 118 119 TEST(RecursiveASTVisitor, AttributesAreVisited) { 120 AttrVisitor Visitor; 121 Visitor.ExpectMatch("Attr", 4, 24); 122 Visitor.ExpectMatch("guarded_by", 4, 24); 123 Visitor.ExpectMatch("mu1", 4, 35); 124 Visitor.ExpectMatch("Attr", 5, 29); 125 Visitor.ExpectMatch("mu1", 5, 54); 126 Visitor.ExpectMatch("mu2", 5, 59); 127 EXPECT_TRUE(Visitor.runOver( 128 "class Foo {\n" 129 " int mu1;\n" 130 " int mu2;\n" 131 " int a __attribute__((guarded_by(mu1)));\n" 132 " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n" 133 "};\n")); 134 } 135 136 // Check to ensure that VarDecls are visited. 137 class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { 138 public: 139 bool VisitVarDecl(VarDecl *VD) { 140 Match(VD->getNameAsString(), VD->getLocStart()); 141 return true; 142 } 143 }; 144 145 TEST(RecursiveASTVisitor, ArrayInitializersAreVisited) { 146 VarDeclVisitor Visitor; 147 Visitor.ExpectMatch("__i0", 1, 8); 148 EXPECT_TRUE( 149 Visitor.runOver("struct MyClass {\n" 150 " int c[1];\n" 151 " static MyClass Create() { return MyClass(); }\n" 152 "};\n")); 153 } 154 155 } // end anonymous namespace 156