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 12 using namespace clang; 13 14 namespace { 15 16 class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { 17 public: 18 bool VisitVarDecl(VarDecl *Variable) { 19 Match(Variable->getNameAsString(), Variable->getLocStart()); 20 return true; 21 } 22 }; 23 24 TEST(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 33 class ParmVarDeclVisitorForImplicitCode : 34 public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> { 35 public: 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. 46 TEST(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 62 class NamedDeclVisitor 63 : public ExpectedLocationVisitor<NamedDeclVisitor> { 64 public: 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 76 TEST(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 92 TEST(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 100 TEST(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 110 TEST(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 118 TEST(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 128 TEST(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 141