Home | History | Annotate | Download | only in Tooling
      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