Hello Clang developers,
I am trying to fix this ICE related to exception handling coroutine in initial suspend’s await_resume
.
A small repro:
#include <coroutine>
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() {
co_return;
}
The crash occurs when the return type of await_resume
is not trivially destructible. We tried to emit an expr that binds the temporary to a RValue here, that EmitAnyExpr
messed up the EHScopeStack
state EnterCXXTryStmt
sets up for us.
This code gen seems to be more complicated than what the standard suggests. There’s also this test case validates that the try block was around the co_await promise-type.initial_suspend()
and sets up the flag for skipping the body.
Based on what the standard says, I don’t think we should continue doing this anymore, but I also feel like I might be missing something obvious. I have a draft PR to work on and the only failing test is the one above.
I feel like I need to discuss with the community what we’d like to do here. Is this PR on the right track? If no, what should I do to fix it?
Thanks.
Yuxuan