-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang][Coroutines] Properly emit EH code for initial suspend await_resume
#73073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…f await_resume() is not trivially destructible
9f98b9d
to
f2cba69
Compare
@llvm/pr-subscribers-coroutines @llvm/pr-subscribers-clang-codegen Author: Yuxuan Chen (yuxuanchen1997) ChangesThis change aims to fix an ICE in issue #63803 The crash happens in However, since we never read a value returned from Full diff: https://github.com/llvm/llvm-project/pull/73073.diff 2 Files Affected:
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;
}
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..78fc88a071d5c74
--- /dev/null
+++ b/clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp
@@ -0,0 +1,49 @@
+// 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) {}
+
+ // Nontrivial type caused crash!
+ NontrivialType await_resume() noexcept {
+ 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 {{.*}}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks.
f2cba69
to
e11b488
Compare
2317603
to
c88474f
Compare
This change aims to fix an ICE in issue #63803
The crash happens in
ExitCXXTryStmt
becauseEmitAnyExpr()
adds additional cleanup to theEHScopeStack
. This messes up the assumption inExitCXXTryStmt
that the top of the stack should be aEHCatchScope
.However, since we never read a value returned from
await_resume()
of an init suspend, we can skip the part that builds thisRValue
.The code here may not be in the best shape. There's another bug that
memberCallExpressionCanThrow
doesn't work on the current Expr due to type mismatch. I am preparing a separate PR to address it plus some refactoring might be beneficial.