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