[clang] [Clang][Coroutines] Properly emit EH code for initial suspend `await_resume` (PR #73073)
Yuxuan Chen via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 21 19:52:52 PST 2023
https://github.com/yuxuanchen1997 updated https://github.com/llvm/llvm-project/pull/73073
>From e7d1ae077d7d301094b663166cc0c14c706d2110 Mon Sep 17 00:00:00 2001
From: Yuxuan Chen <ych at meta.com>
Date: Tue, 21 Nov 2023 19:06:31 -0800
Subject: [PATCH 1/3] [Clang][coro] Fix crash on emitting init suspend if the
return type of await_resume() is not trivially destructible
---
clang/lib/CodeGen/CGCoroutine.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index 7e449d5af3423cf..aaf122c0f83bc47 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -245,6 +245,15 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
FPOptionsOverride(), Loc, Loc);
TryStmt = CXXTryStmt::Create(CGF.getContext(), Loc, TryBody, Catch);
CGF.EnterCXXTryStmt(*TryStmt);
+ CGF.EmitStmt(TryBody);
+ // We don't use EmitCXXTryStmt here. We need to store to ResumeEHVar that
+ // doesn't exist in the body.
+ Builder.CreateFlagStore(false, Coro.ResumeEHVar);
+ CGF.ExitCXXTryStmt(*TryStmt);
+ LValueOrRValue Res;
+ // We are not supposed to obtain the value from init suspend await_resume().
+ Res.RV = RValue::getIgnored();
+ return Res;
}
LValueOrRValue Res;
@@ -253,11 +262,6 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
else
Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);
- if (TryStmt) {
- Builder.CreateFlagStore(false, Coro.ResumeEHVar);
- CGF.ExitCXXTryStmt(*TryStmt);
- }
-
return Res;
}
>From e11b48867b2f02a095d043d57cf7830702f47ed6 Mon Sep 17 00:00:00 2001
From: Yuxuan Chen <ych at meta.com>
Date: Tue, 21 Nov 2023 19:35:10 -0800
Subject: [PATCH 2/3] add test case for the previously crashing case
---
.../coro-init-await-nontrivial-return.cpp | 46 +++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp
diff --git a/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp b/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp
new file mode 100644
index 000000000000000..c4b8da327f5c140
--- /dev/null
+++ b/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++20 -triple=x86_64-- -emit-llvm -fcxx-exceptions \
+// RUN: -disable-llvm-passes %s -o - | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+struct NontrivialType {
+ ~NontrivialType() {}
+};
+
+struct Task {
+ struct promise_type;
+ using handle_type = std::coroutine_handle<promise_type>;
+
+ struct initial_suspend_awaiter {
+ bool await_ready() {
+ return false;
+ }
+
+ void await_suspend(handle_type h) {}
+
+ NontrivialType await_resume() { return {}; }
+ };
+
+ struct promise_type {
+ void return_void() {}
+ void unhandled_exception() {}
+ initial_suspend_awaiter initial_suspend() { return {}; }
+ std::suspend_never final_suspend() noexcept { return {}; }
+ Task get_return_object() {
+ return Task{handle_type::from_promise(*this)};
+ }
+ };
+
+ handle_type handler;
+};
+
+Task coro_create() {
+ co_return;
+}
+
+// CHECK-LABEL: define{{.*}} ptr @_Z11coro_createv(
+// CHECK: init.ready:
+// CHECK-NEXT: store i1 true, ptr {{.*}}
+// CHECK-NEXT: call void @_ZN4Task23initial_suspend_awaiter12await_resumeEv(
+// CHECK-NEXT: call void @_ZN14NontrivialTypeD1Ev(
+// CHECK-NEXT: store i1 false, ptr {{.*}}
>From 231760360962cf980f06f2b83d1467fd2c9f1078 Mon Sep 17 00:00:00 2001
From: Yuxuan Chen <ych at meta.com>
Date: Tue, 21 Nov 2023 19:52:34 -0800
Subject: [PATCH 3/3] Add release note entry
---
clang/docs/ReleaseNotes.rst | 4 ++++
clang/lib/CodeGen/CGCoroutine.cpp | 2 ++
2 files changed, 6 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 157afd9e8629152..9f9f83c673b7ba7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -592,6 +592,7 @@ Bug Fixes in This Version
- Clang now properly diagnoses use of stand-alone OpenMP directives after a
label (including ``case`` or ``default`` labels).
+
Before:
.. code-block:: c++
@@ -610,6 +611,9 @@ Bug Fixes in This Version
inside a lambda. (`#61460 <https://github.com/llvm/llvm-project/issues/61460>`_)
- Fix crash during instantiation of some class template specializations within class
templates. Fixes (`#70375 <https://github.com/llvm/llvm-project/issues/70375>`_)
+- Fix crash during code generation of C++ coroutine initial suspend when the
+ return type of await_resume is not trivially destructible.
+ Fixes (`#63803 <https://github.com/llvm/llvm-project/issues/63803>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index aaf122c0f83bc47..ec30c974253d95f 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -130,6 +130,8 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData &Coro, AwaitKind Kind) {
}
static bool memberCallExpressionCanThrow(const Expr *E) {
+ E->dump();
+ std::terminate();
if (const auto *CE = dyn_cast<CXXMemberCallExpr>(E))
if (const auto *Proto =
CE->getMethodDecl()->getType()->getAs<FunctionProtoType>())
More information about the cfe-commits
mailing list