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 = []{};", 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:
VisitMemberExpr(MemberExpr * ME)104 bool VisitMemberExpr(MemberExpr *ME) {
105 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
106 return true;
107 }
VisitAttr(Attr * A)108 bool VisitAttr(Attr *A) {
109 Match("Attr", A->getLocation());
110 return true;
111 }
VisitGuardedByAttr(GuardedByAttr * A)112 bool VisitGuardedByAttr(GuardedByAttr *A) {
113 Match("guarded_by", A->getLocation());
114 return true;
115 }
116 };
117
118
TEST(RecursiveASTVisitor,AttributesAreVisited)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:
VisitVarDecl(VarDecl * VD)139 bool VisitVarDecl(VarDecl *VD) {
140 Match(VD->getNameAsString(), VD->getLocStart());
141 return true;
142 }
143 };
144
TEST(RecursiveASTVisitor,ArrayInitializersAreVisited)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