When forming a fully-qualified type name, put any qualifiers outside/before the

nested-name-specifier. Patch by Sterling Augustine!

llvm-svn: 268988
This commit is contained in:
Richard Smith 2016-05-09 23:06:14 +00:00
parent 0a77dfad95
commit 57443fce3f
2 changed files with 14 additions and 11 deletions

View File

@ -383,10 +383,15 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx) {
}
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<ElaboratedType>(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 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx) {
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<const TemplateSpecializationType>(QT.getTypePtr()) ||
isa<const RecordType>(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;
}

View File

@ -88,6 +88,8 @@ TEST(QualTypeNameTest, getFullyQualifiedName) {
"Foo<X>::non_dependent_type";
Visitor.ExpectedQualTypeNames["AnEnumVar"] = "EnumScopeClass::AnEnum";
Visitor.ExpectedQualTypeNames["AliasTypeVal"] = "A::B::C::InnerAlias<int>";
Visitor.ExpectedQualTypeNames["CheckM"] = "const A::B::Class0 *";
Visitor.ExpectedQualTypeNames["CheckN"] = "const X *";
Visitor.runOver(
"int CheckInt;\n"
"template <typename T>\n"
@ -108,6 +110,7 @@ TEST(QualTypeNameTest, getFullyQualifiedName) {
" AnotherClass> CheckC);\n"
" void Function2(Template0<Template1<C::MyInt, AnotherClass>,\n"
" Template0<int, long> > CheckD);\n"
" void Function3(const B::Class0* CheckM);\n"
" }\n"
"template<typename... Values> class Variadic {};\n"
"Variadic<int, B::Template0<int, char>, "
@ -123,6 +126,8 @@ TEST(QualTypeNameTest, getFullyQualifiedName) {
"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"