| 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 | |