Clang Project

clang_source_code/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
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(Variable->getNameAsString(), Variable->getBeginLoc());
19   return true;
20 }
21};
22
23TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
24  VarDeclVisitor Visitor;
25  Visitor.ExpectMatch("i"217);
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(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.
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(""17);
53  Visitor.ExpectMatch(""37);
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                               Decl->getASTContext().getPrintingPolicy(),
69                               true);
70    Match(OS.str(), 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("A<bool>"126);
83  Visitor.ExpectMatch("A<char *>"226);
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("A<int>"129);
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("A<int>::B<char>"231);
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("A<int>"126);
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("A<int>::B<char>"235);
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("vector_iterator<int>"27);
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