Clang Project

clang_source_code/unittests/Tooling/QualTypeNamesTest.cpp
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"
11using namespace clang;
12
13namespace {
14struct TypeNameVisitor : TestVisitor<TypeNameVisitor> {
15  llvm::StringMap<std::string> ExpectedQualTypeNames;
16  bool WithGlobalNsPrefix = false;
17
18  // ValueDecls are the least-derived decl with both a qualtype and a
19  // name.
20  bool traverseDecl(Decl *D) {
21    return true;  // Always continue
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        // 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;
42      }
43    }
44    return true;
45  }
46};
47
48// named namespaces inside anonymous namespaces
49
50TEST(QualTypeNameTest, getFullyQualifiedName) {
51  TypeNameVisitor Visitor;
52  // Simple case to test the test framework itself.
53  Visitor.ExpectedQualTypeNames["CheckInt"] = "int";
54
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.
58
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
80  // expanded.
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";
90  // Namespace alias
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}  // end anonymous namespace
248