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
11using namespace clang;
12
13namespace {
14
15class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
16public:
17 bool VisitVarDecl(VarDecl *Variable) {
18 Match(Name: Variable->getNameAsString(), Location: Variable->getBeginLoc());
19 return true;
20 }
21};
22
23TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
24 VarDeclVisitor Visitor;
25 Visitor.ExpectMatch(Match: "i", Line: 2, Column: 17);
26 EXPECT_TRUE(Visitor.runOver(
27 "int x[5];\n"
28 "void f() { for (int i : x) {} }",
29 VarDeclVisitor::Lang_CXX11));
30}
31
32class ParmVarDeclVisitorForImplicitCode :
33 public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
34public:
35 bool shouldVisitImplicitCode() const { return true; }
36
37 bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
38 Match(Name: ParamVar->getNameAsString(), Location: 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.
45TEST(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(Match: "", Line: 1, Column: 7);
53 Visitor.ExpectMatch(Match: "", Line: 3, Column: 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
61class NamedDeclVisitor
62 : public ExpectedLocationVisitor<NamedDeclVisitor> {
63public:
64 bool VisitNamedDecl(NamedDecl *Decl) {
65 std::string NameWithTemplateArgs;
66 llvm::raw_string_ostream OS(NameWithTemplateArgs);
67 Decl->getNameForDiagnostic(OS,
68 Policy: Decl->getASTContext().getPrintingPolicy(),
69 Qualified: true);
70 Match(Name: OS.str(), Location: Decl->getLocation());
71 return true;
72 }
73};
74
75TEST(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(Match: "A<bool>", Line: 1, Column: 26);
83 Visitor.ExpectMatch(Match: "A<char *>", Line: 2, Column: 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
91TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
92 NamedDeclVisitor Visitor;
93 Visitor.ExpectMatch(Match: "A<int>", Line: 1, Column: 29);
94 EXPECT_TRUE(Visitor.runOver(
95 "template<typename T> struct A;\n"
96 "A<int> *p;\n"));
97}
98
99TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
100 NamedDeclVisitor Visitor;
101 Visitor.ExpectMatch(Match: "A<int>::B<char>", Line: 2, Column: 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
109TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
110 NamedDeclVisitor Visitor;
111 Visitor.ExpectMatch(Match: "A<int>", Line: 1, Column: 26);
112 EXPECT_TRUE(Visitor.runOver(
113 "template<typename T> int A();\n"
114 "int k = A<int>();\n"));
115}
116
117TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
118 NamedDeclVisitor Visitor;
119 Visitor.ExpectMatch(Match: "A<int>::B<char>", Line: 2, Column: 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
127TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
128 // From cfe-commits/Week-of-Mon-20100830/033977.html
129 NamedDeclVisitor Visitor;
130 Visitor.ExpectMatch(Match: "vector_iterator<int>", Line: 2, Column: 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

source code of clang/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp