[clang] a743885 - [CIR] Add support for throwing destructed type (#188644)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 31 11:04:03 PDT 2026
Author: Andy Kaylor
Date: 2026-03-31T11:03:54-07:00
New Revision: a7438859265548c8443436d9c0c996338976ad85
URL: https://github.com/llvm/llvm-project/commit/a7438859265548c8443436d9c0c996338976ad85
DIFF: https://github.com/llvm/llvm-project/commit/a7438859265548c8443436d9c0c996338976ad85.diff
LOG: [CIR] Add support for throwing destructed type (#188644)
This adds handling for throwing an object of a type that has a
non-trivial destructor.
Added:
Modified:
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
clang/test/CIR/CodeGen/throws.cpp
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index f6116ca2a8d29..25deb9fbf5934 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -1860,18 +1860,22 @@ void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,
// null dtor). In CIR, we forward this info and allow for
// Lowering pass to skip passing the trivial function.
//
- if (const RecordType *recordTy = clangThrowType->getAs<RecordType>()) {
- auto *rec = cast<CXXRecordDecl>(recordTy->getDecl()->getDefinition());
- assert(!cir::MissingFeatures::isTrivialCtorOrDtor());
- if (!rec->hasTrivialDestructor()) {
- cgm.errorNYI("emitThrow: non-trivial destructor");
- return;
- }
+ const auto *cxxrd = clangThrowType->getAsCXXRecordDecl();
+ mlir::FlatSymbolRefAttr dtor{};
+ if (cxxrd && !cxxrd->hasTrivialDestructor()) {
+ // __cxa_throw is declared to take its destructor as void (*)(void *). We
+ // must match that if function pointers can be authenticated with a
+ // discriminator based on their type.
+ assert(!cir::MissingFeatures::pointerAuthentication());
+ CXXDestructorDecl *dtorD = cxxrd->getDestructor();
+ dtor = mlir::FlatSymbolRefAttr::get(
+ cgm.getAddrOfCXXStructor(GlobalDecl(dtorD, Dtor_Complete))
+ .getSymNameAttr());
}
// Now throw the exception.
mlir::Location loc = cgf.getLoc(e->getSourceRange());
- insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol());
+ insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol(), dtor);
}
CIRGenCXXABI *clang::CIRGen::CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) {
diff --git a/clang/test/CIR/CodeGen/throws.cpp b/clang/test/CIR/CodeGen/throws.cpp
index da08ecd26e4c8..0c11bffc2dd2e 100644
--- a/clang/test/CIR/CodeGen/throws.cpp
+++ b/clang/test/CIR/CodeGen/throws.cpp
@@ -271,3 +271,20 @@ void throw_pointer_type() {
// OGCG: %[[TMP_PTR:.*]] = load ptr, ptr %[[PTR_ADDR]], align 8
// OGCG: store ptr %[[TMP_PTR]], ptr %[[EXCEPTION_ADDR]], align 16
// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIPi, ptr null)
+// Throwing a class type with a non-trivial destructor exercises
+// CIRGenItaniumCXXABI::emitThrow (destructor symbol for __cxa_throw).
+
+struct ThrowNonTrivialDtor {
+ ~ThrowNonTrivialDtor() {}
+};
+void throw_class_with_nontrivial_dtor() { throw ThrowNonTrivialDtor(); }
+
+// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 1 -> !cir.ptr<!rec_ThrowNonTrivialDtor>
+// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!rec_ThrowNonTrivialDtor>, @_ZTI19ThrowNonTrivialDtor, @_ZN19ThrowNonTrivialDtorD1Ev
+// CIR: cir.unreachable
+
+// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 1)
+// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTI19ThrowNonTrivialDtor, ptr @_ZN19ThrowNonTrivialDtorD1Ev)
+
+// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 1)
+// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTI19ThrowNonTrivialDtor, ptr @_ZN19ThrowNonTrivialDtorD1Ev)
More information about the cfe-commits
mailing list