diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp index 7cdee52acce3f..191841649a86f 100644 --- a/clang/lib/AST/QualTypeNames.cpp +++ b/clang/lib/AST/QualTypeNames.cpp @@ -369,17 +369,6 @@ NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx, /// versions of any template parameters. QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx, bool WithGlobalNsPrefix) { - // Use the underlying deduced type for AutoType - if (const auto *AT = dyn_cast(QT.getTypePtr())) { - if (AT->isDeduced()) { - // Get the qualifiers. - Qualifiers Quals = QT.getQualifiers(); - QT = AT->getDeducedType(); - // Add back the qualifiers. - QT = Ctx.getQualifiedType(QT, Quals); - } - } - // In case of myType* we need to strip the pointer first, fully // qualify and attach the pointer once again. if (isa(QT.getTypePtr())) { diff --git a/clang/lib/Interpreter/InterpreterValuePrinter.cpp b/clang/lib/Interpreter/InterpreterValuePrinter.cpp index cfa50ee908bf8..1754e7812469a 100644 --- a/clang/lib/Interpreter/InterpreterValuePrinter.cpp +++ b/clang/lib/Interpreter/InterpreterValuePrinter.cpp @@ -78,7 +78,7 @@ static std::string QualTypeToString(ASTContext &Ctx, QualType QT) { !NonRefTy->isMemberPointerType()) return Canon.getAsString(Ctx.getPrintingPolicy()); - if (const auto *TDTy = dyn_cast(NonRefTy)) { + if (const auto *TDTy = dyn_cast(Canon)) { // FIXME: TemplateSpecializationType & SubstTemplateTypeParmType checks // are predominately to get STL containers to print nicer and might be // better handled in GetFullyQualifiedName. @@ -87,13 +87,12 @@ static std::string QualTypeToString(ASTContext &Ctx, QualType QT) { // std::vector::value_type is a SubstTemplateTypeParmType // QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType(); - if (llvm::isa(SSDesugar)) + if (llvm::isa(SSDesugar) || + llvm::isa(SSDesugar)) return GetFullTypeName(Ctx, Canon); - else if (llvm::isa(SSDesugar)) - return GetFullTypeName(Ctx, NonRefTy); - return DeclTypeToString(NonRefTy, TDTy->getDecl()); + return DeclTypeToString(Canon, TDTy->getDecl()); } - return GetFullTypeName(Ctx, NonRefTy); + return GetFullTypeName(Ctx, Canon); } static std::string EnumToString(const Value &V) { diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp index ef0ee8e233c28..204939eb3b523 100644 --- a/clang/test/Interpreter/pretty-print.cpp +++ b/clang/test/Interpreter/pretty-print.cpp @@ -73,6 +73,22 @@ auto y = Outer::Bar(); y const auto z = Outer::Foo(); z // CHECK-NEXT: (const Outer::Foo &) @0x{{[0-9a-f]+}} +// Check printing of DecltypeTypes (this used to assert) +namespace N { struct D {}; } +decltype(N::D()) decl1; decl1 +// CHECK-NEXT: (N::D &) @0x{{[0-9a-f]+}} + +// double-nested DecltypeType +decltype(decl1) decl2; decl2 +// CHECK-NEXT: (N::D &) @0x{{[0-9a-f]+}} + +const decltype(N::D()) decl3; decl3 +// CHECK-NEXT: (const N::D &) @0x{{[0-9a-f]+}} + +// Check printing of UnaryTransformType (this used to assert) +__remove_extent(N::D)* decl4; decl4 +// CHECK-NEXT: (N::D *) + // int i = 12; // int &iref = i; // iref