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