1 //===- unittest/Tooling/QualTypeNameTest.cpp ------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/AST/QualTypeNames.h"
10 #include "TestVisitor.h"
11 using namespace clang
;
14 struct TypeNameVisitor
: TestVisitor
{
15 llvm::StringMap
<std::string
> ExpectedQualTypeNames
;
16 bool WithGlobalNsPrefix
= false;
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
;
43 // named namespaces inside anonymous namespaces
45 TEST(QualTypeNameTest
, Simple
) {
46 TypeNameVisitor Visitor
;
47 // Simple case to test the test framework itself.
48 Visitor
.ExpectedQualTypeNames
["CheckInt"] = "int";
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.
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
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";
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";
100 "template <typename T>\n"
101 "class OuterTemplateClass { public: struct Inner {}; };\n"
104 " class Class0 { };\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"
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"
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"
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"
136 " struct X {} CheckH;\n"
139 "void f(const ::X* CheckN) {}\n"
141 " class aClass {};\n"
145 " struct aStruct {} CheckJ;\n"
150 " class aStruct {};\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"
161 "struct X { typedef int A; };"
164 " var.dependent_type_var = 0;\n"
165 "var.non_dependent_type_var = 0;\n"
167 "class EnumScopeClass {\n"
169 " enum AnEnum { ZERO, ONE };\n"
171 "EnumScopeClass::AnEnum AnEnumVar;\n",
172 TypeNameVisitor::Lang_CXX11
);
175 TEST(QualTypeNameTest
, Complex
) {
176 TypeNameVisitor Complex
;
177 Complex
.ExpectedQualTypeNames
["CheckTX"] = "B::TX";
183 "namespace fake_std {"
184 " template<class... Types > class tuple {};"
187 " using fake_std::tuple;"
188 " typedef tuple<X> TX;"
190 " struct A { typedef int X; };"
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(
201 template<int> class A {};
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(
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"
239 " X Y::Z::*YZMPtr;\n"
247 " class aStruct {};\n"
255 TEST(QualTypeNameTest
, InlineNamespace
) {
256 TypeNameVisitor InlineNamespace
;
257 InlineNamespace
.ExpectedQualTypeNames
["c"] = "B::C";
258 InlineNamespace
.runOver("inline namespace A {\n"
263 "using namespace A::B;\n"
265 TypeNameVisitor::Lang_CXX11
);
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 "
274 AnonStrucs
.ExpectedQualTypeNames
["b"] = "short";
275 AnonStrucs
.ExpectedQualTypeNames
["un_in_st_2"] =
276 "union (unnamed struct at input.cc:1:1)::(unnamed union at "
278 AnonStrucs
.ExpectedQualTypeNames
["anon_st"] =
279 "struct (unnamed struct at input.cc:1:1)";
280 AnonStrucs
.runOver(R
"(struct {
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 {
298 void foo(const S& param1, const S param2);)");
300 } // end anonymous namespace