1 //===- unittest/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp ------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "TestVisitor.h"
11 using namespace clang
;
15 class VarDeclVisitor
: public ExpectedLocationVisitor
<VarDeclVisitor
> {
17 bool VisitVarDecl(VarDecl
*Variable
) {
18 Match(Variable
->getNameAsString(), Variable
->getBeginLoc());
23 TEST(RecursiveASTVisitor
, VisitsCXXForRangeStmtLoopVariable
) {
24 VarDeclVisitor Visitor
;
25 Visitor
.ExpectMatch("i", 2, 17);
26 EXPECT_TRUE(Visitor
.runOver(
28 "void f() { for (int i : x) {} }",
29 VarDeclVisitor::Lang_CXX11
));
32 class ParmVarDeclVisitorForImplicitCode
:
33 public ExpectedLocationVisitor
<ParmVarDeclVisitorForImplicitCode
> {
35 bool shouldVisitImplicitCode() const { return true; }
37 bool VisitParmVarDecl(ParmVarDecl
*ParamVar
) {
38 Match(ParamVar
->getNameAsString(), ParamVar
->getBeginLoc());
43 // Test RAV visits parameter variable declaration of the implicit
44 // copy assignment operator and implicit copy constructor.
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(
56 "void foo(X a, X b) {a = b;}\n"
58 "void bar(Y a) {Y b = a;}"));
61 class NamedDeclVisitor
62 : public ExpectedLocationVisitor
<NamedDeclVisitor
> {
64 bool VisitNamedDecl(NamedDecl
*Decl
) {
65 std::string NameWithTemplateArgs
;
66 llvm::raw_string_ostream
OS(NameWithTemplateArgs
);
67 Decl
->getNameForDiagnostic(OS
,
68 Decl
->getASTContext().getPrintingPolicy(),
70 Match(OS
.str(), Decl
->getLocation());
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"
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"
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"
106 "A<int>::B<char> *p;\n"));
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"));
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"
124 "int k = A<int>::B<char>();\n"));
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"
136 "vector_iterator<int> it_int;\n"));
139 } // end anonymous namespace