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
