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