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 = []{};", 96 ClassVisitor::Lang_CXX11)); 97 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses()); 98 } 99 100 101 // Check to ensure that attributes and expressions within them are being 102 // visited. 103 class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> { 104 public: 105 bool VisitMemberExpr(MemberExpr *ME) { 106 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart()); 107 return true; 108 } 109 bool VisitAttr(Attr *A) { 110 Match("Attr", A->getLocation()); 111 return true; 112 } 113 bool VisitGuardedByAttr(GuardedByAttr *A) { 114 Match("guarded_by", A->getLocation()); 115 return true; 116 } 117 }; 118 119 120 TEST(RecursiveASTVisitor, AttributesAreVisited) { 121 AttrVisitor Visitor; 122 Visitor.ExpectMatch("Attr", 4, 24); 123 Visitor.ExpectMatch("guarded_by", 4, 24); 124 Visitor.ExpectMatch("mu1", 4, 35); 125 Visitor.ExpectMatch("Attr", 5, 29); 126 Visitor.ExpectMatch("mu1", 5, 54); 127 Visitor.ExpectMatch("mu2", 5, 59); 128 EXPECT_TRUE(Visitor.runOver( 129 "class Foo {\n" 130 " int mu1;\n" 131 " int mu2;\n" 132 " int a __attribute__((guarded_by(mu1)));\n" 133 " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n" 134 "};\n")); 135 } 136 137 } // end anonymous namespace 138