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
<TypeNameVisitor
> {
15 llvm::StringMap
<std::string
> ExpectedQualTypeNames
;
16 bool WithGlobalNsPrefix
= false;
18 // ValueDecls are the least-derived decl with both a qualtype and a
20 bool TraverseDecl(Decl
*D
) {
21 return true; // Always continue
24 bool VisitValueDecl(const ValueDecl
*VD
) {
25 std::string ExpectedName
=
26 ExpectedQualTypeNames
.lookup(VD
->getNameAsString());
27 if (ExpectedName
!= "") {
28 PrintingPolicy
Policy(Context
->getPrintingPolicy());
29 Policy
.SuppressScope
= false;
30 Policy
.AnonymousTagLocations
= true;
31 Policy
.PolishForDeclaration
= true;
32 Policy
.SuppressUnwrittenScope
= true;
33 std::string ActualName
= TypeName::getFullyQualifiedName(
34 VD
->getType(), *Context
, Policy
, WithGlobalNsPrefix
);
35 if (ExpectedName
!= ActualName
) {
36 // A custom message makes it much easier to see what declaration
37 // failed compared to EXPECT_EQ.
38 EXPECT_TRUE(false) << "Typename::getFullyQualifiedName failed for "
39 << VD
->getQualifiedNameAsString() << std::endl
40 << " Actual: " << ActualName
<< std::endl
41 << " Exepcted: " << ExpectedName
;
48 // named namespaces inside anonymous namespaces
50 TEST(QualTypeNameTest
, getFullyQualifiedName
) {
51 TypeNameVisitor Visitor
;
52 // Simple case to test the test framework itself.
53 Visitor
.ExpectedQualTypeNames
["CheckInt"] = "int";
55 // Keeping the names of the variables whose types we check unique
56 // within the entire test--regardless of their own scope--makes it
57 // easier to diagnose test failures.
59 // Simple namespace qualifier
60 Visitor
.ExpectedQualTypeNames
["CheckA"] = "A::B::Class0";
61 // Lookup up the enclosing scopes, then down another one. (These
62 // appear as elaborated type in the AST. In that case--even if
63 // policy.SuppressScope = 0--qual_type.getAsString(policy) only
64 // gives the name as it appears in the source, not the full name.
65 Visitor
.ExpectedQualTypeNames
["CheckB"] = "A::B::C::Class1";
66 // Template parameter expansion.
67 Visitor
.ExpectedQualTypeNames
["CheckC"] =
68 "A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>";
69 // Recursive template parameter expansion.
70 Visitor
.ExpectedQualTypeNames
["CheckD"] =
71 "A::B::Template0<A::B::Template1<A::B::C::MyInt, A::B::AnotherClass>, "
72 "A::B::Template0<int, long> >";
73 // Variadic Template expansion.
74 Visitor
.ExpectedQualTypeNames
["CheckE"] =
75 "A::Variadic<int, A::B::Template0<int, char>, "
76 "A::B::Template1<int, long>, A::B::C::MyInt>";
77 // Using declarations should be fully expanded.
78 Visitor
.ExpectedQualTypeNames
["CheckF"] = "A::B::Class0";
79 // Elements found within "using namespace foo;" should be fully
81 Visitor
.ExpectedQualTypeNames
["CheckG"] = "A::B::C::MyInt";
82 // Type inside function
83 Visitor
.ExpectedQualTypeNames
["CheckH"] = "struct X";
84 // Anonymous Namespaces
85 Visitor
.ExpectedQualTypeNames
["CheckI"] = "aClass";
86 // Keyword inclusion with namespaces
87 Visitor
.ExpectedQualTypeNames
["CheckJ"] = "struct A::aStruct";
88 // Anonymous Namespaces nested in named namespaces and vice-versa.
89 Visitor
.ExpectedQualTypeNames
["CheckK"] = "D::aStruct";
91 Visitor
.ExpectedQualTypeNames
["CheckL"] = "A::B::C::MyInt";
92 Visitor
.ExpectedQualTypeNames
["non_dependent_type_var"] =
93 "Foo<X>::non_dependent_type";
94 Visitor
.ExpectedQualTypeNames
["AnEnumVar"] = "EnumScopeClass::AnEnum";
95 Visitor
.ExpectedQualTypeNames
["AliasTypeVal"] = "A::B::C::InnerAlias<int>";
96 Visitor
.ExpectedQualTypeNames
["CheckM"] = "const A::B::Class0 *";
97 Visitor
.ExpectedQualTypeNames
["CheckN"] = "const X *";
100 "template <typename T>\n"
101 "class OuterTemplateClass { };\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"
111 " template<class X, class Y> class Template0;"
112 " template<class X, class Y> class Template1;"
113 " typedef B::Class0 AnotherClass;\n"
114 " void Function1(Template0<C::MyInt,\n"
115 " AnotherClass> CheckC);\n"
116 " void Function2(Template0<Template1<C::MyInt, AnotherClass>,\n"
117 " Template0<int, long> > CheckD);\n"
118 " void Function3(const B::Class0* CheckM);\n"
120 "template<typename... Values> class Variadic {};\n"
121 "Variadic<int, B::Template0<int, char>, "
122 " B::Template1<int, long>, "
123 " B::C::MyInt > CheckE;\n"
124 " namespace BC = B::C;\n"
125 " BC::MyInt CheckL;\n"
127 "using A::B::Class0;\n"
128 "void Function(Class0 CheckF);\n"
129 "using namespace A::B::C;\n"
130 "void Function(MyInt CheckG);\n"
132 " struct X {} CheckH;\n"
135 "void f(const ::X* CheckN) {}\n"
137 " class aClass {};\n"
141 " struct aStruct {} CheckJ;\n"
146 " class aStruct {};\n"
151 "template<class T> struct Foo {\n"
152 " typedef typename T::A dependent_type;\n"
153 " typedef int non_dependent_type;\n"
154 " dependent_type dependent_type_var;\n"
155 " non_dependent_type non_dependent_type_var;\n"
157 "struct X { typedef int A; };"
160 " var.dependent_type_var = 0;\n"
161 "var.non_dependent_type_var = 0;\n"
163 "class EnumScopeClass {\n"
165 " enum AnEnum { ZERO, ONE };\n"
167 "EnumScopeClass::AnEnum AnEnumVar;\n",
168 TypeNameVisitor::Lang_CXX11
171 TypeNameVisitor Complex
;
172 Complex
.ExpectedQualTypeNames
["CheckTX"] = "B::TX";
178 "namespace fake_std {"
179 " template<class... Types > class tuple {};"
182 " using fake_std::tuple;"
183 " typedef tuple<X> TX;"
185 " struct A { typedef int X; };"
188 TypeNameVisitor GlobalNsPrefix
;
189 GlobalNsPrefix
.WithGlobalNsPrefix
= true;
190 GlobalNsPrefix
.ExpectedQualTypeNames
["IntVal"] = "int";
191 GlobalNsPrefix
.ExpectedQualTypeNames
["BoolVal"] = "bool";
192 GlobalNsPrefix
.ExpectedQualTypeNames
["XVal"] = "::A::B::X";
193 GlobalNsPrefix
.ExpectedQualTypeNames
["IntAliasVal"] = "::A::B::Alias<int>";
194 GlobalNsPrefix
.ExpectedQualTypeNames
["ZVal"] = "::A::B::Y::Z";
195 GlobalNsPrefix
.ExpectedQualTypeNames
["GlobalZVal"] = "::Z";
196 GlobalNsPrefix
.ExpectedQualTypeNames
["CheckK"] = "D::aStruct";
197 GlobalNsPrefix
.ExpectedQualTypeNames
["YZMPtr"] = "::A::B::X ::A::B::Y::Z::*";
198 GlobalNsPrefix
.runOver(
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 { X YZIPtr; }; };\n"
211 " X Y::Z::*YZMPtr;\n"
219 " class aStruct {};\n"
226 TypeNameVisitor InlineNamespace
;
227 InlineNamespace
.ExpectedQualTypeNames
["c"] = "B::C";
228 InlineNamespace
.runOver("inline namespace A {\n"
233 "using namespace A::B;\n"
235 TypeNameVisitor::Lang_CXX11
);
237 TypeNameVisitor AnonStrucs
;
238 AnonStrucs
.ExpectedQualTypeNames
["a"] = "short";
239 AnonStrucs
.ExpectedQualTypeNames
["un_in_st_1"] =
240 "union (anonymous struct at input.cc:1:1)::(anonymous union at "
242 AnonStrucs
.ExpectedQualTypeNames
["b"] = "short";
243 AnonStrucs
.ExpectedQualTypeNames
["un_in_st_2"] =
244 "union (anonymous struct at input.cc:1:1)::(anonymous union at "
246 AnonStrucs
.ExpectedQualTypeNames
["anon_st"] =
247 "struct (anonymous struct at input.cc:1:1)";
248 AnonStrucs
.runOver(R
"(struct {
258 } // end anonymous namespace