diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 157afd9e86291..b65106b9106d4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -610,6 +610,9 @@ Bug Fixes in This Version inside a lambda. (`#61460 `_) - Fix crash during instantiation of some class template specializations within class templates. Fixes (`#70375 `_) +- Fix crash during code generation of C++ coroutine initial suspend when the return + type of await_resume is not trivially destructible. + Fixes (`#63803 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index 7e449d5af3423..aaf122c0f83bc 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 0000000000000..c4b8da327f5c1 --- /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; + + 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 {{.*}}