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 13 using namespace clang; 14 15 namespace { 16 17 class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { 18 public: 19 bool VisitVarDecl(VarDecl *Variable) { 20 Match(Variable->getNameAsString(), Variable->getLocStart()); 21 return true; 22 } 23 }; 24 25 TEST(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 34 class ParmVarDeclVisitorForImplicitCode : 35 public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> { 36 public: 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. 47 TEST(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 63 class NamedDeclVisitor 64 : public ExpectedLocationVisitor<NamedDeclVisitor> { 65 public: 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 77 TEST(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 93 TEST(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 101 TEST(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 111 TEST(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 119 TEST(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 129 TEST(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