Pirama Arumuga Nainar | 4967a71 | 2016-09-19 22:19:55 -0700 | [diff] [blame] | 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. |
| 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 | 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 | |
| 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 |