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