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)


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to