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