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