Index: lib/Tooling/Core/QualTypeNames.cpp =================================================================== --- lib/Tooling/Core/QualTypeNames.cpp +++ lib/Tooling/Core/QualTypeNames.cpp @@ -383,10 +383,15 @@ } NestedNameSpecifier *Prefix = nullptr; - Qualifiers PrefixQualifiers; + // Local qualifiers are attached to the QualType outside of the + // elaborated type. Retrieve them before descending into the + // elaborated type. + Qualifiers PrefixQualifiers = QT.getLocalQualifiers(); + QT = QualType(QT.getTypePtr(), 0); ElaboratedTypeKeyword Keyword = ETK_None; if (const auto *ETypeInput = dyn_cast(QT.getTypePtr())) { QT = ETypeInput->getNamedType(); + assert(!QT.hasLocalQualifiers()); Keyword = ETypeInput->getKeyword(); } // Create a nested name specifier if needed (i.e. if the decl context @@ -394,28 +399,21 @@ Prefix = createNestedNameSpecifierForScopeOf(Ctx, QT.getTypePtr(), true /*FullyQualified*/); - // move the qualifiers on the outer type (avoid 'std::const string'!) - if (Prefix) { - PrefixQualifiers = QT.getLocalQualifiers(); - QT = QualType(QT.getTypePtr(), 0); - } - // In case of template specializations iterate over the arguments and // fully qualify them as well. if (isa(QT.getTypePtr()) || isa(QT.getTypePtr())) { // We are asked to fully qualify and we have a Record Type (which - // may pont to a template specialization) or Template + // may point to a template specialization) or Template // Specialization Type. We need to fully qualify their arguments. - Qualifiers Quals = QT.getLocalQualifiers(); const Type *TypePtr = getFullyQualifiedTemplateType(Ctx, QT.getTypePtr()); - QT = Ctx.getQualifiedType(TypePtr, Quals); + QT = QualType(TypePtr, 0); } if (Prefix || Keyword != ETK_None) { QT = Ctx.getElaboratedType(Keyword, Prefix, QT); - QT = Ctx.getQualifiedType(QT, PrefixQualifiers); } + QT = Ctx.getQualifiedType(QT, PrefixQualifiers); return QT; } Index: unittests/Tooling/QualTypeNamesTest.cpp =================================================================== --- unittests/Tooling/QualTypeNamesTest.cpp +++ unittests/Tooling/QualTypeNamesTest.cpp @@ -88,6 +88,8 @@ "Foo::non_dependent_type"; Visitor.ExpectedQualTypeNames["AnEnumVar"] = "EnumScopeClass::AnEnum"; Visitor.ExpectedQualTypeNames["AliasTypeVal"] = "A::B::C::InnerAlias"; + Visitor.ExpectedQualTypeNames["CheckM"] = "const A::B::Class0 *"; + Visitor.ExpectedQualTypeNames["CheckN"] = "const X *"; Visitor.runOver( "int CheckInt;\n" "template \n" @@ -108,6 +110,7 @@ " AnotherClass> CheckC);\n" " void Function2(Template0,\n" " Template0 > CheckD);\n" + " void Function3(const B::Class0* CheckM);\n" " }\n" "template class Variadic {};\n" "Variadic, " @@ -123,6 +126,8 @@ "void f() {\n" " struct X {} CheckH;\n" "}\n" + "struct X;\n" + "void f(const ::X* CheckN) {}\n" "namespace {\n" " class aClass {};\n" " aClass CheckI;\n"