Outdated Coroutine Exception Handling in Initial Suspend `await_resume()`?

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

I fixed this bug with the current implementation. I think the current implementation is equivalent to what the standard dictates and is likely to be better in some ways (i.e. not emitting the try block around init-suspend.await_resume() if it’s noexcept.)