blob: 991ae8bb7f3d274a2879675d6f5edad27db6c6b5 [file] [log] [blame]
David Blaikieea7d8472012-04-26 20:39:46 +00001//===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===//
Manuel Klimek770691b2012-04-19 08:48:53 +00002//
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
Richard Smith87d8fb92012-06-24 23:56:26 +000010#include "TestVisitor.h"
James Dennett86e67a22013-07-10 18:29:15 +000011#include <stack>
12
Richard Smith1be902c2014-05-19 22:34:38 +000013using namespace clang;
14
15namespace {
Manuel Klimek770691b2012-04-19 08:48:53 +000016
James Dennett9ad99592013-06-30 03:13:35 +000017class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
18public:
19 bool VisitLambdaExpr(LambdaExpr *Lambda) {
James Dennett86e67a22013-07-10 18:29:15 +000020 PendingBodies.push(Lambda);
James Dennett9ad99592013-06-30 03:13:35 +000021 Match("", Lambda->getIntroducerRange().getBegin());
22 return true;
23 }
James Dennett86e67a22013-07-10 18:29:15 +000024 /// 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 }
37private:
James Dennettddd36ff2013-08-09 23:08:25 +000038 std::stack<LambdaExpr *> PendingBodies;
39};
40
James Dennett9ad99592013-06-30 03:13:35 +000041TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
42 LambdaExprVisitor Visitor;
43 Visitor.ExpectMatch("", 1, 12);
44 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
Nico Weber5fe41222016-01-22 14:12:44 +000045 LambdaExprVisitor::Lang_CXX11));
James Dennett9ad99592013-06-30 03:13:35 +000046}
47
James Dennett86e67a22013-07-10 18:29:15 +000048TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
49 LambdaExprVisitor Visitor;
50 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
Nico Weber5fe41222016-01-22 14:12:44 +000051 LambdaExprVisitor::Lang_CXX11));
James Dennett86e67a22013-07-10 18:29:15 +000052 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
53}
54
Manuel Klimek20c1c892014-10-09 15:02:06 +000055// Matches the (optional) capture-default of a lambda-introducer.
56class LambdaDefaultCaptureVisitor
57 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
58public:
59 bool VisitLambdaExpr(LambdaExpr *Lambda) {
60 if (Lambda->getCaptureDefault() != LCD_None) {
61 Match("", Lambda->getCaptureDefaultLoc());
62 }
63 return true;
64 }
65};
66
James Dennettddd36ff2013-08-09 23:08:25 +000067TEST(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
James Dennett8f60cdd2013-09-05 17:46:21 +000074// Checks for lambda classes that are not marked as implicitly-generated.
75// (There should be none.)
76class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
77public:
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
89private:
90 bool SawNonImplicitLambdaClass;
91};
92
93TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
94 ClassVisitor Visitor;
Nico Weber5fe41222016-01-22 14:12:44 +000095 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};", ClassVisitor::Lang_CXX11));
James Dennett8f60cdd2013-09-05 17:46:21 +000096 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
97}
98
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +000099
DeLesley Hutchinsc4a82432013-12-30 17:24:36 +0000100// Check to ensure that attributes and expressions within them are being
101// visited.
102class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
103public:
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
119TEST(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
Nico Weberc4acee32016-01-22 15:11:54 +0000136// Check to ensure that VarDecls are visited.
137class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
138public:
139 bool VisitVarDecl(VarDecl *VD) {
140 Match(VD->getNameAsString(), VD->getLocStart());
141 return true;
142 }
143};
144
145TEST(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
Richard Smith1be902c2014-05-19 22:34:38 +0000155} // end anonymous namespace