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