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

Reply via email to