https://github.com/Andres-Salamanca updated 
https://github.com/llvm/llvm-project/pull/220466

>From 9d20cb13fec7b761e98c8aa28ee07e871348ae2a Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Tue, 1 Sep 2026 22:01:28 -0500
Subject: [PATCH 1/3] [CIR] Add support for coroutine allocation failure

---
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp     | 25 +++++-
 .../test/CIR/CodeGenCoroutines/coro-alloc.cpp | 78 +++++++++++++++++++
 2 files changed, 99 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp

diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 7bcaa43bae765..13e06c2b580ab 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/MissingFeatures.h"
 
@@ -370,16 +371,32 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt 
&s) {
             loc, emitScalarExpr(s.getAllocate()), storeAddr);
         cir::YieldOp::create(builder, loc);
       });
+
+  // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
+  if (Stmt *retOnAllocFailure = s.getReturnStmtOnAllocFailure()) {
+
+    mlir::LogicalResult res = mlir::success();
+    mlir::Value isPtrNull = builder.createPtrIsNull(storeAddr);
+
+    assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
+
+    cir::IfOp::create(
+        builder, openCurlyLoc, isPtrNull, /*withElseRegion=*/false,
+        [&](mlir::OpBuilder &b, mlir::Location loc) {
+          res = emitStmt(retOnAllocFailure, /*useCurrentScope=*/true);
+          cir::TrapOp::create(builder, openCurlyLoc);
+        });
+
+    if (res.failed())
+      return res;
+  }
+
   curCoro.data->coroBegin = cir::CoroBeginOp::create(
       cgm.getBuilder(), openCurlyLoc,
       mlir::ValueRange{
           curCoro.data->coroId.getResult(),
           cir::LoadOp::create(builder, openCurlyLoc, allocaTy, storeAddr)});
 
-  // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
-  if (s.getReturnStmtOnAllocFailure())
-    cgm.errorNYI("handle coroutine return alloc failure");
-
   {
     assert(!cir::MissingFeatures::generateDebugInfo());
     ParamReferenceReplacerRAII paramReplacer(localDeclMap);
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
new file mode 100644
index 0000000000000..02684a1dbfebf
--- /dev/null
+++ b/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir 
-fno-clangir-call-conv-lowering -Wno-coroutine-missing-unhandled-exception 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm  
-disable-llvm-passes -Wno-coroutine-missing-unhandled-exception %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=OGCG
+#include "Inputs/coroutine.h"
+namespace std {
+
+struct nothrow_t {};
+constexpr nothrow_t nothrow = {};
+
+} // end namespace std
+
+// Required when get_return_object_on_allocation_failure() is defined by
+// the promise. The nothrow overload prevents allocation failure from
+// throwing std::bad_alloc.
+using SizeT = decltype(sizeof(int));
+void* operator new(SizeT __sz, const std::nothrow_t&) noexcept;
+void  operator delete(void* __p, const std::nothrow_t&) noexcept;
+
+struct promise_on_alloc_failure_tag {};
+
+template <>
+struct std::coroutine_traits<int, promise_on_alloc_failure_tag> {
+  struct promise_type {
+    int get_return_object() { return 0; }
+    suspend_always initial_suspend() { return {}; }
+    suspend_always final_suspend() noexcept { return {}; }
+    void return_void() {}
+    static int get_return_object_on_allocation_failure() { return -1; }
+  };
+};
+
+int f4(promise_on_alloc_failure_tag) {
+
+  co_return;
+}
+
+// CIR-LABEL: @_Z2f428promise_on_alloc_failure_tag(
+// CIR: %[[RetVal:.*]] = cir.alloca "__retval"
+// CIR: %[[SavedFrameAddr:.*]] = cir.alloca "__coro_frame_addr"
+// CIR: %[[CORO_ID:.*]] = cir.coro.intrinsic.id(
+// CIR: %[[ShouldAlloc:.*]] = cir.coro.intrinsic.alloc(%[[CORO_ID]])
+// CIR: cir.if %[[ShouldAlloc]] {
+// CIR:   %[[CORO_SIZE:.*]] = cir.coro.intrinsic.size()
+// CIR:   %[[STD_NOTHROW:.*]] = cir.get_global @_ZStL7nothrow
+// CIR:   %[[ALLOC_ADDR:.*]] = cir.call @_ZnwmRKSt9nothrow_t(%[[CORO_SIZE]], 
%[[STD_NOTHROW]])
+// CIR:   cir.store %[[ALLOC_ADDR]], %[[SavedFrameAddr]]
+// CIR: }
+// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null>
+// CIR: %[[IS_NULL_PTR:.*]] = cir.cmp eq %[[SavedFrameAddr]], %[[NULL_PTR:.*]]
+// CIR: cir.if %[[IS_NULL_PTR]] {
+// CIR:   %[[FailRet:.*]] = cir.call 
@_ZNSt16coroutine_traitsIiJ28promise_on_alloc_failure_tagEE12promise_type39get_return_object_on_allocation_failureEv
+// CIR:   cir.store %[[FailRet]], %[[RetVal]] : !s32i
+// CIR:   %[[RET:.*]] = cir.load %[[RetVal]] : !cir.ptr<!s32i>
+// CIR:   cir.return %[[RET]] : !s32i
+// CIR: ^[[UNREACHABLE:.*]]:
+// CIR:   cir.trap
+// CIR: }
+
+// OGCG-LABEL: @_Z2f428promise_on_alloc_failure_tag(
+// OGCG: %[[RetVal:.*]] = alloca i32
+// OGCG: %[[ID:.*]] = call token @llvm.coro.id(i32 16
+// OGCG: %[[SIZE:.*]] = call i64 @llvm.coro.size.i64()
+// OGCG: %[[MEM:.*]] = call noalias noundef ptr @_ZnwmRKSt9nothrow_t(i64 
noundef %[[SIZE]], ptr noundef nonnull align 1 dereferenceable(1) 
@_ZStL7nothrow)
+// OGCG: %[[OK:.*]] = icmp ne ptr %[[MEM]], null
+// OGCG: br i1 %[[OK]], label %[[OKBB:.*]], label %[[ERRBB:.*]]
+
+// OGCG: [[ERRBB]]:
+// OGCG:   %[[FailRet:.*]] = call noundef i32 
@_ZNSt16coroutine_traitsIiJ28promise_on_alloc_failure_tagEE12promise_type39get_return_object_on_allocation_failureEv()
+// OGCG:   store i32 %[[FailRet]], ptr %[[RetVal]]
+// OGCG:   br label %[[RetBB:.*]]
+
+// OGCG: [[OKBB]]:
+// OGCG:   %[[OkRet:.*]] = call noundef i32 
@_ZNSt16coroutine_traitsIiJ28promise_on_alloc_failure_tagEE12promise_type17get_return_objectEv({{.*}}
+
+// OGCG: [[RetBB]]:
+// OGCG:   %[[LoadRet:.*]] = load i32, ptr %[[RetVal]], align 4
+// OGCG:   ret i32 %[[LoadRet]]

>From 3988e6aff6b84f60cc0befd12260194de445a0a5 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Tue, 1 Sep 2026 23:39:13 -0500
Subject: [PATCH 2/3] Address review comments

---
 clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp     | 36 +++++++++----------
 .../test/CIR/CodeGenCoroutines/coro-alloc.cpp | 26 +++++++-------
 2 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
index 13e06c2b580ab..4fbede0f88ad4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp
@@ -363,33 +363,29 @@ CIRGenFunction::emitCoroutineBody(const CoroutineBodyStmt 
&s) {
 
   mlir::Value storeAddr = coroFrame.getPointer();
   builder.CIRBaseBuilderTy::createStore(openCurlyLoc, nullPtrCst, storeAddr);
+  mlir::LogicalResult res = mlir::success();
   cir::IfOp::create(
       builder, openCurlyLoc, coroAlloc.getResult(),
       /*withElseRegion=*/false,
       /*thenBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
-        builder.CIRBaseBuilderTy::createStore(
-            loc, emitScalarExpr(s.getAllocate()), storeAddr);
+        mlir::Value allocatedPtr = emitScalarExpr(s.getAllocate());
+        builder.CIRBaseBuilderTy::createStore(loc, allocatedPtr, storeAddr);
+        // Handle allocation failure if 'ReturnStmtOnAllocFailure' was 
provided.
+        if (Stmt *retOnAllocFailure = s.getReturnStmtOnAllocFailure()) {
+          mlir::Value isPtrNull = builder.createPtrIsNull(allocatedPtr);
+          
assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
+          cir::IfOp::create(builder, loc, isPtrNull, /*withElseRegion=*/false,
+                            [&](mlir::OpBuilder &b, mlir::Location loc) {
+                              res = emitStmt(retOnAllocFailure,
+                                             /*useCurrentScope=*/true);
+                              cir::UnreachableOp::create(builder, loc);
+                            });
+        }
         cir::YieldOp::create(builder, loc);
       });
 
-  // Handle allocation failure if 'ReturnStmtOnAllocFailure' was provided.
-  if (Stmt *retOnAllocFailure = s.getReturnStmtOnAllocFailure()) {
-
-    mlir::LogicalResult res = mlir::success();
-    mlir::Value isPtrNull = builder.createPtrIsNull(storeAddr);
-
-    assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
-
-    cir::IfOp::create(
-        builder, openCurlyLoc, isPtrNull, /*withElseRegion=*/false,
-        [&](mlir::OpBuilder &b, mlir::Location loc) {
-          res = emitStmt(retOnAllocFailure, /*useCurrentScope=*/true);
-          cir::TrapOp::create(builder, openCurlyLoc);
-        });
-
-    if (res.failed())
-      return res;
-  }
+  if (res.failed())
+    return res;
 
   curCoro.data->coroBegin = cir::CoroBeginOp::create(
       cgm.getBuilder(), openCurlyLoc,
diff --git a/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
index 02684a1dbfebf..1c7bc9b4797c9 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
@@ -37,24 +37,26 @@ int f4(promise_on_alloc_failure_tag) {
 
 // CIR-LABEL: @_Z2f428promise_on_alloc_failure_tag(
 // CIR: %[[RetVal:.*]] = cir.alloca "__retval"
-// CIR: %[[SavedFrameAddr:.*]] = cir.alloca "__coro_frame_addr"
+// CIR: %[[FrameAddr:.*]] = cir.alloca "__coro_frame_addr"
+// CIR: %[[NULL_INIT:.*]] = cir.const #cir.ptr<null>
 // CIR: %[[CORO_ID:.*]] = cir.coro.intrinsic.id(
 // CIR: %[[ShouldAlloc:.*]] = cir.coro.intrinsic.alloc(%[[CORO_ID]])
+// CIR: cir.store %[[NULL_INIT]], %[[FrameAddr]]
 // CIR: cir.if %[[ShouldAlloc]] {
 // CIR:   %[[CORO_SIZE:.*]] = cir.coro.intrinsic.size()
 // CIR:   %[[STD_NOTHROW:.*]] = cir.get_global @_ZStL7nothrow
 // CIR:   %[[ALLOC_ADDR:.*]] = cir.call @_ZnwmRKSt9nothrow_t(%[[CORO_SIZE]], 
%[[STD_NOTHROW]])
-// CIR:   cir.store %[[ALLOC_ADDR]], %[[SavedFrameAddr]]
-// CIR: }
-// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null>
-// CIR: %[[IS_NULL_PTR:.*]] = cir.cmp eq %[[SavedFrameAddr]], %[[NULL_PTR:.*]]
-// CIR: cir.if %[[IS_NULL_PTR]] {
-// CIR:   %[[FailRet:.*]] = cir.call 
@_ZNSt16coroutine_traitsIiJ28promise_on_alloc_failure_tagEE12promise_type39get_return_object_on_allocation_failureEv
-// CIR:   cir.store %[[FailRet]], %[[RetVal]] : !s32i
-// CIR:   %[[RET:.*]] = cir.load %[[RetVal]] : !cir.ptr<!s32i>
-// CIR:   cir.return %[[RET]] : !s32i
-// CIR: ^[[UNREACHABLE:.*]]:
-// CIR:   cir.trap
+// CIR:   cir.store %[[ALLOC_ADDR]], %[[FrameAddr]]
+// CIR:   %[[NULL_PTR:.*]] = cir.const #cir.ptr<null>
+// CIR:   %[[IS_NULL_PTR:.*]] = cir.cmp eq %[[ALLOC_ADDR]], %[[NULL_PTR]]
+// CIR:   cir.if %[[IS_NULL_PTR]] {
+// CIR:     %[[FailRet:.*]] = cir.call 
@_ZNSt16coroutine_traitsIiJ28promise_on_alloc_failure_tagEE12promise_type39get_return_object_on_allocation_failureEv
+// CIR:     cir.store %[[FailRet]], %[[RetVal]] : !s32i
+// CIR:     %[[RET:.*]] = cir.load %[[RetVal]] : !cir.ptr<!s32i>
+// CIR:     cir.return %[[RET]] : !s32i
+// CIR:   ^[[UNREACHABLE:.*]]:
+// CIR:     cir.unreachable
+// CIR:   }
 // CIR: }
 
 // OGCG-LABEL: @_Z2f428promise_on_alloc_failure_tag(

>From 2dc20e008926f54914bb84c8b3d681cca76620a2 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Wed, 2 Sep 2026 16:58:59 -0500
Subject: [PATCH 3/3] Address review comments

---
 clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp 
b/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
index 1c7bc9b4797c9..bb0d27af57271 100644
--- a/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
+++ b/clang/test/CIR/CodeGenCoroutines/coro-alloc.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir 
-fno-clangir-call-conv-lowering -Wno-coroutine-missing-unhandled-exception 
-emit-cir %s -o %t.cir
+// TODO(cir): drop -fno-clangir-call-conv-lowering once CallConvLowering
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir 
-Wno-coroutine-missing-unhandled-exception -emit-cir %s -o %t.cir
 // RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm  
-disable-llvm-passes -Wno-coroutine-missing-unhandled-exception %s -o %t-cir.ll
 // RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=OGCG

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

Reply via email to