Home | History | Annotate | Download | only in Tooling
      1 //===- unittest/Tooling/QualTypeNameTest.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 "clang/Tooling/Core/QualTypeNames.h"
     11 #include "TestVisitor.h"
     12 using namespace clang;
     13 
     14 namespace {
     15 struct TypeNameVisitor : TestVisitor<TypeNameVisitor> {
     16   llvm::StringMap<std::string> ExpectedQualTypeNames;
     17   bool WithGlobalNsPrefix = false;
     18 
     19   // ValueDecls are the least-derived decl with both a qualtype and a
     20   // name.
     21   bool traverseDecl(Decl *D) {
     22     return true;  // Always continue
     23   }
     24 
     25   bool VisitValueDecl(const ValueDecl *VD) {
     26     std::string ExpectedName =
     27         ExpectedQualTypeNames.lookup(VD->getNameAsString());
     28     if (ExpectedName != "") {
     29       std::string ActualName =
     30           TypeName::getFullyQualifiedName(VD->getType(), *Context,
     31                                           WithGlobalNsPrefix);
     32       if (ExpectedName != ActualName) {
     33         // A custom message makes it much easier to see what declaration
     34         // failed compared to EXPECT_EQ.
     35         EXPECT_TRUE(false) << "Typename::getFullyQualifiedName failed for "
     36                            << VD->getQualifiedNameAsString() << std::endl
     37                            << "   Actual: " << ActualName << std::endl
     38                            << " Exepcted: " << ExpectedName;
     39       }
     40     }
     41     return true;
     42   }
     43 };
     44 
     45 // named namespaces inside anonymous namespaces
     46 
     47 TEST(QualTypeNameTest, getFullyQualifiedName) {
     48   TypeNameVisitor Visitor;
     49   // Simple case to test the test framework itself.
     50   Visitor.ExpectedQualTypeNames["CheckInt"] = "int";
     51 
     52   // Keeping the names of the variables whose types we check unique
     53   // within the entire test--regardless of their own scope--makes it
     54   // easier to diagnose test failures.
     55 
     56   // Simple namespace qualifier
     57   Visitor.ExpectedQualTypeNames["CheckA"] = "A::B::Class0";
     58   // Lookup up the enclosing scopes, then down another one. (These
     59   // appear as elaborated type in the AST. In that case--even if
     60   // policy.SuppressScope = 0--qual_type.getAsString(policy) only
     61   // gives the name as it appears in the source, not the full name.
     62   Visitor.ExpectedQualTypeNames["CheckB"] = "A::B::C::Class1";
     63   // Template parameter expansion.
     64   Visitor.ExpectedQualTypeNames["CheckC"] =
     65       "A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>";
     66   // Recursive template parameter expansion.
     67   Visitor.ExpectedQualTypeNames["CheckD"] =
     68       "A::B::Template0<A::B::Template1<A::B::C::MyInt, A::B::AnotherClass>, "
     69       "A::B::Template0<int, long> >";
     70   // Variadic Template expansion.
     71   Visitor.ExpectedQualTypeNames["CheckE"] =
     72       "A::Variadic<int, A::B::Template0<int, char>, "
     73       "A::B::Template1<int, long>, A::B::C::MyInt>";
     74   // Using declarations should be fully expanded.
     75   Visitor.ExpectedQualTypeNames["CheckF"] = "A::B::Class0";
     76   // Elements found within "using namespace foo;" should be fully
     77   // expanded.
     78   Visitor.ExpectedQualTypeNames["CheckG"] = "A::B::C::MyInt";
     79   // Type inside function
     80   Visitor.ExpectedQualTypeNames["CheckH"] = "struct X";
     81   // Anonymous Namespaces
     82   Visitor.ExpectedQualTypeNames["CheckI"] = "aClass";
     83   // Keyword inclusion with namespaces
     84   Visitor.ExpectedQualTypeNames["CheckJ"] = "struct A::aStruct";
     85   // Anonymous Namespaces nested in named namespaces and vice-versa.
     86   Visitor.ExpectedQualTypeNames["CheckK"] = "D::aStruct";
     87   // Namespace alias
     88   Visitor.ExpectedQualTypeNames["CheckL"] = "A::B::C::MyInt";
     89   Visitor.ExpectedQualTypeNames["non_dependent_type_var"] =
     90       "Foo<X>::non_dependent_type";
     91   Visitor.ExpectedQualTypeNames["AnEnumVar"] = "EnumScopeClass::AnEnum";
     92   Visitor.ExpectedQualTypeNames["AliasTypeVal"] = "A::B::C::InnerAlias<int>";
     93   Visitor.ExpectedQualTypeNames["CheckM"] = "const A::B::Class0 *";
     94   Visitor.ExpectedQualTypeNames["CheckN"] = "const X *";
     95   Visitor.runOver(
     96       "int CheckInt;\n"
     97       "template <typename T>\n"
     98       "class OuterTemplateClass { };\n"
     99       "namespace A {\n"
    100       " namespace B {\n"
    101       "   class Class0 { };\n"
    102       "   namespace C {\n"
    103       "     typedef int MyInt;"
    104       "     template <typename T>\n"
    105       "     using InnerAlias = OuterTemplateClass<T>;\n"
    106       "     InnerAlias<int> AliasTypeVal;\n"
    107       "   }\n"
    108       "   template<class X, class Y> class Template0;"
    109       "   template<class X, class Y> class Template1;"
    110       "   typedef B::Class0 AnotherClass;\n"
    111       "   void Function1(Template0<C::MyInt,\n"
    112       "                  AnotherClass> CheckC);\n"
    113       "   void Function2(Template0<Template1<C::MyInt, AnotherClass>,\n"
    114       "                            Template0<int, long> > CheckD);\n"
    115       "   void Function3(const B::Class0* CheckM);\n"
    116       "  }\n"
    117       "template<typename... Values> class Variadic {};\n"
    118       "Variadic<int, B::Template0<int, char>, "
    119       "         B::Template1<int, long>, "
    120       "         B::C::MyInt > CheckE;\n"
    121       " namespace BC = B::C;\n"
    122       " BC::MyInt CheckL;\n"
    123       "}\n"
    124       "using A::B::Class0;\n"
    125       "void Function(Class0 CheckF);\n"
    126       "using namespace A::B::C;\n"
    127       "void Function(MyInt CheckG);\n"
    128       "void f() {\n"
    129       "  struct X {} CheckH;\n"
    130       "}\n"
    131       "struct X;\n"
    132       "void f(const ::X* CheckN) {}\n"
    133       "namespace {\n"
    134       "  class aClass {};\n"
    135       "   aClass CheckI;\n"
    136       "}\n"
    137       "namespace A {\n"
    138       "  struct aStruct {} CheckJ;\n"
    139       "}\n"
    140       "namespace {\n"
    141       "  namespace D {\n"
    142       "    namespace {\n"
    143       "      class aStruct {};\n"
    144       "      aStruct CheckK;\n"
    145       "    }\n"
    146       "  }\n"
    147       "}\n"
    148       "template<class T> struct Foo {\n"
    149       "  typedef typename T::A dependent_type;\n"
    150       "  typedef int non_dependent_type;\n"
    151       "  dependent_type dependent_type_var;\n"
    152       "  non_dependent_type non_dependent_type_var;\n"
    153       "};\n"
    154       "struct X { typedef int A; };"
    155       "Foo<X> var;"
    156       "void F() {\n"
    157       "  var.dependent_type_var = 0;\n"
    158       "var.non_dependent_type_var = 0;\n"
    159       "}\n"
    160       "class EnumScopeClass {\n"
    161       "public:\n"
    162       "  enum AnEnum { ZERO, ONE };\n"
    163       "};\n"
    164       "EnumScopeClass::AnEnum AnEnumVar;\n",
    165       TypeNameVisitor::Lang_CXX11
    166 );
    167 
    168   TypeNameVisitor Complex;
    169   Complex.ExpectedQualTypeNames["CheckTX"] = "B::TX";
    170   Complex.runOver(
    171       "namespace A {"
    172       "  struct X {};"
    173       "}"
    174       "using A::X;"
    175       "namespace fake_std {"
    176       "  template<class... Types > class tuple {};"
    177       "}"
    178       "namespace B {"
    179       "  using fake_std::tuple;"
    180       "  typedef tuple<X> TX;"
    181       "  TX CheckTX;"
    182       "  struct A { typedef int X; };"
    183       "}");
    184 
    185   TypeNameVisitor GlobalNsPrefix;
    186   GlobalNsPrefix.WithGlobalNsPrefix = true;
    187   GlobalNsPrefix.ExpectedQualTypeNames["IntVal"] = "int";
    188   GlobalNsPrefix.ExpectedQualTypeNames["BoolVal"] = "bool";
    189   GlobalNsPrefix.ExpectedQualTypeNames["XVal"] = "::A::B::X";
    190   GlobalNsPrefix.ExpectedQualTypeNames["IntAliasVal"] = "::A::B::Alias<int>";
    191   GlobalNsPrefix.ExpectedQualTypeNames["ZVal"] = "::A::B::Y::Z";
    192   GlobalNsPrefix.ExpectedQualTypeNames["GlobalZVal"] = "::Z";
    193   GlobalNsPrefix.ExpectedQualTypeNames["CheckK"] = "D::aStruct";
    194   GlobalNsPrefix.runOver(
    195       "namespace A {\n"
    196       "  namespace B {\n"
    197       "    int IntVal;\n"
    198       "    bool BoolVal;\n"
    199       "    struct X {};\n"
    200       "    X XVal;\n"
    201       "    template <typename T> class CCC { };\n"
    202       "    template <typename T>\n"
    203       "    using Alias = CCC<T>;\n"
    204       "    Alias<int> IntAliasVal;\n"
    205       "    struct Y { struct Z {}; };\n"
    206       "    Y::Z ZVal;\n"
    207       "  }\n"
    208       "}\n"
    209       "struct Z {};\n"
    210       "Z GlobalZVal;\n"
    211       "namespace {\n"
    212       "  namespace D {\n"
    213       "    namespace {\n"
    214       "      class aStruct {};\n"
    215       "      aStruct CheckK;\n"
    216       "    }\n"
    217       "  }\n"
    218       "}\n"
    219   );
    220 }
    221 
    222 }  // end anonymous namespace
    223