//===- unittest/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "TestVisitor.h" #include <stack> using namespace clang; namespace { class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> { public: bool VisitVarDecl(VarDecl *Variable) { Match(Variable->getNameAsString(), Variable->getLocStart()); return true; } }; TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) { VarDeclVisitor Visitor; Visitor.ExpectMatch("i", 2, 17); EXPECT_TRUE(Visitor.runOver( "int x[5];\n" "void f() { for (int i : x) {} }", VarDeclVisitor::Lang_CXX11)); } class ParmVarDeclVisitorForImplicitCode : public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> { public: bool shouldVisitImplicitCode() const { return true; } bool VisitParmVarDecl(ParmVarDecl *ParamVar) { Match(ParamVar->getNameAsString(), ParamVar->getLocStart()); return true; } }; // Test RAV visits parameter variable declaration of the implicit // copy assignment operator and implicit copy constructor. TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) { ParmVarDeclVisitorForImplicitCode Visitor; // Match parameter variable name of implicit copy assignment operator and // implicit copy constructor. // This parameter name does not have a valid IdentifierInfo, and shares // same SourceLocation with its class declaration, so we match an empty name // with the class' source location. Visitor.ExpectMatch("", 1, 7); Visitor.ExpectMatch("", 3, 7); EXPECT_TRUE(Visitor.runOver( "class X {};\n" "void foo(X a, X b) {a = b;}\n" "class Y {};\n" "void bar(Y a) {Y b = a;}")); } class NamedDeclVisitor : public ExpectedLocationVisitor<NamedDeclVisitor> { public: bool VisitNamedDecl(NamedDecl *Decl) { std::string NameWithTemplateArgs; llvm::raw_string_ostream OS(NameWithTemplateArgs); Decl->getNameForDiagnostic(OS, Decl->getASTContext().getPrintingPolicy(), true); Match(OS.str(), Decl->getLocation()); return true; } }; TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) { // From cfe-commits/Week-of-Mon-20100830/033998.html // Contrary to the approach suggested in that email, we visit all // specializations when we visit the primary template. Visiting them when we // visit the associated specialization is problematic for specializations of // template members of class templates. NamedDeclVisitor Visitor; Visitor.ExpectMatch("A<bool>", 1, 26); Visitor.ExpectMatch("A<char *>", 2, 26); EXPECT_TRUE(Visitor.runOver( "template <class T> class A {};\n" "template <class T> class A<T*> {};\n" "A<bool> ab;\n" "A<char*> acp;\n")); } TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) { NamedDeclVisitor Visitor; Visitor.ExpectMatch("A<int>", 1, 29); EXPECT_TRUE(Visitor.runOver( "template<typename T> struct A;\n" "A<int> *p;\n")); } TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) { NamedDeclVisitor Visitor; Visitor.ExpectMatch("A<int>::B<char>", 2, 31); EXPECT_TRUE(Visitor.runOver( "template<typename T> struct A {\n" " template<typename U> struct B;\n" "};\n" "A<int>::B<char> *p;\n")); } TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) { NamedDeclVisitor Visitor; Visitor.ExpectMatch("A<int>", 1, 26); EXPECT_TRUE(Visitor.runOver( "template<typename T> int A();\n" "int k = A<int>();\n")); } TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) { NamedDeclVisitor Visitor; Visitor.ExpectMatch("A<int>::B<char>", 2, 35); EXPECT_TRUE(Visitor.runOver( "template<typename T> struct A {\n" " template<typename U> static int B();\n" "};\n" "int k = A<int>::B<char>();\n")); } TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) { // From cfe-commits/Week-of-Mon-20100830/033977.html NamedDeclVisitor Visitor; Visitor.ExpectMatch("vector_iterator<int>", 2, 7); EXPECT_TRUE(Visitor.runOver( "template<typename Container>\n" "class vector_iterator {\n" " template <typename C> friend class vector_iterator;\n" "};\n" "vector_iterator<int> it_int;\n")); } } // end anonymous namespace