]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unittests/Tooling/RecursiveASTVisitorTest.cpp
Vendor import of clang trunk r321530:
[FreeBSD/FreeBSD.git] / unittests / Tooling / RecursiveASTVisitorTest.cpp
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 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));
61 }
62
63 // Matches the (optional) capture-default of a lambda-introducer.
64 class LambdaDefaultCaptureVisitor
65   : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
66 public:
67   bool VisitLambdaExpr(LambdaExpr *Lambda) {
68     if (Lambda->getCaptureDefault() != LCD_None) {
69       Match("", Lambda->getCaptureDefaultLoc());
70     }
71     return true;
72   }
73 };
74
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));
80 }
81
82 // Checks for lambda classes that are not marked as implicitly-generated.
83 // (There should be none.)
84 class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
85 public:
86   ClassVisitor() : SawNonImplicitLambdaClass(false) {}
87   bool VisitCXXRecordDecl(CXXRecordDecl* record) {
88     if (record->isLambda() && !record->isImplicit())
89       SawNonImplicitLambdaClass = true;
90     return true;
91   }
92
93   bool sawOnlyImplicitLambdaClasses() const {
94     return !SawNonImplicitLambdaClass;
95   }
96
97 private:
98   bool SawNonImplicitLambdaClass;
99 };
100
101 TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
102   ClassVisitor Visitor;
103   EXPECT_TRUE(Visitor.runOver("auto lambda = []{};", ClassVisitor::Lang_CXX11));
104   EXPECT_TRUE(Visitor.sawOnlyImplicitLambdaClasses());
105 }
106
107
108 // Check to ensure that attributes and expressions within them are being
109 // visited.
110 class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
111 public:
112   bool VisitMemberExpr(MemberExpr *ME) {
113     Match(ME->getMemberDecl()->getNameAsString(), ME->getLocStart());
114     return true;
115   }
116   bool VisitAttr(Attr *A) {
117     Match("Attr", A->getLocation());
118     return true;
119   }
120   bool VisitGuardedByAttr(GuardedByAttr *A) {
121     Match("guarded_by", A->getLocation());
122     return true;
123   }
124 };
125
126
127 TEST(RecursiveASTVisitor, AttributesAreVisited) {
128   AttrVisitor Visitor;
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(
136     "class Foo {\n"
137     "  int mu1;\n"
138     "  int mu2;\n"
139     "  int a __attribute__((guarded_by(mu1)));\n"
140     "  void bar() __attribute__((exclusive_locks_required(mu1, mu2)));\n"
141     "};\n"));
142 }
143
144 // Check to ensure that implicit default argument expressions are visited.
145 class IntegerLiteralVisitor
146     : public ExpectedLocationVisitor<IntegerLiteralVisitor> {
147 public:
148   bool VisitIntegerLiteral(const IntegerLiteral *IL) {
149     Match("literal", IL->getLocation());
150     return true;
151   }
152 };
153
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"));
159 }
160
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> {
165 public:
166   bool VisitInitListExpr(InitListExpr *ILE) {
167     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
168     return true;
169   }
170 };
171
172 class InitListExprPostOrderVisitor
173     : public ExpectedLocationVisitor<InitListExprPostOrderVisitor> {
174 public:
175   bool shouldTraversePostOrder() const { return true; }
176
177   bool VisitInitListExpr(InitListExpr *ILE) {
178     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
179     return true;
180   }
181 };
182
183 class InitListExprPreOrderNoQueueVisitor
184     : public ExpectedLocationVisitor<InitListExprPreOrderNoQueueVisitor> {
185 public:
186   bool TraverseInitListExpr(InitListExpr *ILE) {
187     return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
188   }
189
190   bool VisitInitListExpr(InitListExpr *ILE) {
191     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
192     return true;
193   }
194 };
195
196 class InitListExprPostOrderNoQueueVisitor
197     : public ExpectedLocationVisitor<InitListExprPostOrderNoQueueVisitor> {
198 public:
199   bool shouldTraversePostOrder() const { return true; }
200
201   bool TraverseInitListExpr(InitListExpr *ILE) {
202     return ExpectedLocationVisitor::TraverseInitListExpr(ILE);
203   }
204
205   bool VisitInitListExpr(InitListExpr *ILE) {
206     Match(ILE->isSemanticForm() ? "semantic" : "syntactic", ILE->getLocStart());
207     return true;
208   }
209 };
210
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));
218 }
219
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));
227 }
228
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));
236 }
237
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));
245 }
246
247 // Check to ensure that nested name specifiers are visited.
248 class NestedNameSpecifiersVisitor
249     : public ExpectedLocationVisitor<NestedNameSpecifiersVisitor> {
250 public:
251   bool VisitRecordTypeLoc(RecordTypeLoc RTL) {
252     if (!RTL)
253       return true;
254     Match(RTL.getDecl()->getName(), RTL.getNameLoc());
255     return true;
256   }
257
258   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
259     if (!NNS)
260       return true;
261     if (const NamespaceDecl *ND =
262             NNS.getNestedNameSpecifier()->getAsNamespace())
263       Match(ND->getName(), NNS.getLocalBeginLoc());
264     return ExpectedLocationVisitor::TraverseNestedNameSpecifierLoc(NNS);
265   }
266 };
267
268 TEST(RecursiveASTVisitor,
269      NestedNameSpecifiersForTemplateSpecializationsAreVisited) {
270   StringRef Source = R"(
271 namespace ns {
272 struct Outer {
273     template<typename T, typename U>
274     struct Nested { };
275
276     template<typename T>
277     static T x;
278 };
279 }
280
281 template<>
282 struct ns::Outer::Nested<int, int>;
283
284 template<>
285 struct ns::Outer::Nested<int, int> { };
286
287 template<typename T>
288 struct ns::Outer::Nested<int, T> { };
289
290 template<>
291 int ns::Outer::x<int> = 0;
292 )";
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));
303 }
304
305 } // end anonymous namespace