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