]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
Vendor import of clang trunk r321530:
[FreeBSD/FreeBSD.git] / unittests / Tooling / RecursiveASTVisitorTestExprVisitor.cpp
1 //===- unittest/Tooling/RecursiveASTVisitorTestExprVisitor.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
12 using namespace clang;
13
14 namespace {
15
16 class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
17 public:
18   bool VisitParenExpr(ParenExpr *Parens) {
19     Match("", Parens->getExprLoc());
20     return true;
21   }
22 };
23
24 TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
25   ParenExprVisitor Visitor;
26   Visitor.ExpectMatch("", 1, 9);
27   EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
28 }
29
30 class TemplateArgumentLocTraverser
31   : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
32 public:
33   bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
34     std::string ArgStr;
35     llvm::raw_string_ostream Stream(ArgStr);
36     const TemplateArgument &Arg = ArgLoc.getArgument();
37
38     Arg.print(Context->getPrintingPolicy(), Stream);
39     Match(Stream.str(), ArgLoc.getLocation());
40     return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
41       TraverseTemplateArgumentLoc(ArgLoc);
42   }
43 };
44
45 TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
46   TemplateArgumentLocTraverser Visitor;
47   Visitor.ExpectMatch("X", 2, 40);
48   EXPECT_TRUE(Visitor.runOver(
49     "template<typename T> class X;\n"
50     "template<template <typename> class T = X> class Y;\n"
51     "template<template <typename> class T> class Y {};\n"));
52 }
53
54 class CXXBoolLiteralExprVisitor 
55   : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
56 public:
57   bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
58     if (BE->getValue())
59       Match("true", BE->getLocation());
60     else
61       Match("false", BE->getLocation());
62     return true;
63   }
64 };
65
66 TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
67   CXXBoolLiteralExprVisitor Visitor;
68   Visitor.ExpectMatch("true", 2, 19);
69   EXPECT_TRUE(Visitor.runOver(
70     "template<bool B> class X;\n"
71     "template<bool B = true> class Y;\n"
72     "template<bool B> class Y {};\n"));
73 }
74
75 // A visitor that visits implicit declarations and matches constructors.
76 class ImplicitCtorVisitor
77     : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
78 public:
79   bool shouldVisitImplicitCode() const { return true; }
80
81   bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
82     if (Ctor->isImplicit()) {  // Was not written in source code
83       if (const CXXRecordDecl* Class = Ctor->getParent()) {
84         Match(Class->getName(), Ctor->getLocation());
85       }
86     }
87     return true;
88   }
89 };
90
91 TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
92   ImplicitCtorVisitor Visitor;
93   Visitor.ExpectMatch("Simple", 2, 8);
94   // Note: Clang lazily instantiates implicit declarations, so we need
95   // to use them in order to force them to appear in the AST.
96   EXPECT_TRUE(Visitor.runOver(
97       "struct WithCtor { WithCtor(); }; \n"
98       "struct Simple { Simple(); WithCtor w; }; \n"
99       "int main() { Simple s; Simple t(s); }\n"));
100 }
101
102 /// \brief A visitor that optionally includes implicit code and matches
103 /// CXXConstructExpr.
104 ///
105 /// The name recorded for the match is the name of the class whose constructor
106 /// is invoked by the CXXConstructExpr, not the name of the class whose
107 /// constructor the CXXConstructExpr is contained in.
108 class ConstructExprVisitor
109     : public ExpectedLocationVisitor<ConstructExprVisitor> {
110 public:
111   ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
112
113   bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
114
115   void setShouldVisitImplicitCode(bool NewValue) {
116     ShouldVisitImplicitCode = NewValue;
117   }
118
119   bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
120     if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
121       if (const CXXRecordDecl* Class = Ctor->getParent()) {
122         Match(Class->getName(), Expr->getLocation());
123       }
124     }
125     return true;
126   }
127
128  private:
129   bool ShouldVisitImplicitCode;
130 };
131
132 TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
133   ConstructExprVisitor Visitor;
134   Visitor.setShouldVisitImplicitCode(true);
135   Visitor.ExpectMatch("WithCtor", 2, 8);
136   // Simple has a constructor that implicitly initializes 'w'.  Test
137   // that a visitor that visits implicit code visits that initialization.
138   // Note: Clang lazily instantiates implicit declarations, so we need
139   // to use them in order to force them to appear in the AST.
140   EXPECT_TRUE(Visitor.runOver(
141       "struct WithCtor { WithCtor(); }; \n"
142       "struct Simple { WithCtor w; }; \n"
143       "int main() { Simple s; }\n"));
144 }
145
146 // The same as CanVisitImplicitMemberInitializations, but checking that the
147 // visits are omitted when the visitor does not include implicit code.
148 TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
149   ConstructExprVisitor Visitor;
150   Visitor.setShouldVisitImplicitCode(false);
151   Visitor.DisallowMatch("WithCtor", 2, 8);
152   // Simple has a constructor that implicitly initializes 'w'.  Test
153   // that a visitor that skips implicit code skips that initialization.
154   // Note: Clang lazily instantiates implicit declarations, so we need
155   // to use them in order to force them to appear in the AST.
156   EXPECT_TRUE(Visitor.runOver(
157       "struct WithCtor { WithCtor(); }; \n"
158       "struct Simple { WithCtor w; }; \n"
159       "int main() { Simple s; }\n"));
160 }
161
162 class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
163 public:
164   DeclRefExprVisitor() : ShouldVisitImplicitCode(false) {}
165
166   bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
167
168   void setShouldVisitImplicitCode(bool NewValue) {
169     ShouldVisitImplicitCode = NewValue;
170   }
171
172   bool VisitDeclRefExpr(DeclRefExpr *Reference) {
173     Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
174     return true;
175   }
176
177 private:
178   bool ShouldVisitImplicitCode;
179 };
180
181 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
182   DeclRefExprVisitor Visitor;
183   Visitor.ExpectMatch("x", 2, 3);
184   EXPECT_TRUE(Visitor.runOver(
185     "void x(); template <void (*T)()> class X {};\nX<x> y;"));
186 }
187
188 TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
189   DeclRefExprVisitor Visitor;
190   Visitor.ExpectMatch("x", 2, 25);
191   Visitor.ExpectMatch("x", 2, 30);
192   EXPECT_TRUE(Visitor.runOver(
193     "int x[5];\n"
194     "void f() { for (int i : x) { x[0] = 1; } }",
195     DeclRefExprVisitor::Lang_CXX11));
196 }
197
198 TEST(RecursiveASTVisitor, VisitsCallExpr) {
199   DeclRefExprVisitor Visitor;
200   Visitor.ExpectMatch("x", 1, 22);
201   EXPECT_TRUE(Visitor.runOver(
202     "void x(); void y() { x(); }"));
203 }
204
205 TEST(RecursiveASTVisitor, VisitsExplicitLambdaCaptureInit) {
206   DeclRefExprVisitor Visitor;
207   Visitor.ExpectMatch("i", 1, 20);
208   EXPECT_TRUE(Visitor.runOver(
209     "void f() { int i; [i]{}; }",
210     DeclRefExprVisitor::Lang_CXX11));
211 }
212
213 TEST(RecursiveASTVisitor, VisitsUseOfImplicitLambdaCapture) {
214   DeclRefExprVisitor Visitor;
215   Visitor.ExpectMatch("i", 1, 24);
216   EXPECT_TRUE(Visitor.runOver(
217     "void f() { int i; [=]{ i; }; }",
218     DeclRefExprVisitor::Lang_CXX11));
219 }
220
221 TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
222   DeclRefExprVisitor Visitor;
223   Visitor.setShouldVisitImplicitCode(true);
224   // We're expecting the "i" in the lambda to be visited twice:
225   // - Once for the DeclRefExpr in the lambda capture initialization (whose
226   //   source code location is set to the first use of the variable).
227   // - Once for the DeclRefExpr for the use of "i" inside the lambda.
228   Visitor.ExpectMatch("i", 1, 24, /*Times=*/2);
229   EXPECT_TRUE(Visitor.runOver(
230     "void f() { int i; [=]{ i; }; }",
231     DeclRefExprVisitor::Lang_CXX11));
232 }
233
234 TEST(RecursiveASTVisitor, VisitsLambdaInitCaptureInit) {
235   DeclRefExprVisitor Visitor;
236   Visitor.ExpectMatch("i", 1, 24);
237   EXPECT_TRUE(Visitor.runOver(
238     "void f() { int i; [a = i + 1]{}; }",
239     DeclRefExprVisitor::Lang_CXX14));
240 }
241
242 /* FIXME: According to Richard Smith this is a bug in the AST.
243 TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
244   DeclRefExprVisitor Visitor;
245   Visitor.ExpectMatch("x", 3, 43);
246   EXPECT_TRUE(Visitor.runOver(
247     "template <typename T> void x();\n"
248     "template <void (*T)()> class X {};\n"
249     "template <typename T> class Y : public X< x<T> > {};\n"
250     "Y<int> y;"));
251 }
252 */
253
254 TEST(RecursiveASTVisitor, VisitsExtension) {
255   DeclRefExprVisitor Visitor;
256   Visitor.ExpectMatch("s", 1, 24);
257   EXPECT_TRUE(Visitor.runOver(
258     "int s = __extension__ (s);\n"));
259 }
260
261 TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
262   DeclRefExprVisitor Visitor;
263   Visitor.ExpectMatch("x", 3, 24);
264   EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
265                               "void g() { \n"
266                               "  f([&](int x){ return x; }); \n"
267                               "}",
268                               DeclRefExprVisitor::Lang_OBJCXX11));
269 }
270
271 } // end anonymous namespace