[clang] [CIR] Fix dynamic cast of const types (PR #192751)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 16:01:03 PDT 2026
https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/192751
When a dynamic cast was performed using const-qualified values, we were generating a reference to const-qualified typeinfo but never emitting such const-qualified typeinfo, leading to an undefined reference at link time.
This change fixes that by stripping the type qualifiers before processing the cast. This matches the behavior of classic codegen in ItaniumCXXABI::emitDynamicCastCall.
>From 5cc27dad926b0e5a3af9ec7b2ef8abe11e924900 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Fri, 17 Apr 2026 15:19:48 -0700
Subject: [PATCH] [CIR] Fix dynamic cast of const types
When a dynamic cast was performed using const-qualified values, we
were generating a reference to const-qualified typeinfo but never
emitting such const-qualified typeinfo, leading to an undefined
reference at link time.
This change fixes that by stripping the type qualifiers before processing
the cast. This matches the behavior of classic codegen in
ItaniumCXXABI::emitDynamicCastCall.
---
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 4 +-
clang/test/CIR/CodeGen/dynamic-cast.cpp | 38 +++++++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index c398e6183d91c..458dc5152298b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -2324,9 +2324,9 @@ static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf,
QualType srcRecordTy,
QualType destRecordTy) {
auto srcRtti = mlir::cast<cir::GlobalViewAttr>(
- cgf.cgm.getAddrOfRTTIDescriptor(loc, srcRecordTy));
+ cgf.cgm.getAddrOfRTTIDescriptor(loc, srcRecordTy.getUnqualifiedType()));
auto destRtti = mlir::cast<cir::GlobalViewAttr>(
- cgf.cgm.getAddrOfRTTIDescriptor(loc, destRecordTy));
+ cgf.cgm.getAddrOfRTTIDescriptor(loc, destRecordTy.getUnqualifiedType()));
cir::FuncOp runtimeFuncOp = getItaniumDynamicCastFn(cgf);
cir::FuncOp badCastFuncOp = getBadCastFn(cgf);
diff --git a/clang/test/CIR/CodeGen/dynamic-cast.cpp b/clang/test/CIR/CodeGen/dynamic-cast.cpp
index 517ec0ae8380a..11bd7b0f73aae 100644
--- a/clang/test/CIR/CodeGen/dynamic-cast.cpp
+++ b/clang/test/CIR/CodeGen/dynamic-cast.cpp
@@ -157,3 +157,41 @@ void *ptr_cast_to_complete(Base *ptr) {
// OGCG: br label %[[DONE]]
// OGCG: [[DONE]]:
// OGCG: %[[RET:.*]] = phi ptr [ %[[RESULT]], %[[NOT_NULL]] ], [ null, %[[NULL]] ]
+
+// Dynamic cast to a const pointer/reference must reference the typeinfo of
+// the unqualified class type (e.g. `_ZTI7Derived`), not a const-qualified
+// typeinfo symbol (`_ZTIK7Derived`), which is never emitted. Regression test
+// for a bug where CIR emitted `_ZTIK...` references that caused link-time
+// undefined-reference errors.
+
+const Derived *const_ptr_cast(const Base *b) {
+ return dynamic_cast<const Derived *>(b);
+}
+
+// CIR-BEFORE: cir.func {{.*}} @_Z14const_ptr_castPK4Base
+// CIR-BEFORE: %{{.+}} = cir.dyn_cast ptr %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived
+// CIR-BEFORE: }
+
+// LLVM: define {{.*}} @_Z14const_ptr_castPK4Base
+// LLVM: call ptr @__dynamic_cast(ptr %{{.*}}, ptr @_ZTI4Base, ptr @_ZTI7Derived, i64 0)
+// LLVM-NOT: _ZTIK4Base
+// LLVM-NOT: _ZTIK7Derived
+
+// OGCG: define {{.*}} @_Z14const_ptr_castPK4Base
+// OGCG: call ptr @__dynamic_cast(ptr %{{.*}}, ptr @_ZTI4Base, ptr @_ZTI7Derived, i64 0)
+
+const Derived &const_ref_cast(const Base &b) {
+ return dynamic_cast<const Derived &>(b);
+}
+
+// CIR-BEFORE: cir.func {{.*}} @_Z14const_ref_castRK4Base
+// CIR-BEFORE: %{{.+}} = cir.dyn_cast ref %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived
+// CIR-BEFORE: }
+
+// LLVM: define {{.*}} ptr @_Z14const_ref_castRK4Base
+// LLVM: call ptr @__dynamic_cast(ptr %{{.*}}, ptr @_ZTI4Base, ptr @_ZTI7Derived, i64 0)
+// LLVM-NOT: _ZTIK4Base
+// LLVM-NOT: _ZTIK7Derived
+
+// OGCG: define {{.*}} ptr @_Z14const_ref_castRK4Base
+// OGCG: call ptr @__dynamic_cast(ptr %{{.*}}, ptr @_ZTI4Base, ptr @_ZTI7Derived, i64 0)
More information about the cfe-commits
mailing list