[clang] [clang-repl] Use canonical types in QualTypeToString (PR #190528)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 5 07:39:37 PDT 2026
https://github.com/devajithvs created https://github.com/llvm/llvm-project/pull/190528
Use the canonical type when generating type strings to ensure sugared (e.g. `AutoType`, `DecltypeType`) are resolved before calling getFullyQualifiedType.
This will revert a few commits that were added to fix these assertions.
>From 6d6734865cf46488009eff5d574d4771d3327683 Mon Sep 17 00:00:00 2001
From: Devajith <devajithvs at gmail.com>
Date: Sun, 5 Apr 2026 16:10:21 +0200
Subject: [PATCH 1/4] Revert "[clang][AST] Fix assertion in
getFullyQualifiedType for DecltypeType (#187725)"
This reverts commit 720abd76e71f722f546c58af11049c773a583058.
---
clang/lib/AST/QualTypeNames.cpp | 11 -----------
clang/test/Interpreter/pretty-print.cpp | 12 ------------
2 files changed, 23 deletions(-)
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 066c5de35bba9..7cdee52acce3f 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -450,17 +450,6 @@ QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
QT = Ctx.getQualifiedType(QT, Quals);
}
- // Try to get to the underlying type for DecltypeType
- while (const auto *DT = dyn_cast<DecltypeType>(QT.getTypePtr())) {
- // Get the qualifiers.
- Qualifiers Quals = QT.getQualifiers();
- QualType Underlying = DT->getUnderlyingType();
- if (Underlying.isNull() || Underlying->isDependentType())
- break;
- // Add back the qualifiers.
- QT = Ctx.getQualifiedType(Underlying, Quals);
- }
-
if (const auto *TST =
dyn_cast<const TemplateSpecializationType>(QT.getTypePtr())) {
diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp
index 852c4117197d8..ef0ee8e233c28 100644
--- a/clang/test/Interpreter/pretty-print.cpp
+++ b/clang/test/Interpreter/pretty-print.cpp
@@ -73,18 +73,6 @@ auto y = Outer::Bar<int>(); 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]+}}
-
// int i = 12;
// int &iref = i;
// iref
>From 076b05686d226bf6f47da08d8f5e312e4aa7951d Mon Sep 17 00:00:00 2001
From: Devajith <devajithvs at gmail.com>
Date: Sun, 5 Apr 2026 16:10:33 +0200
Subject: [PATCH 2/4] Revert "[clang][AST] Preserve qualifiers in
getFullyQualifiedType for AutoType (#187717)"
This reverts commit 1f9c54a15a87f72ca45fb47ec006d1eae63f4eb0.
---
clang/lib/AST/QualTypeNames.cpp | 10 ++--------
clang/test/Interpreter/pretty-print.cpp | 4 ----
2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 7cdee52acce3f..9e3885e100c6b 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -370,15 +370,9 @@ NestedNameSpecifier createNestedNameSpecifier(const ASTContext &Ctx,
QualType getFullyQualifiedType(QualType QT, const ASTContext &Ctx,
bool WithGlobalNsPrefix) {
// Use the underlying deduced type for AutoType
- if (const auto *AT = dyn_cast<AutoType>(QT.getTypePtr())) {
- if (AT->isDeduced()) {
- // Get the qualifiers.
- Qualifiers Quals = QT.getQualifiers();
+ if (const auto *AT = dyn_cast<AutoType>(QT.getTypePtr()))
+ if (AT->isDeduced())
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.
diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp
index ef0ee8e233c28..f0548358d65db 100644
--- a/clang/test/Interpreter/pretty-print.cpp
+++ b/clang/test/Interpreter/pretty-print.cpp
@@ -69,10 +69,6 @@ namespace Outer { template<class T> struct Bar {}; }
auto y = Outer::Bar<int>(); y
// CHECK-NEXT: (Outer::Bar<int> &) @0x{{[0-9a-f]+}}
-// Check that const is preserved
-const auto z = Outer::Foo(); z
-// CHECK-NEXT: (const Outer::Foo &) @0x{{[0-9a-f]+}}
-
// int i = 12;
// int &iref = i;
// iref
>From 88f59b35672b66650b8e1db7fe5967322efe819a Mon Sep 17 00:00:00 2001
From: Devajith <devajithvs at gmail.com>
Date: Sun, 5 Apr 2026 16:10:41 +0200
Subject: [PATCH 3/4] Revert "[clang][AST] Fix assertion in
`getFullyQualifiedType` for AutoType (#186105)"
This reverts commit 86c4e96856a645a4015adf0e4d1a779e5662c6ca.
---
clang/lib/AST/QualTypeNames.cpp | 5 -----
clang/test/Interpreter/pretty-print.cpp | 9 ---------
2 files changed, 14 deletions(-)
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 9e3885e100c6b..191841649a86f 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -369,11 +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<AutoType>(QT.getTypePtr()))
- if (AT->isDeduced())
- QT = AT->getDeducedType();
-
// In case of myType* we need to strip the pointer first, fully
// qualify and attach the pointer once again.
if (isa<PointerType>(QT.getTypePtr())) {
diff --git a/clang/test/Interpreter/pretty-print.cpp b/clang/test/Interpreter/pretty-print.cpp
index f0548358d65db..bad71cdd48f0b 100644
--- a/clang/test/Interpreter/pretty-print.cpp
+++ b/clang/test/Interpreter/pretty-print.cpp
@@ -60,15 +60,6 @@ struct S5 { int foo() { return 42; }};
&S5::foo
// CHECK-NEXT: (int (S5::*)()) Function @0x{{[0-9a-f]+}}
-// Namespaced types deduced via auto
-namespace Outer { struct Foo {}; }
-auto x = Outer::Foo(); x
-// CHECK-NEXT: (Outer::Foo &) @0x{{[0-9a-f]+}}
-
-namespace Outer { template<class T> struct Bar {}; }
-auto y = Outer::Bar<int>(); y
-// CHECK-NEXT: (Outer::Bar<int> &) @0x{{[0-9a-f]+}}
-
// int i = 12;
// int &iref = i;
// iref
>From b13dc0c993f3168c41d378c6fc287a2e73f328c8 Mon Sep 17 00:00:00 2001
From: Devajith <devajithvs at gmail.com>
Date: Sun, 5 Apr 2026 15:53:06 +0200
Subject: [PATCH 4/4] [clang-repl] Use canonical types in QualTypeToString
Use the canonical type when generating type strings to ensure sugared
types (e.g. `AutoType`, `DecltypeType`) are resolved before calling
getFullyQualifiedType.
---
.../Interpreter/InterpreterValuePrinter.cpp | 11 ++++---
clang/test/Interpreter/pretty-print.cpp | 29 +++++++++++++++++++
2 files changed, 34 insertions(+), 6 deletions(-)
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<TypedefType>(NonRefTy)) {
+ if (const auto *TDTy = dyn_cast<TypedefType>(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<Type>::value_type is a SubstTemplateTypeParmType
//
QualType SSDesugar = TDTy->getLocallyUnqualifiedSingleStepDesugaredType();
- if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar))
+ if (llvm::isa<SubstTemplateTypeParmType>(SSDesugar) ||
+ llvm::isa<TemplateSpecializationType>(SSDesugar))
return GetFullTypeName(Ctx, Canon);
- else if (llvm::isa<TemplateSpecializationType>(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 bad71cdd48f0b..12133ad877ade 100644
--- a/clang/test/Interpreter/pretty-print.cpp
+++ b/clang/test/Interpreter/pretty-print.cpp
@@ -60,6 +60,35 @@ struct S5 { int foo() { return 42; }};
&S5::foo
// CHECK-NEXT: (int (S5::*)()) Function @0x{{[0-9a-f]+}}
+// Namespaced types deduced via auto
+namespace Outer { struct Foo {}; }
+auto x = Outer::Foo(); x
+// CHECK-NEXT: (Outer::Foo &) @0x{{[0-9a-f]+}}
+
+namespace Outer { template<class T> struct Bar {}; }
+auto y = Outer::Bar<int>(); y
+// CHECK-NEXT: (Outer::Bar<int> &) @0x{{[0-9a-f]+}}
+
+// Check that const is preserved
+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 *) @0x{{[0-9a-f]+}}
+
// int i = 12;
// int &iref = i;
// iref
More information about the cfe-commits
mailing list