Skip to content

Commit 1fad78b

Browse files
[Clang][Coroutines] Properly emit EH code for initial suspend await_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.
1 parent 2c87571 commit 1fad78b

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,9 @@ Bug Fixes in This Version
610610
inside a lambda. (`#61460 <https://github.com/llvm/llvm-project/issues/61460>`_)
611611
- Fix crash during instantiation of some class template specializations within class
612612
templates. Fixes (`#70375 <https://github.com/llvm/llvm-project/issues/70375>`_)
613+
- Fix crash during code generation of C++ coroutine initial suspend when the return
614+
type of await_resume is not trivially destructible.
615+
Fixes (`#63803 <https://github.com/llvm/llvm-project/issues/63803>`_)
613616

614617
Bug Fixes to Compiler Builtins
615618
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/CodeGen/CGCoroutine.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,15 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
245245
FPOptionsOverride(), Loc, Loc);
246246
TryStmt = CXXTryStmt::Create(CGF.getContext(), Loc, TryBody, Catch);
247247
CGF.EnterCXXTryStmt(*TryStmt);
248+
CGF.EmitStmt(TryBody);
249+
// We don't use EmitCXXTryStmt here. We need to store to ResumeEHVar that
250+
// doesn't exist in the body.
251+
Builder.CreateFlagStore(false, Coro.ResumeEHVar);
252+
CGF.ExitCXXTryStmt(*TryStmt);
253+
LValueOrRValue Res;
254+
// We are not supposed to obtain the value from init suspend await_resume().
255+
Res.RV = RValue::getIgnored();
256+
return Res;
248257
}
249258

250259
LValueOrRValue Res;
@@ -253,11 +262,6 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
253262
else
254263
Res.RV = CGF.EmitAnyExpr(S.getResumeExpr(), aggSlot, ignoreResult);
255264

256-
if (TryStmt) {
257-
Builder.CreateFlagStore(false, Coro.ResumeEHVar);
258-
CGF.ExitCXXTryStmt(*TryStmt);
259-
}
260-
261265
return Res;
262266
}
263267

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %clang_cc1 -std=c++20 -triple=x86_64-- -emit-llvm -fcxx-exceptions \
2+
// RUN: -disable-llvm-passes %s -o - | FileCheck %s
3+
4+
#include "Inputs/coroutine.h"
5+
6+
struct NontrivialType {
7+
~NontrivialType() {}
8+
};
9+
10+
struct Task {
11+
struct promise_type;
12+
using handle_type = std::coroutine_handle<promise_type>;
13+
14+
struct initial_suspend_awaiter {
15+
bool await_ready() {
16+
return false;
17+
}
18+
19+
void await_suspend(handle_type h) {}
20+
21+
NontrivialType await_resume() { return {}; }
22+
};
23+
24+
struct promise_type {
25+
void return_void() {}
26+
void unhandled_exception() {}
27+
initial_suspend_awaiter initial_suspend() { return {}; }
28+
std::suspend_never final_suspend() noexcept { return {}; }
29+
Task get_return_object() {
30+
return Task{handle_type::from_promise(*this)};
31+
}
32+
};
33+
34+
handle_type handler;
35+
};
36+
37+
Task coro_create() {
38+
co_return;
39+
}
40+
41+
// CHECK-LABEL: define{{.*}} ptr @_Z11coro_createv(
42+
// CHECK: init.ready:
43+
// CHECK-NEXT: store i1 true, ptr {{.*}}
44+
// CHECK-NEXT: call void @_ZN4Task23initial_suspend_awaiter12await_resumeEv(
45+
// CHECK-NEXT: call void @_ZN14NontrivialTypeD1Ev(
46+
// CHECK-NEXT: store i1 false, ptr {{.*}}

0 commit comments

Comments
 (0)