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