xref: /minix3/external/bsd/llvm/dist/clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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