1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "clang/AST/QualTypeNames.h" |
10 | #include "TestVisitor.h" |
11 | using namespace clang; |
12 | |
13 | namespace { |
14 | struct TypeNameVisitor : TestVisitor<TypeNameVisitor> { |
15 | llvm::StringMap<std::string> ExpectedQualTypeNames; |
16 | bool WithGlobalNsPrefix = false; |
17 | |
18 | |
19 | |
20 | bool traverseDecl(Decl *D) { |
21 | return true; |
22 | } |
23 | |
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 | |
37 | |
38 | EXPECT_TRUE(false) << "Typename::getFullyQualifiedName failed for " |
39 | << VD->getQualifiedNameAsString() << std::endl |
40 | << " Actual: " << ActualName << std::endl |
41 | << " Exepcted: " << ExpectedName; |
42 | } |
43 | } |
44 | return true; |
45 | } |
46 | }; |
47 | |
48 | |
49 | |
50 | TEST(QualTypeNameTest, getFullyQualifiedName) { |
51 | TypeNameVisitor Visitor; |
52 | |
53 | Visitor.ExpectedQualTypeNames["CheckInt"] = "int"; |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | Visitor.ExpectedQualTypeNames["CheckA"] = "A::B::Class0"; |
61 | |
62 | |
63 | |
64 | |
65 | Visitor.ExpectedQualTypeNames["CheckB"] = "A::B::C::Class1"; |
66 | |
67 | Visitor.ExpectedQualTypeNames["CheckC"] = |
68 | "A::B::Template0<A::B::C::MyInt, A::B::AnotherClass>"; |
69 | |
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 | |
74 | Visitor.ExpectedQualTypeNames["CheckE"] = |
75 | "A::Variadic<int, A::B::Template0<int, char>, " |
76 | "A::B::Template1<int, long>, A::B::C::MyInt>"; |
77 | |
78 | Visitor.ExpectedQualTypeNames["CheckF"] = "A::B::Class0"; |
79 | |
80 | |
81 | Visitor.ExpectedQualTypeNames["CheckG"] = "A::B::C::MyInt"; |
82 | |
83 | Visitor.ExpectedQualTypeNames["CheckH"] = "struct X"; |
84 | |
85 | Visitor.ExpectedQualTypeNames["CheckI"] = "aClass"; |
86 | |
87 | Visitor.ExpectedQualTypeNames["CheckJ"] = "struct A::aStruct"; |
88 | |
89 | Visitor.ExpectedQualTypeNames["CheckK"] = "D::aStruct"; |
90 | |
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 *"; |
98 | Visitor.runOver( |
99 | "int CheckInt;\n" |
100 | "template <typename T>\n" |
101 | "class OuterTemplateClass { };\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 | " }\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" |
119 | " }\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" |
126 | "}\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" |
131 | "void f() {\n" |
132 | " struct X {} CheckH;\n" |
133 | "}\n" |
134 | "struct X;\n" |
135 | "void f(const ::X* CheckN) {}\n" |
136 | "namespace {\n" |
137 | " class aClass {};\n" |
138 | " aClass CheckI;\n" |
139 | "}\n" |
140 | "namespace A {\n" |
141 | " struct aStruct {} CheckJ;\n" |
142 | "}\n" |
143 | "namespace {\n" |
144 | " namespace D {\n" |
145 | " namespace {\n" |
146 | " class aStruct {};\n" |
147 | " aStruct CheckK;\n" |
148 | " }\n" |
149 | " }\n" |
150 | "}\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" |
156 | "};\n" |
157 | "struct X { typedef int A; };" |
158 | "Foo<X> var;" |
159 | "void F() {\n" |
160 | " var.dependent_type_var = 0;\n" |
161 | "var.non_dependent_type_var = 0;\n" |
162 | "}\n" |
163 | "class EnumScopeClass {\n" |
164 | "public:\n" |
165 | " enum AnEnum { ZERO, ONE };\n" |
166 | "};\n" |
167 | "EnumScopeClass::AnEnum AnEnumVar;\n", |
168 | TypeNameVisitor::Lang_CXX11 |
169 | ); |
170 | |
171 | TypeNameVisitor Complex; |
172 | Complex.ExpectedQualTypeNames["CheckTX"] = "B::TX"; |
173 | Complex.runOver( |
174 | "namespace A {" |
175 | " struct X {};" |
176 | "}" |
177 | "using A::X;" |
178 | "namespace fake_std {" |
179 | " template<class... Types > class tuple {};" |
180 | "}" |
181 | "namespace B {" |
182 | " using fake_std::tuple;" |
183 | " typedef tuple<X> TX;" |
184 | " TX CheckTX;" |
185 | " struct A { typedef int X; };" |
186 | "}"); |
187 | |
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( |
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 { X YZIPtr; }; };\n" |
210 | " Y::Z ZVal;\n" |
211 | " X Y::Z::*YZMPtr;\n" |
212 | " }\n" |
213 | "}\n" |
214 | "struct Z {};\n" |
215 | "Z GlobalZVal;\n" |
216 | "namespace {\n" |
217 | " namespace D {\n" |
218 | " namespace {\n" |
219 | " class aStruct {};\n" |
220 | " aStruct CheckK;\n" |
221 | " }\n" |
222 | " }\n" |
223 | "}\n" |
224 | ); |
225 | |
226 | TypeNameVisitor AnonStrucs; |
227 | AnonStrucs.ExpectedQualTypeNames["a"] = "short"; |
228 | AnonStrucs.ExpectedQualTypeNames["un_in_st_1"] = |
229 | "union (anonymous struct at input.cc:1:1)::(anonymous union at " |
230 | "input.cc:2:27)"; |
231 | AnonStrucs.ExpectedQualTypeNames["b"] = "short"; |
232 | AnonStrucs.ExpectedQualTypeNames["un_in_st_2"] = |
233 | "union (anonymous struct at input.cc:1:1)::(anonymous union at " |
234 | "input.cc:5:27)"; |
235 | AnonStrucs.ExpectedQualTypeNames["anon_st"] = |
236 | "struct (anonymous struct at input.cc:1:1)"; |
237 | AnonStrucs.runOver(R"(struct { |
238 | union { |
239 | short a; |
240 | } un_in_st_1; |
241 | union { |
242 | short b; |
243 | } un_in_st_2; |
244 | } anon_st;)"); |
245 | } |
246 | |
247 | } |
248 | |