diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 7557336f0aafa..6ed5c9c3b2dee 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -272,43 +272,22 @@ static NestedNameSpecifier *createNestedNameSpecifierForScopeOf( const auto *Outer = dyn_cast_or_null(DC); const auto *OuterNS = dyn_cast_or_null(DC); if (Outer && !(OuterNS && OuterNS->isAnonymousNamespace())) { - if (const auto *CxxDecl = dyn_cast(DC)) { - if (ClassTemplateDecl *ClassTempl = - CxxDecl->getDescribedClassTemplate()) { - // We are in the case of a type(def) that was declared in a - // class template but is *not* type dependent. In clang, it - // gets attached to the class template declaration rather than - // any specific class template instantiation. This result in - // 'odd' fully qualified typename: - // - // vector<_Tp,_Alloc>::size_type - // - // Make the situation is 'useable' but looking a bit odd by - // picking a random instance as the declaring context. - if (ClassTempl->spec_begin() != ClassTempl->spec_end()) { - Decl = *(ClassTempl->spec_begin()); - Outer = dyn_cast(Decl); - OuterNS = dyn_cast(Decl); - } + if (OuterNS) { + return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix); + } else if (const auto *TD = dyn_cast(Outer)) { + return createNestedNameSpecifier(Ctx, TD, FullyQualified, + WithGlobalNsPrefix); + } else if (isa(Outer)) { + // Context is the TU. Nothing needs to be done. + return nullptr; + } else { + // Decl's context was neither the TU, a namespace, nor a + // TagDecl, which means it is a type local to a scope, and not + // accessible at the end of the TU. + return nullptr; } - } - - if (OuterNS) { - return createNestedNameSpecifier(Ctx, OuterNS, WithGlobalNsPrefix); - } else if (const auto *TD = dyn_cast(Outer)) { - return createNestedNameSpecifier( - Ctx, TD, FullyQualified, WithGlobalNsPrefix); - } else if (isa(Outer)) { - // Context is the TU. Nothing needs to be done. - return nullptr; - } else { - // Decl's context was neither the TU, a namespace, nor a - // TagDecl, which means it is a type local to a scope, and not - // accessible at the end of the TU. - return nullptr; - } } else if (WithGlobalNsPrefix && DC->isTranslationUnit()) { - return NestedNameSpecifier::GlobalSpecifier(Ctx); + return NestedNameSpecifier::GlobalSpecifier(Ctx); } return nullptr; } diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp index 686d189cf69eb..18286f9e74921 100644 --- a/clang/unittests/Tooling/QualTypeNamesTest.cpp +++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp @@ -85,7 +85,7 @@ TEST(QualTypeNameTest, Simple) { // Namespace alias Visitor.ExpectedQualTypeNames["CheckL"] = "A::B::C::MyInt"; Visitor.ExpectedQualTypeNames["non_dependent_type_var"] = - "Foo::non_dependent_type"; + "Foo::non_dependent_type"; Visitor.ExpectedQualTypeNames["AnEnumVar"] = "EnumScopeClass::AnEnum"; Visitor.ExpectedQualTypeNames["AliasTypeVal"] = "A::B::C::InnerAlias"; Visitor.ExpectedQualTypeNames["AliasInnerTypeVal"] = @@ -175,20 +175,19 @@ TEST(QualTypeNameTest, Simple) { TEST(QualTypeNameTest, Complex) { TypeNameVisitor Complex; Complex.ExpectedQualTypeNames["CheckTX"] = "B::TX"; - Complex.runOver( - "namespace A {" - " struct X {};" - "}" - "using A::X;" - "namespace fake_std {" - " template class tuple {};" - "}" - "namespace B {" - " using fake_std::tuple;" - " typedef tuple TX;" - " TX CheckTX;" - " struct A { typedef int X; };" - "}"); + Complex.runOver("namespace A {" + " struct X {};" + "}" + "using A::X;" + "namespace fake_std {" + " template class tuple {};" + "}" + "namespace B {" + " using fake_std::tuple;" + " typedef tuple TX;" + " TX CheckTX;" + " struct A { typedef int X; };" + "}"); } TEST(QualTypeNameTest, DoubleUsing) { @@ -223,33 +222,31 @@ TEST(QualTypeNameTest, GlobalNsPrefix) { GlobalNsPrefix.ExpectedQualTypeNames["GlobalZVal"] = "::Z"; GlobalNsPrefix.ExpectedQualTypeNames["CheckK"] = "D::aStruct"; GlobalNsPrefix.ExpectedQualTypeNames["YZMPtr"] = "::A::B::X ::A::B::Y::Z::*"; - GlobalNsPrefix.runOver( - "namespace A {\n" - " namespace B {\n" - " int IntVal;\n" - " bool BoolVal;\n" - " struct X {};\n" - " X XVal;\n" - " template class CCC { };\n" - " template \n" - " using Alias = CCC;\n" - " Alias IntAliasVal;\n" - " struct Y { struct Z { X YZIPtr; }; };\n" - " Y::Z ZVal;\n" - " X Y::Z::*YZMPtr;\n" - " }\n" - "}\n" - "struct Z {};\n" - "Z GlobalZVal;\n" - "namespace {\n" - " namespace D {\n" - " namespace {\n" - " class aStruct {};\n" - " aStruct CheckK;\n" - " }\n" - " }\n" - "}\n" - ); + GlobalNsPrefix.runOver("namespace A {\n" + " namespace B {\n" + " int IntVal;\n" + " bool BoolVal;\n" + " struct X {};\n" + " X XVal;\n" + " template class CCC { };\n" + " template \n" + " using Alias = CCC;\n" + " Alias IntAliasVal;\n" + " struct Y { struct Z { X YZIPtr; }; };\n" + " Y::Z ZVal;\n" + " X Y::Z::*YZMPtr;\n" + " }\n" + "}\n" + "struct Z {};\n" + "Z GlobalZVal;\n" + "namespace {\n" + " namespace D {\n" + " namespace {\n" + " class aStruct {};\n" + " aStruct CheckK;\n" + " }\n" + " }\n" + "}\n"); } TEST(QualTypeNameTest, InlineNamespace) { @@ -297,4 +294,4 @@ TEST(QualTypeNameTest, ConstUsing) { using ::A::S; void foo(const S& param1, const S param2);)"); } -} // end anonymous namespace +} // end anonymous namespace