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