1*67e74705SXin Li //===- unittest/Tooling/RecursiveASTVisitorTestDeclVisitor.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 VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
18*67e74705SXin Li public:
VisitVarDecl(VarDecl * Variable)19*67e74705SXin Li bool VisitVarDecl(VarDecl *Variable) {
20*67e74705SXin Li Match(Variable->getNameAsString(), Variable->getLocStart());
21*67e74705SXin Li return true;
22*67e74705SXin Li }
23*67e74705SXin Li };
24*67e74705SXin Li
TEST(RecursiveASTVisitor,VisitsCXXForRangeStmtLoopVariable)25*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
26*67e74705SXin Li VarDeclVisitor Visitor;
27*67e74705SXin Li Visitor.ExpectMatch("i", 2, 17);
28*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
29*67e74705SXin Li "int x[5];\n"
30*67e74705SXin Li "void f() { for (int i : x) {} }",
31*67e74705SXin Li VarDeclVisitor::Lang_CXX11));
32*67e74705SXin Li }
33*67e74705SXin Li
34*67e74705SXin Li class ParmVarDeclVisitorForImplicitCode :
35*67e74705SXin Li public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
36*67e74705SXin Li public:
shouldVisitImplicitCode() const37*67e74705SXin Li bool shouldVisitImplicitCode() const { return true; }
38*67e74705SXin Li
VisitParmVarDecl(ParmVarDecl * ParamVar)39*67e74705SXin Li bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
40*67e74705SXin Li Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
41*67e74705SXin Li return true;
42*67e74705SXin Li }
43*67e74705SXin Li };
44*67e74705SXin Li
45*67e74705SXin Li // Test RAV visits parameter variable declaration of the implicit
46*67e74705SXin Li // copy assignment operator and implicit copy constructor.
TEST(RecursiveASTVisitor,VisitsParmVarDeclForImplicitCode)47*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
48*67e74705SXin Li ParmVarDeclVisitorForImplicitCode Visitor;
49*67e74705SXin Li // Match parameter variable name of implicit copy assignment operator and
50*67e74705SXin Li // implicit copy constructor.
51*67e74705SXin Li // This parameter name does not have a valid IdentifierInfo, and shares
52*67e74705SXin Li // same SourceLocation with its class declaration, so we match an empty name
53*67e74705SXin Li // with the class' source location.
54*67e74705SXin Li Visitor.ExpectMatch("", 1, 7);
55*67e74705SXin Li Visitor.ExpectMatch("", 3, 7);
56*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
57*67e74705SXin Li "class X {};\n"
58*67e74705SXin Li "void foo(X a, X b) {a = b;}\n"
59*67e74705SXin Li "class Y {};\n"
60*67e74705SXin Li "void bar(Y a) {Y b = a;}"));
61*67e74705SXin Li }
62*67e74705SXin Li
63*67e74705SXin Li class NamedDeclVisitor
64*67e74705SXin Li : public ExpectedLocationVisitor<NamedDeclVisitor> {
65*67e74705SXin Li public:
VisitNamedDecl(NamedDecl * Decl)66*67e74705SXin Li bool VisitNamedDecl(NamedDecl *Decl) {
67*67e74705SXin Li std::string NameWithTemplateArgs;
68*67e74705SXin Li llvm::raw_string_ostream OS(NameWithTemplateArgs);
69*67e74705SXin Li Decl->getNameForDiagnostic(OS,
70*67e74705SXin Li Decl->getASTContext().getPrintingPolicy(),
71*67e74705SXin Li true);
72*67e74705SXin Li Match(OS.str(), Decl->getLocation());
73*67e74705SXin Li return true;
74*67e74705SXin Li }
75*67e74705SXin Li };
76*67e74705SXin Li
TEST(RecursiveASTVisitor,VisitsPartialTemplateSpecialization)77*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
78*67e74705SXin Li // From cfe-commits/Week-of-Mon-20100830/033998.html
79*67e74705SXin Li // Contrary to the approach suggested in that email, we visit all
80*67e74705SXin Li // specializations when we visit the primary template. Visiting them when we
81*67e74705SXin Li // visit the associated specialization is problematic for specializations of
82*67e74705SXin Li // template members of class templates.
83*67e74705SXin Li NamedDeclVisitor Visitor;
84*67e74705SXin Li Visitor.ExpectMatch("A<bool>", 1, 26);
85*67e74705SXin Li Visitor.ExpectMatch("A<char *>", 2, 26);
86*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
87*67e74705SXin Li "template <class T> class A {};\n"
88*67e74705SXin Li "template <class T> class A<T*> {};\n"
89*67e74705SXin Li "A<bool> ab;\n"
90*67e74705SXin Li "A<char*> acp;\n"));
91*67e74705SXin Li }
92*67e74705SXin Li
TEST(RecursiveASTVisitor,VisitsUndefinedClassTemplateSpecialization)93*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
94*67e74705SXin Li NamedDeclVisitor Visitor;
95*67e74705SXin Li Visitor.ExpectMatch("A<int>", 1, 29);
96*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
97*67e74705SXin Li "template<typename T> struct A;\n"
98*67e74705SXin Li "A<int> *p;\n"));
99*67e74705SXin Li }
100*67e74705SXin Li
TEST(RecursiveASTVisitor,VisitsNestedUndefinedClassTemplateSpecialization)101*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
102*67e74705SXin Li NamedDeclVisitor Visitor;
103*67e74705SXin Li Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
104*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
105*67e74705SXin Li "template<typename T> struct A {\n"
106*67e74705SXin Li " template<typename U> struct B;\n"
107*67e74705SXin Li "};\n"
108*67e74705SXin Li "A<int>::B<char> *p;\n"));
109*67e74705SXin Li }
110*67e74705SXin Li
TEST(RecursiveASTVisitor,VisitsUndefinedFunctionTemplateSpecialization)111*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
112*67e74705SXin Li NamedDeclVisitor Visitor;
113*67e74705SXin Li Visitor.ExpectMatch("A<int>", 1, 26);
114*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
115*67e74705SXin Li "template<typename T> int A();\n"
116*67e74705SXin Li "int k = A<int>();\n"));
117*67e74705SXin Li }
118*67e74705SXin Li
TEST(RecursiveASTVisitor,VisitsNestedUndefinedFunctionTemplateSpecialization)119*67e74705SXin Li TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
120*67e74705SXin Li NamedDeclVisitor Visitor;
121*67e74705SXin Li Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
122*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
123*67e74705SXin Li "template<typename T> struct A {\n"
124*67e74705SXin Li " template<typename U> static int B();\n"
125*67e74705SXin Li "};\n"
126*67e74705SXin Li "int k = A<int>::B<char>();\n"));
127*67e74705SXin Li }
128*67e74705SXin Li
TEST(RecursiveASTVisitor,NoRecursionInSelfFriend)129*67e74705SXin Li TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
130*67e74705SXin Li // From cfe-commits/Week-of-Mon-20100830/033977.html
131*67e74705SXin Li NamedDeclVisitor Visitor;
132*67e74705SXin Li Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
133*67e74705SXin Li EXPECT_TRUE(Visitor.runOver(
134*67e74705SXin Li "template<typename Container>\n"
135*67e74705SXin Li "class vector_iterator {\n"
136*67e74705SXin Li " template <typename C> friend class vector_iterator;\n"
137*67e74705SXin Li "};\n"
138*67e74705SXin Li "vector_iterator<int> it_int;\n"));
139*67e74705SXin Li }
140*67e74705SXin Li
141*67e74705SXin Li } // end anonymous namespace
142