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