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:
VisitLambdaExpr(LambdaExpr * Lambda)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.
TraverseLambdaBody(LambdaExpr * Lambda)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.
allBodiesHaveBeenTraversed() const34 bool allBodiesHaveBeenTraversed() const {
35 return PendingBodies.empty();
36 }
37 private:
38 std::stack<LambdaExpr *> PendingBodies;
39 };
40
TEST(RecursiveASTVisitor,VisitsLambdaExpr)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
TEST(RecursiveASTVisitor,TraverseLambdaBodyCanBeOverridden)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:
VisitLambdaExpr(LambdaExpr * Lambda)59 bool VisitLambdaExpr(LambdaExpr *Lambda) {
60 if (Lambda->getCaptureDefault() != LCD_None) {
61 Match("", Lambda->getCaptureDefaultLoc());
62 }
63 return true;
64 }
65 };
66
TEST(RecursiveASTVisitor,HasCaptureDefaultLoc)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:
ClassVisitor()78 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
VisitCXXRecordDecl(CXXRecordDecl * record)79 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
80 if (record->isLambda() && !record->isImplicit())
81 SawNonImplicitLambdaClass = true;
82 return true;
83 }
84
sawOnlyImplicitLambdaClasses() const85 bool sawOnlyImplicitLambdaClasses() const {
86 return !SawNonImplicitLambdaClass;
87 }
88
89 private:
90 bool SawNonImplicitLambdaClass;
91 };
92
TEST(RecursiveASTVisitor,LambdaClosureTypesAreImplicit)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:
VisitMemberExpr(MemberExpr * ME)105 bool VisitMemberExpr(MemberExpr *ME) {
106 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
107 return true;
108 }
VisitAttr(Attr * A)109 bool VisitAttr(Attr *A) {
110 Match("Attr", A->getLocation());
111 return true;
112 }
VisitGuardedByAttr(GuardedByAttr * A)113 bool VisitGuardedByAttr(GuardedByAttr *A) {
114 Match("guarded_by", A->getLocation());
115 return true;
116 }
117 };
118
119
TEST(RecursiveASTVisitor,AttributesAreVisited)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