xref: /aosp_15_r20/external/clang/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- unittest/Tooling/RecursiveASTVisitorTestExprVisitor.cpp ------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li 
10*67e74705SXin Li #include "TestVisitor.h"
11*67e74705SXin Li #include <stack>
12*67e74705SXin Li 
13*67e74705SXin Li using namespace clang;
14*67e74705SXin Li 
15*67e74705SXin Li namespace {
16*67e74705SXin Li 
17*67e74705SXin Li class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
18*67e74705SXin Li public:
VisitParenExpr(ParenExpr * Parens)19*67e74705SXin Li   bool VisitParenExpr(ParenExpr *Parens) {
20*67e74705SXin Li     Match("", Parens->getExprLoc());
21*67e74705SXin Li     return true;
22*67e74705SXin Li   }
23*67e74705SXin Li };
24*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsParensDuringDataRecursion)25*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
26*67e74705SXin Li   ParenExprVisitor Visitor;
27*67e74705SXin Li   Visitor.ExpectMatch("", 1, 9);
28*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
29*67e74705SXin Li }
30*67e74705SXin Li 
31*67e74705SXin Li class TemplateArgumentLocTraverser
32*67e74705SXin Li   : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
33*67e74705SXin Li public:
TraverseTemplateArgumentLoc(const TemplateArgumentLoc & ArgLoc)34*67e74705SXin Li   bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
35*67e74705SXin Li     std::string ArgStr;
36*67e74705SXin Li     llvm::raw_string_ostream Stream(ArgStr);
37*67e74705SXin Li     const TemplateArgument &Arg = ArgLoc.getArgument();
38*67e74705SXin Li 
39*67e74705SXin Li     Arg.print(Context->getPrintingPolicy(), Stream);
40*67e74705SXin Li     Match(Stream.str(), ArgLoc.getLocation());
41*67e74705SXin Li     return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
42*67e74705SXin Li       TraverseTemplateArgumentLoc(ArgLoc);
43*67e74705SXin Li   }
44*67e74705SXin Li };
45*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsClassTemplateTemplateParmDefaultArgument)46*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
47*67e74705SXin Li   TemplateArgumentLocTraverser Visitor;
48*67e74705SXin Li   Visitor.ExpectMatch("X", 2, 40);
49*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
50*67e74705SXin Li     "template<typename T> class X;\n"
51*67e74705SXin Li     "template<template <typename> class T = X> class Y;\n"
52*67e74705SXin Li     "template<template <typename> class T> class Y {};\n"));
53*67e74705SXin Li }
54*67e74705SXin Li 
55*67e74705SXin Li class CXXBoolLiteralExprVisitor
56*67e74705SXin Li   : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
57*67e74705SXin Li public:
VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr * BE)58*67e74705SXin Li   bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
59*67e74705SXin Li     if (BE->getValue())
60*67e74705SXin Li       Match("true", BE->getLocation());
61*67e74705SXin Li     else
62*67e74705SXin Li       Match("false", BE->getLocation());
63*67e74705SXin Li     return true;
64*67e74705SXin Li   }
65*67e74705SXin Li };
66*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsClassTemplateNonTypeParmDefaultArgument)67*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
68*67e74705SXin Li   CXXBoolLiteralExprVisitor Visitor;
69*67e74705SXin Li   Visitor.ExpectMatch("true", 2, 19);
70*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
71*67e74705SXin Li     "template<bool B> class X;\n"
72*67e74705SXin Li     "template<bool B = true> class Y;\n"
73*67e74705SXin Li     "template<bool B> class Y {};\n"));
74*67e74705SXin Li }
75*67e74705SXin Li 
76*67e74705SXin Li // A visitor that visits implicit declarations and matches constructors.
77*67e74705SXin Li class ImplicitCtorVisitor
78*67e74705SXin Li     : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
79*67e74705SXin Li public:
shouldVisitImplicitCode() const80*67e74705SXin Li   bool shouldVisitImplicitCode() const { return true; }
81*67e74705SXin Li 
VisitCXXConstructorDecl(CXXConstructorDecl * Ctor)82*67e74705SXin Li   bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
83*67e74705SXin Li     if (Ctor->isImplicit()) {  // Was not written in source code
84*67e74705SXin Li       if (const CXXRecordDecl* Class = Ctor->getParent()) {
85*67e74705SXin Li         Match(Class->getName(), Ctor->getLocation());
86*67e74705SXin Li       }
87*67e74705SXin Li     }
88*67e74705SXin Li     return true;
89*67e74705SXin Li   }
90*67e74705SXin Li };
91*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsImplicitCopyConstructors)92*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
93*67e74705SXin Li   ImplicitCtorVisitor Visitor;
94*67e74705SXin Li   Visitor.ExpectMatch("Simple", 2, 8);
95*67e74705SXin Li   // Note: Clang lazily instantiates implicit declarations, so we need
96*67e74705SXin Li   // to use them in order to force them to appear in the AST.
97*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
98*67e74705SXin Li       "struct WithCtor { WithCtor(); }; \n"
99*67e74705SXin Li       "struct Simple { Simple(); WithCtor w; }; \n"
100*67e74705SXin Li       "int main() { Simple s; Simple t(s); }\n"));
101*67e74705SXin Li }
102*67e74705SXin Li 
103*67e74705SXin Li /// \brief A visitor that optionally includes implicit code and matches
104*67e74705SXin Li /// CXXConstructExpr.
105*67e74705SXin Li ///
106*67e74705SXin Li /// The name recorded for the match is the name of the class whose constructor
107*67e74705SXin Li /// is invoked by the CXXConstructExpr, not the name of the class whose
108*67e74705SXin Li /// constructor the CXXConstructExpr is contained in.
109*67e74705SXin Li class ConstructExprVisitor
110*67e74705SXin Li     : public ExpectedLocationVisitor<ConstructExprVisitor> {
111*67e74705SXin Li public:
ConstructExprVisitor()112*67e74705SXin Li   ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
113*67e74705SXin Li 
shouldVisitImplicitCode() const114*67e74705SXin Li   bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
115*67e74705SXin Li 
setShouldVisitImplicitCode(bool NewValue)116*67e74705SXin Li   void setShouldVisitImplicitCode(bool NewValue) {
117*67e74705SXin Li     ShouldVisitImplicitCode = NewValue;
118*67e74705SXin Li   }
119*67e74705SXin Li 
VisitCXXConstructExpr(CXXConstructExpr * Expr)120*67e74705SXin Li   bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
121*67e74705SXin Li     if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
122*67e74705SXin Li       if (const CXXRecordDecl* Class = Ctor->getParent()) {
123*67e74705SXin Li         Match(Class->getName(), Expr->getLocation());
124*67e74705SXin Li       }
125*67e74705SXin Li     }
126*67e74705SXin Li     return true;
127*67e74705SXin Li   }
128*67e74705SXin Li 
129*67e74705SXin Li  private:
130*67e74705SXin Li   bool ShouldVisitImplicitCode;
131*67e74705SXin Li };
132*67e74705SXin Li 
TEST(RecursiveASTVisitor,CanVisitImplicitMemberInitializations)133*67e74705SXin Li TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
134*67e74705SXin Li   ConstructExprVisitor Visitor;
135*67e74705SXin Li   Visitor.setShouldVisitImplicitCode(true);
136*67e74705SXin Li   Visitor.ExpectMatch("WithCtor", 2, 8);
137*67e74705SXin Li   // Simple has a constructor that implicitly initializes 'w'.  Test
138*67e74705SXin Li   // that a visitor that visits implicit code visits that initialization.
139*67e74705SXin Li   // Note: Clang lazily instantiates implicit declarations, so we need
140*67e74705SXin Li   // to use them in order to force them to appear in the AST.
141*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
142*67e74705SXin Li       "struct WithCtor { WithCtor(); }; \n"
143*67e74705SXin Li       "struct Simple { WithCtor w; }; \n"
144*67e74705SXin Li       "int main() { Simple s; }\n"));
145*67e74705SXin Li }
146*67e74705SXin Li 
147*67e74705SXin Li // The same as CanVisitImplicitMemberInitializations, but checking that the
148*67e74705SXin Li // visits are omitted when the visitor does not include implicit code.
TEST(RecursiveASTVisitor,CanSkipImplicitMemberInitializations)149*67e74705SXin Li TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
150*67e74705SXin Li   ConstructExprVisitor Visitor;
151*67e74705SXin Li   Visitor.setShouldVisitImplicitCode(false);
152*67e74705SXin Li   Visitor.DisallowMatch("WithCtor", 2, 8);
153*67e74705SXin Li   // Simple has a constructor that implicitly initializes 'w'.  Test
154*67e74705SXin Li   // that a visitor that skips implicit code skips that initialization.
155*67e74705SXin Li   // Note: Clang lazily instantiates implicit declarations, so we need
156*67e74705SXin Li   // to use them in order to force them to appear in the AST.
157*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
158*67e74705SXin Li       "struct WithCtor { WithCtor(); }; \n"
159*67e74705SXin Li       "struct Simple { WithCtor w; }; \n"
160*67e74705SXin Li       "int main() { Simple s; }\n"));
161*67e74705SXin Li }
162*67e74705SXin Li 
163*67e74705SXin Li class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
164*67e74705SXin Li public:
VisitDeclRefExpr(DeclRefExpr * Reference)165*67e74705SXin Li   bool VisitDeclRefExpr(DeclRefExpr *Reference) {
166*67e74705SXin Li     Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
167*67e74705SXin Li     return true;
168*67e74705SXin Li   }
169*67e74705SXin Li };
170*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsBaseClassTemplateArguments)171*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
172*67e74705SXin Li   DeclRefExprVisitor Visitor;
173*67e74705SXin Li   Visitor.ExpectMatch("x", 2, 3);
174*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
175*67e74705SXin Li     "void x(); template <void (*T)()> class X {};\nX<x> y;"));
176*67e74705SXin Li }
177*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsCXXForRangeStmtRange)178*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
179*67e74705SXin Li   DeclRefExprVisitor Visitor;
180*67e74705SXin Li   Visitor.ExpectMatch("x", 2, 25);
181*67e74705SXin Li   Visitor.ExpectMatch("x", 2, 30);
182*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
183*67e74705SXin Li     "int x[5];\n"
184*67e74705SXin Li     "void f() { for (int i : x) { x[0] = 1; } }",
185*67e74705SXin Li     DeclRefExprVisitor::Lang_CXX11));
186*67e74705SXin Li }
187*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsCallExpr)188*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsCallExpr) {
189*67e74705SXin Li   DeclRefExprVisitor Visitor;
190*67e74705SXin Li   Visitor.ExpectMatch("x", 1, 22);
191*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
192*67e74705SXin Li     "void x(); void y() { x(); }"));
193*67e74705SXin Li }
194*67e74705SXin Li 
195*67e74705SXin Li /* FIXME: According to Richard Smith this is a bug in the AST.
196*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
197*67e74705SXin Li   DeclRefExprVisitor Visitor;
198*67e74705SXin Li   Visitor.ExpectMatch("x", 3, 43);
199*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
200*67e74705SXin Li     "template <typename T> void x();\n"
201*67e74705SXin Li     "template <void (*T)()> class X {};\n"
202*67e74705SXin Li     "template <typename T> class Y : public X< x<T> > {};\n"
203*67e74705SXin Li     "Y<int> y;"));
204*67e74705SXin Li }
205*67e74705SXin Li */
206*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsExtension)207*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsExtension) {
208*67e74705SXin Li   DeclRefExprVisitor Visitor;
209*67e74705SXin Li   Visitor.ExpectMatch("s", 1, 24);
210*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver(
211*67e74705SXin Li     "int s = __extension__ (s);\n"));
212*67e74705SXin Li }
213*67e74705SXin Li 
TEST(RecursiveASTVisitor,VisitsCopyExprOfBlockDeclCapture)214*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
215*67e74705SXin Li   DeclRefExprVisitor Visitor;
216*67e74705SXin Li   Visitor.ExpectMatch("x", 3, 24);
217*67e74705SXin Li   EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
218*67e74705SXin Li                               "void g() { \n"
219*67e74705SXin Li                               "  f([&](int x){ return x; }); \n"
220*67e74705SXin Li                               "}",
221*67e74705SXin Li                               DeclRefExprVisitor::Lang_OBJCXX11));
222*67e74705SXin Li }
223*67e74705SXin Li 
224*67e74705SXin Li } // end anonymous namespace
225