Author: Yuxuan Chen Date: 2023-11-21T21:21:27-08:00 New Revision: 1fad78b123d20db675d339053e4265aceb07c4af
URL: https://github.com/llvm/llvm-project/commit/1fad78b123d20db675d339053e4265aceb07c4af DIFF: https://github.com/llvm/llvm-project/commit/1fad78b123d20db675d339053e4265aceb07c4af.diff LOG: [Clang][Coroutines] Properly emit EH code for initial suspend `await_resume` (#73073) This change aims to fix an ICE in issue https://github.com/llvm/llvm-project/issues/63803 The crash happens in `ExitCXXTryStmt` because `EmitAnyExpr()` adds additional cleanup to the `EHScopeStack`. This messes up the assumption in `ExitCXXTryStmt` that the top of the stack should be a `EHCatchScope`. However, since we never read a value returned from `await_resume()` of an init suspend, we can skip the part that builds this `RValue`. 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. Added: clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/CodeGen/CGCoroutine.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 157afd9e8629152..b65106b9106d4d7 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -610,6 +610,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 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..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 {{.*}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits