Author: Jiahao Guo Date: 2026-05-23T18:38:12+08:00 New Revision: 38e0a91f244fb0789c3d90d444bd07972f1051cb
URL: https://github.com/llvm/llvm-project/commit/38e0a91f244fb0789c3d90d444bd07972f1051cb DIFF: https://github.com/llvm/llvm-project/commit/38e0a91f244fb0789c3d90d444bd07972f1051cb.diff LOG: [CIR] Attach noreturn attribute to __cxa_bad_cast (#198727) ## Summary - Mark `__cxa_bad_cast` as `noreturn` in CIR, mirroring the existing `__cxa_bad_typeid` handling. The attribute is now set on every `CallOp` that targets it, covering both the CodeGen direct path (`emitCallToBadCast`) and the target-lowering path (`buildBadCastCall`). - Drop the now-fulfilled `MissingFeatures::opFuncNoReturn` entry and the corresponding TODO/assert at the lone caller in `LowerItaniumCXXABI.cpp`. - Update FileCheck expectations in `dynamic-cast.cpp`, `dynamic-cast-exact.cpp`, and `abi-lower-after-unreachable.cpp` to require the `{noreturn}` attribute on the lowered `cir.call @__cxa_bad_cast()`. Added: Modified: clang/include/clang/CIR/MissingFeatures.h clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp clang/test/CIR/CodeGen/dynamic-cast-exact.cpp clang/test/CIR/CodeGen/dynamic-cast.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 8af09c5007495..32331452fe294 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -83,7 +83,6 @@ struct MissingFeatures { static bool opFuncReadOnly() { return false; } static bool opFuncUnwindTablesAttr() { return false; } static bool opFuncWillReturn() { return false; } - static bool opFuncNoReturn() { return false; } static bool handleCUDALaunchBoundsAttr() { return false; } static bool setLLVMFunctionFEnvAttributes() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 560a4de9b9b01..552d73966e97b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -2083,7 +2083,11 @@ static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) { // TODO(cir): set the calling convention to the runtime function. assert(!cir::MissingFeatures::opFuncCallingConv()); - cgf.emitRuntimeCall(loc, getBadCastFn(cgf)); + mlir::NamedAttrList attrs; + attrs.set(cir::CIRDialect::getNoReturnAttrName(), + mlir::UnitAttr::get(&cgf.cgm.getMLIRContext())); + + cgf.emitRuntimeCall(loc, getBadCastFn(cgf), {}, attrs); cir::UnreachableOp::create(cgf.getBuilder(), loc); cgf.getBuilder().clearInsertionPoint(); } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp index 3ed5ba4750a0c..5c54103c60247 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp @@ -684,10 +684,11 @@ mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast( static void buildBadCastCall(mlir::OpBuilder &builder, mlir::Location loc, mlir::FlatSymbolRefAttr badCastFuncRef) { - cir::CallOp::create(builder, loc, badCastFuncRef, /*resType=*/cir::VoidType(), - /*operands=*/mlir::ValueRange{}); - // TODO(cir): Set the 'noreturn' attribute on the function. - assert(!cir::MissingFeatures::opFuncNoReturn()); + auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef, + /*resType=*/cir::VoidType(), + /*operands=*/mlir::ValueRange{}); + callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(), + builder.getUnitAttr()); cir::UnreachableOp::create(builder, loc); builder.clearInsertionPoint(); diff --git a/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp b/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp index 180bf365940ef..92f8be1ca97ff 100644 --- a/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp +++ b/clang/test/CIR/CodeGen/abi-lower-after-unreachable.cpp @@ -21,7 +21,7 @@ void untransformed_after_unreachable(Base2 &ref, PMFTy pmf) { // CIR: %[[PMF:.*]] = cir.alloca !{{.*}} ["pmf", init] // CIR: %[[DERIVED:.*]] = cir.alloca !rec_Derived // CIR: cir.load %{{.*}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2> -// CIR-NEXT: cir.call @__cxa_bad_cast() : () -> () +// CIR-NEXT: cir.call @__cxa_bad_cast() {noreturn} : () -> () // CIR-NEXT: cir.unreachable // CIR-BEFORE: %[[PMF_LOAD:.*]] = cir.load{{.*}} %[[PMF]] // CIR-BEFORE: cir.get_method %[[PMF_LOAD]], %[[DERIVED]] diff --git a/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp b/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp index 39f0dd45b9de6..2ec65814fb584 100644 --- a/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp +++ b/clang/test/CIR/CodeGen/dynamic-cast-exact.cpp @@ -85,7 +85,7 @@ Derived &ref_cast(Base1 &ref) { // CIR-NEXT: %[[SUCCESS:.*]] = cir.cmp eq %[[SRC_VPTR]], %[[EXPECTED_VPTR]] : !cir.vptr // CIR-NEXT: %[[FAILED:.*]] = cir.not %[[SUCCESS]] : !cir.bool // CIR-NEXT: cir.if %[[FAILED]] { -// CIR-NEXT: cir.call @__cxa_bad_cast() : () -> () +// CIR-NEXT: cir.call @__cxa_bad_cast() {noreturn} : () -> () // CIR-NEXT: cir.unreachable // CIR-NEXT: } // CIR-NEXT: %{{.+}} = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base1> -> !cir.ptr<!rec_Derived> @@ -195,7 +195,7 @@ Derived &ref_cast_always_fail(Base2 &ref) { // CIR: cir.func {{.*}} @_Z20ref_cast_always_failR5Base2 // CIR: %{{.+}} = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base2>>, !cir.ptr<!rec_Base2> -// CIR-NEXT: cir.call @__cxa_bad_cast() : () -> () +// CIR-NEXT: cir.call @__cxa_bad_cast() {noreturn} : () -> () // CIR-NEXT: cir.unreachable // LLVM: define {{.*}} ptr @_Z20ref_cast_always_failR5Base2 diff --git a/clang/test/CIR/CodeGen/dynamic-cast.cpp b/clang/test/CIR/CodeGen/dynamic-cast.cpp index 11bd7b0f73aae..a6d529f7c4dc7 100644 --- a/clang/test/CIR/CodeGen/dynamic-cast.cpp +++ b/clang/test/CIR/CodeGen/dynamic-cast.cpp @@ -82,7 +82,7 @@ Derived &ref_cast(Base &b) { // CIR-AFTER-NEXT: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void> // CIR-AFTER-NEXT: %[[CASTED_PTR_IS_NULL:.*]] = cir.cmp eq %[[CASTED_PTR]], %[[NULL_PTR]] : !cir.ptr<!void> // CIR-AFTER-NEXT: cir.if %[[CASTED_PTR_IS_NULL]] { -// CIR-AFTER-NEXT: cir.call @__cxa_bad_cast() : () -> () +// CIR-AFTER-NEXT: cir.call @__cxa_bad_cast() {noreturn} : () -> () // CIR-AFTER-NEXT: cir.unreachable // CIR-AFTER-NEXT: } // CIR-AFTER-NEXT: %{{.+}} = cir.cast bitcast %[[CASTED_PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_Derived> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
