Skip to content

Commit

Permalink
[Clang][Coroutines] Properly emit EH code for initial suspend `await_…
Browse files Browse the repository at this point in the history
…resume` (#73073)

This change aims to fix an ICE in issue
#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.
  • Loading branch information
yuxuanchen1997 committed Nov 22, 2023
1 parent 2c87571 commit 1fad78b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 5 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
14 changes: 9 additions & 5 deletions clang/lib/CodeGen/CGCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down
46 changes: 46 additions & 0 deletions clang/test/CodeGenCoroutines/coro-init-await-nontrivial-return.cpp
Original file line number Diff line number Diff line change
@@ -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 {{.*}}

0 comments on commit 1fad78b

Please sign in to comment.