Open
Description
The code below will trigger the assert(err == message) on windows with clang 20.1.0. While it will pass with gcc and msvc. Also the clang on linux does not have this issue.
This issue looks like #59723, which should had been fixed on the 20.1.0.
#include <cassert>
#include <coroutine>
#include <exception>
#include <iostream>
#include <stdexcept>
#include <string>
struct Task
{
struct promise_type;
using handle_type = std::coroutine_handle<promise_type>;
struct promise_type
{
std::exception_ptr exception;
handle_type continuation;
Task get_return_object()
{
return Task{handle_type::from_promise(*this)};
}
std::suspend_always initial_suspend() noexcept
{
return {};
}
auto final_suspend() noexcept
{
struct FinalAwaiter
{
bool await_ready() noexcept
{
return false;
}
void await_resume() noexcept
{
}
std::coroutine_handle<> await_suspend(handle_type h) noexcept
{
auto& promise = h.promise();
return promise.continuation ? std::coroutine_handle<>(promise.continuation) : std::noop_coroutine();
}
};
return FinalAwaiter{};
}
void unhandled_exception()
{
exception = std::current_exception();
}
void return_void()
{
}
};
handle_type handle;
explicit Task(handle_type h) : handle(h)
{
}
~Task()
{
if (handle)
handle.destroy();
}
bool await_ready() const noexcept
{
return false;
}
handle_type await_suspend(std::coroutine_handle<> continuation) noexcept
{
handle.promise().continuation =
handle_type::from_address(continuation.address());
return handle;
}
void await_resume()
{
rethrowIfAny();
}
void start()
{
if (handle && !handle.done())
{
handle.resume();
}
}
void rethrowIfAny()
{
if (handle.promise().exception)
{
// auto except = handle.promise().exception;
// handle.promise().exception = nullptr;
std::rethrow_exception(handle.promise().exception);
}
}
};
int main()
{
constexpr static char message[] = "test a very long message ~~~~~~~";
auto taskLambda = [&]() -> Task {
try
{
co_await []() -> Task {
co_await []() -> Task {
throw std::runtime_error(message);
}();
}();
}
catch (std::runtime_error e)
{
const std::string err = e.what();
std::cout << err << std::endl;
assert(err == message);
}
};
Task task = taskLambda();
task.start();
return 0;
}
Below is the command line execution record.
C:\Users\YXX\source\repos\TestNestedCoroutine>clang++ --version
clang version 20.1.0
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin
C:\Users\YXX\source\repos\TestNestedCoroutine>clang++ -std=c++20 -O0 -g -o test.exe TestNestedCoroutine.cpp
C:\Users\YXX\source\repos\TestNestedCoroutine>test.exe
Unknown exception
Assertion failed: err == message, file TestNestedCoroutine.cpp, line 124