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