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