From 3e55f55048387a8efef01e445d46fc5cf100285d Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov Date: Thu, 3 Jun 2021 10:23:49 -0700 Subject: [PATCH] Fully-qualify template args of outer types in getFullyQualifiedType Template args of outer types were not fully-qualified when calling getFullyQualifiedType() for inner types. For simplicity the patch is a copy-paste of the same call from getFullyQualifiedType(). Reviewed at: https://reviews.llvm.org/D103039 --- clang/lib/AST/QualTypeNames.cpp | 16 ++++++++++++---- clang/unittests/Tooling/QualTypeNamesTest.cpp | 8 +++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 73a33a2..9a1b418 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -356,11 +356,19 @@ NestedNameSpecifier *createNestedNameSpecifier(const ASTContext &Ctx, const TypeDecl *TD, bool FullyQualify, bool WithGlobalNsPrefix) { + const Type *TypePtr = TD->getTypeForDecl(); + if (isa(TypePtr) || + isa(TypePtr)) { + // We are asked to fully qualify and we have a Record Type (which + // may point to a template specialization) or Template + // Specialization Type. We need to fully qualify their arguments. + + TypePtr = getFullyQualifiedTemplateType(Ctx, TypePtr, WithGlobalNsPrefix); + } + return NestedNameSpecifier::Create( - Ctx, - createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), - false /*No TemplateKeyword*/, - TD->getTypeForDecl()); + Ctx, createOuterNNS(Ctx, TD, FullyQualify, WithGlobalNsPrefix), + false /*No TemplateKeyword*/, TypePtr); } /// Return the fully qualified type, including fully-qualified diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp index c820b61..8272edb 100644 --- a/clang/unittests/Tooling/QualTypeNamesTest.cpp +++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp @@ -93,12 +93,14 @@ TEST(QualTypeNameTest, getFullyQualifiedName) { "Foo::non_dependent_type"; Visitor.ExpectedQualTypeNames["AnEnumVar"] = "EnumScopeClass::AnEnum"; Visitor.ExpectedQualTypeNames["AliasTypeVal"] = "A::B::C::InnerAlias"; + Visitor.ExpectedQualTypeNames["AliasInnerTypeVal"] = + "OuterTemplateClass::Inner"; Visitor.ExpectedQualTypeNames["CheckM"] = "const A::B::Class0 *"; Visitor.ExpectedQualTypeNames["CheckN"] = "const X *"; Visitor.runOver( "int CheckInt;\n" "template \n" - "class OuterTemplateClass { };\n" + "class OuterTemplateClass { public: struct Inner {}; };\n" "namespace A {\n" " namespace B {\n" " class Class0 { };\n" @@ -107,6 +109,7 @@ TEST(QualTypeNameTest, getFullyQualifiedName) { " template \n" " using InnerAlias = OuterTemplateClass;\n" " InnerAlias AliasTypeVal;\n" + " InnerAlias::Inner AliasInnerTypeVal;\n" " }\n" " template class Template0;" " template class Template1;" @@ -165,8 +168,7 @@ TEST(QualTypeNameTest, getFullyQualifiedName) { " enum AnEnum { ZERO, ONE };\n" "};\n" "EnumScopeClass::AnEnum AnEnumVar;\n", - TypeNameVisitor::Lang_CXX11 -); + TypeNameVisitor::Lang_CXX11); TypeNameVisitor Complex; Complex.ExpectedQualTypeNames["CheckTX"] = "B::TX"; -- 2.7.4