• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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