xref: /llvm-project/clang/unittests/Tooling/QualTypeNamesTest.cpp (revision 4e600751d2f7e8e7b85a71b7128b68444bdde91b)
1 //===- unittest/Tooling/QualTypeNameTest.cpp ------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/AST/QualTypeNames.h"
10 #include "TestVisitor.h"
11 using namespace clang;
12 
13 namespace {
14 struct TypeNameVisitor : TestVisitor {
15   llvm::StringMap<std::string> ExpectedQualTypeNames;
16   bool WithGlobalNsPrefix = false;
17 
18   // ValueDecls are the least-derived decl with both a qualtype and a name.
19   bool VisitValueDecl(ValueDecl *VD) override {
20     std::string ExpectedName =
21         ExpectedQualTypeNames.lookup(VD->getNameAsString());
22     if (ExpectedName != "") {
23       PrintingPolicy Policy(Context->getPrintingPolicy());
24       Policy.SuppressScope = false;
25       Policy.AnonymousTagLocations = true;
26       Policy.PolishForDeclaration = true;
27       Policy.SuppressUnwrittenScope = true;
28       std::string ActualName = TypeName::getFullyQualifiedName(
29           VD->getType(), *Context, Policy, WithGlobalNsPrefix);
30       if (ExpectedName != ActualName) {
31         // A custom message makes it much easier to see what declaration
32         // failed compared to EXPECT_EQ.
33         ADD_FAILURE() << "Typename::getFullyQualifiedName failed for "
34                       << VD->getQualifiedNameAsString() << std::endl
35                       << "   Actual: " << ActualName << std::endl
36                       << " Expected: " << ExpectedName;
37       }
38     }
39     return true;
40   }
41 };
42 
43 // named namespaces inside anonymous namespaces
44 
45 TEST(QualTypeNameTest, Simple) {
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["AliasInnerTypeVal"] =
92       "OuterTemplateClass<A::B::Class0>::Inner";
93   Visitor.ExpectedQualTypeNames["CheckM"] = "const A::B::Class0 *";
94   Visitor.ExpectedQualTypeNames["CheckN"] = "const X *";
95   Visitor.ExpectedQualTypeNames["ttp_using"] =
96       "OuterTemplateClass<A::B::Class0>";
97   Visitor.ExpectedQualTypeNames["alias_of_template"] = "ABTemplate0IntInt";
98   Visitor.runOver(
99       "int CheckInt;\n"
100       "template <typename T>\n"
101       "class OuterTemplateClass { public: struct Inner {}; };\n"
102       "namespace A {\n"
103       " namespace B {\n"
104       "   class Class0 { };\n"
105       "   namespace C {\n"
106       "     typedef int MyInt;"
107       "     template <typename T>\n"
108       "     using InnerAlias = OuterTemplateClass<T>;\n"
109       "     InnerAlias<int> AliasTypeVal;\n"
110       "     InnerAlias<Class0>::Inner AliasInnerTypeVal;\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       "OuterTemplateClass<Class0> ttp_using;\n"
131       "using ABTemplate0IntInt = A::B::Template0<int, int>;\n"
132       "void Function(ABTemplate0IntInt alias_of_template);\n"
133       "using namespace A::B::C;\n"
134       "void Function(MyInt CheckG);\n"
135       "void f() {\n"
136       "  struct X {} CheckH;\n"
137       "}\n"
138       "struct X;\n"
139       "void f(const ::X* CheckN) {}\n"
140       "namespace {\n"
141       "  class aClass {};\n"
142       "   aClass CheckI;\n"
143       "}\n"
144       "namespace A {\n"
145       "  struct aStruct {} CheckJ;\n"
146       "}\n"
147       "namespace {\n"
148       "  namespace D {\n"
149       "    namespace {\n"
150       "      class aStruct {};\n"
151       "      aStruct CheckK;\n"
152       "    }\n"
153       "  }\n"
154       "}\n"
155       "template<class T> struct Foo {\n"
156       "  typedef typename T::A dependent_type;\n"
157       "  typedef int non_dependent_type;\n"
158       "  dependent_type dependent_type_var;\n"
159       "  non_dependent_type non_dependent_type_var;\n"
160       "};\n"
161       "struct X { typedef int A; };"
162       "Foo<X> var;"
163       "void F() {\n"
164       "  var.dependent_type_var = 0;\n"
165       "var.non_dependent_type_var = 0;\n"
166       "}\n"
167       "class EnumScopeClass {\n"
168       "public:\n"
169       "  enum AnEnum { ZERO, ONE };\n"
170       "};\n"
171       "EnumScopeClass::AnEnum AnEnumVar;\n",
172       TypeNameVisitor::Lang_CXX11);
173 }
174 
175 TEST(QualTypeNameTest, Complex) {
176   TypeNameVisitor Complex;
177   Complex.ExpectedQualTypeNames["CheckTX"] = "B::TX";
178   Complex.runOver(
179       "namespace A {"
180       "  struct X {};"
181       "}"
182       "using A::X;"
183       "namespace fake_std {"
184       "  template<class... Types > class tuple {};"
185       "}"
186       "namespace B {"
187       "  using fake_std::tuple;"
188       "  typedef tuple<X> TX;"
189       "  TX CheckTX;"
190       "  struct A { typedef int X; };"
191       "}");
192 }
193 
194 TEST(QualTypeNameTest, DoubleUsing) {
195   TypeNameVisitor DoubleUsing;
196   DoubleUsing.ExpectedQualTypeNames["direct"] = "a::A<0>";
197   DoubleUsing.ExpectedQualTypeNames["indirect"] = "b::B";
198   DoubleUsing.ExpectedQualTypeNames["double_indirect"] = "b::B";
199   DoubleUsing.runOver(R"cpp(
200     namespace a {
201       template<int> class A {};
202       A<0> direct;
203     }
204     namespace b {
205       using B = ::a::A<0>;
206       B indirect;
207     }
208     namespace b {
209       using ::b::B;
210       B double_indirect;
211     }
212   )cpp");
213 }
214 
215 TEST(QualTypeNameTest, GlobalNsPrefix) {
216   TypeNameVisitor GlobalNsPrefix;
217   GlobalNsPrefix.WithGlobalNsPrefix = true;
218   GlobalNsPrefix.ExpectedQualTypeNames["IntVal"] = "int";
219   GlobalNsPrefix.ExpectedQualTypeNames["BoolVal"] = "bool";
220   GlobalNsPrefix.ExpectedQualTypeNames["XVal"] = "::A::B::X";
221   GlobalNsPrefix.ExpectedQualTypeNames["IntAliasVal"] = "::A::B::Alias<int>";
222   GlobalNsPrefix.ExpectedQualTypeNames["ZVal"] = "::A::B::Y::Z";
223   GlobalNsPrefix.ExpectedQualTypeNames["GlobalZVal"] = "::Z";
224   GlobalNsPrefix.ExpectedQualTypeNames["CheckK"] = "D::aStruct";
225   GlobalNsPrefix.ExpectedQualTypeNames["YZMPtr"] = "::A::B::X ::A::B::Y::Z::*";
226   GlobalNsPrefix.runOver(
227       "namespace A {\n"
228       "  namespace B {\n"
229       "    int IntVal;\n"
230       "    bool BoolVal;\n"
231       "    struct X {};\n"
232       "    X XVal;\n"
233       "    template <typename T> class CCC { };\n"
234       "    template <typename T>\n"
235       "    using Alias = CCC<T>;\n"
236       "    Alias<int> IntAliasVal;\n"
237       "    struct Y { struct Z { X YZIPtr; }; };\n"
238       "    Y::Z ZVal;\n"
239       "    X Y::Z::*YZMPtr;\n"
240       "  }\n"
241       "}\n"
242       "struct Z {};\n"
243       "Z GlobalZVal;\n"
244       "namespace {\n"
245       "  namespace D {\n"
246       "    namespace {\n"
247       "      class aStruct {};\n"
248       "      aStruct CheckK;\n"
249       "    }\n"
250       "  }\n"
251       "}\n"
252   );
253 }
254 
255 TEST(QualTypeNameTest, InlineNamespace) {
256   TypeNameVisitor InlineNamespace;
257   InlineNamespace.ExpectedQualTypeNames["c"] = "B::C";
258   InlineNamespace.runOver("inline namespace A {\n"
259                           "  namespace B {\n"
260                           "    class C {};\n"
261                           "  }\n"
262                           "}\n"
263                           "using namespace A::B;\n"
264                           "C c;\n",
265                           TypeNameVisitor::Lang_CXX11);
266 }
267 
268 TEST(QualTypeNameTest, AnonStrucs) {
269   TypeNameVisitor AnonStrucs;
270   AnonStrucs.ExpectedQualTypeNames["a"] = "short";
271   AnonStrucs.ExpectedQualTypeNames["un_in_st_1"] =
272       "union (unnamed struct at input.cc:1:1)::(unnamed union at "
273       "input.cc:2:27)";
274   AnonStrucs.ExpectedQualTypeNames["b"] = "short";
275   AnonStrucs.ExpectedQualTypeNames["un_in_st_2"] =
276       "union (unnamed struct at input.cc:1:1)::(unnamed union at "
277       "input.cc:5:27)";
278   AnonStrucs.ExpectedQualTypeNames["anon_st"] =
279       "struct (unnamed struct at input.cc:1:1)";
280   AnonStrucs.runOver(R"(struct {
281                           union {
282                             short a;
283                           } un_in_st_1;
284                           union {
285                             short b;
286                           } un_in_st_2;
287                         } anon_st;)");
288 }
289 
290 TEST(QualTypeNameTest, ConstUsing) {
291   TypeNameVisitor ConstUsing;
292   ConstUsing.ExpectedQualTypeNames["param1"] = "const A::S &";
293   ConstUsing.ExpectedQualTypeNames["param2"] = "const A::S";
294   ConstUsing.runOver(R"(namespace A {
295                           class S {};
296                         }
297                         using ::A::S;
298                         void foo(const S& param1, const S param2);)");
299 }
300 }  // end anonymous namespace
301