1 //===- unittest/Tooling/RecursiveASTVisitorTest.cpp -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "TestVisitor.h"
13 using namespace clang;
17 class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
19 bool VisitLambdaExpr(LambdaExpr *Lambda) {
20 PendingBodies.push(Lambda);
21 Match("", Lambda->getIntroducerRange().getBegin());
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);
30 return TraverseStmt(Lambda->getBody());
32 /// Determine whether TraverseLambdaBody has been called for every call to
34 bool allBodiesHaveBeenTraversed() const {
35 return PendingBodies.empty();
38 std::stack<LambdaExpr *> PendingBodies;
41 TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
42 LambdaExprVisitor Visitor;
43 Visitor.ExpectMatch("", 1, 12);
44 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
45 LambdaExprVisitor::Lang_CXX11));
48 TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
49 LambdaExprVisitor Visitor;
50 EXPECT_TRUE(Visitor.runOver("void f() { []{ return; }(); }",
51 LambdaExprVisitor::Lang_CXX11));
52 EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
55 TEST(RecursiveASTVisitor, VisitsAttributedLambdaExpr) {
56 LambdaExprVisitor Visitor;
57 Visitor.ExpectMatch("", 1, 12);
58 EXPECT_TRUE(Visitor.runOver(
59 "void f() { [] () __attribute__ (( fastcall )) { return; }(); }",
60 LambdaExprVisitor::Lang_CXX14));
63 // Matches the (optional) capture-default of a lambda-introducer.
64 class LambdaDefaultCaptureVisitor
65 : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
67 bool VisitLambdaExpr(LambdaExpr *Lambda) {
68 if (Lambda->getCaptureDefault() != LCD_None) {
69 Match("", Lambda->getCaptureDefaultLoc());
75 TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
76 LambdaDefaultCaptureVisitor Visitor;
77 Visitor.ExpectMatch("", 1, 20);
78 EXPECT_TRUE(Visitor.runOver("void f() { int a; [=]{a;}; }",
79 LambdaDefaultCaptureVisitor::Lang_CXX11));
82 // Checks for lambda classes that are not marked as implicitly-generated.
83 // (There should be none.)
84 class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
86 ClassVisitor() : SawNonImplicitLambdaClass(false) {}
87 bool VisitCXXRecordDecl(CXXRecordDecl* record) {
88 if (record->isLambda() && !record->isImplicit())
89 SawNonImplicitLambdaClass = true;
93 bool sawOnlyImplicitLambdaClasses() const {
94 return !SawNonImplicitLambdaClass;
98 bool SawNonImplicitLambdaClass;
101 TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
102 ClassVisitor Visitor;
103 EXPECT_TRUE(Visitor.runOver("auto lambda = []{};", ClassVisitor::Lang_CXX11));
104 EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
108 // Check to ensure that attributes and expressions within them are being
110 class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
112 bool VisitMemberExpr(MemberExpr *ME) {
113 Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
116 bool VisitAttr(Attr *A) {
117 Match("Attr", A->getLocation());
120 bool VisitGuardedByAttr(GuardedByAttr *A) {
121 Match("guarded_by", A->getLocation());
127 TEST(RecursiveASTVisitor, AttributesAreVisited) {
129 Visitor.ExpectMatch("Attr", 4, 24);
130 Visitor.ExpectMatch("guarded_by", 4, 24);
131 Visitor.ExpectMatch("mu1", 4, 35);
132 Visitor.ExpectMatch("Attr", 5, 29);
133 Visitor.ExpectMatch("mu1", 5, 54);
134 Visitor.ExpectMatch("mu2", 5, 59);
135 EXPECT_TRUE(Visitor.runOver(
139 " int a __attribute__((guarded_by(mu1)));\n"
140 " void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n"
144 // Check to ensure that implicit default argument expressions are visited.
145 class IntegerLiteralVisitor
146 : public ExpectedLocationVisitor<IntegerLiteralVisitor> {
148 bool VisitIntegerLiteral(const IntegerLiteral *IL) {
149 Match("literal", IL->getLocation());
154 TEST(RecursiveASTVisitor, DefaultArgumentsAreVisited) {
155 IntegerLiteralVisitor Visitor;
156 Visitor.ExpectMatch("literal", 1, 15, 2);
157 EXPECT_TRUE(Visitor.runOver("int f(int i = 1);\n"
158 "static int k = f();\n"));
161 // Check to ensure that InitListExpr is visited twice, once each for the
162 // syntactic and semantic form.
163 class InitListExprPreOrderVisitor
164 : public ExpectedLocationVisitor<InitListExprPreOrderVisitor> {
166 bool VisitInitListExpr(InitListExpr *ILE) {
167 Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
172 class InitListExprPostOrderVisitor
173 : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
175 bool shouldTraversePostOrder() const { return true; }
177 bool VisitInitListExpr(InitListExpr *ILE) {
178 Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
183 class InitListExprPreOrderNoQueueVisitor
184 : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
186 bool TraverseInitListExpr(InitListExpr *ILE) {
187 return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
190 bool VisitInitListExpr(InitListExpr *ILE) {
191 Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
196 class InitListExprPostOrderNoQueueVisitor
197 : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
199 bool shouldTraversePostOrder() const { return true; }
201 bool TraverseInitListExpr(InitListExpr *ILE) {
202 return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
205 bool VisitInitListExpr(InitListExpr *ILE) {
206 Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
211 TEST(RecursiveASTVisitor, InitListExprIsPreOrderVisitedTwice) {
212 InitListExprPreOrderVisitor Visitor;
213 Visitor.ExpectMatch("syntactic", 2, 21);
214 Visitor.ExpectMatch("semantic", 2, 21);
215 EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
216 "static struct S s = {.x = 0};\n",
217 InitListExprPreOrderVisitor::Lang_C));
220 TEST(RecursiveASTVisitor, InitListExprIsPostOrderVisitedTwice) {
221 InitListExprPostOrderVisitor Visitor;
222 Visitor.ExpectMatch("syntactic", 2, 21);
223 Visitor.ExpectMatch("semantic", 2, 21);
224 EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
225 "static struct S s = {.x = 0};\n",
226 InitListExprPostOrderVisitor::Lang_C));
229 TEST(RecursiveASTVisitor, InitListExprIsPreOrderNoQueueVisitedTwice) {
230 InitListExprPreOrderNoQueueVisitor Visitor;
231 Visitor.ExpectMatch("syntactic", 2, 21);
232 Visitor.ExpectMatch("semantic", 2, 21);
233 EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
234 "static struct S s = {.x = 0};\n",
235 InitListExprPreOrderNoQueueVisitor::Lang_C));
238 TEST(RecursiveASTVisitor, InitListExprIsPostOrderNoQueueVisitedTwice) {
239 InitListExprPostOrderNoQueueVisitor Visitor;
240 Visitor.ExpectMatch("syntactic", 2, 21);
241 Visitor.ExpectMatch("semantic", 2, 21);
242 EXPECT_TRUE(Visitor.runOver("struct S { int x; };\n"
243 "static struct S s = {.x = 0};\n",
244 InitListExprPostOrderNoQueueVisitor::Lang_C));
247 // Check to ensure that nested name specifiers are visited.
248 class NestedNameSpecifiersVisitor
249 : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
251 bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
254 Match(RTL.getDecl()->getName(), RTL.getNameLoc());
258 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
261 if (const NamespaceDecl *ND =
262 NNS.getNestedNameSpecifier()->getAsNamespace())
263 Match(ND->getName(), NNS.getLocalBeginLoc());
264 return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
268 TEST(RecursiveASTVisitor,
269 NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
270 StringRef Source = R"(
273 template<typename T, typename U>
282 struct ns::Outer::Nested<int, int>;
285 struct ns::Outer::Nested<int, int> { };
288 struct ns::Outer::Nested<int, T> { };
291 int ns::Outer::x<int> = 0;
293 NestedNameSpecifiersVisitor Visitor;
294 Visitor.ExpectMatch("ns", 13, 8);
295 Visitor.ExpectMatch("ns", 16, 8);
296 Visitor.ExpectMatch("ns", 19, 8);
297 Visitor.ExpectMatch("ns", 22, 5);
298 Visitor.ExpectMatch("Outer", 13, 12);
299 Visitor.ExpectMatch("Outer", 16, 12);
300 Visitor.ExpectMatch("Outer", 19, 12);
301 Visitor.ExpectMatch("Outer", 22, 9);
302 EXPECT_TRUE(Visitor.runOver(Source, NestedNameSpecifiersVisitor::Lang_CXX14));
305 } // end anonymous namespace