From: Arsen Arsenović Date: Tue, 3 Sep 2024 18:58:55 +0000 (+0200) Subject: c++: add a testcase for [PR 108620] X-Git-Tag: basepoints/gcc-16~6099 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=858918ef4233c837ab85819ad159bf452df3a7fb;p=thirdparty%2Fgcc.git c++: add a testcase for [PR 108620] Fixed by r15-2540-g32e678b2ed7521. Add a testcase, as the original ones do not cover this particular failure mode. gcc/testsuite/ChangeLog: PR c++/108620 * g++.dg/coroutines/pr108620.C: New test. --- diff --git a/gcc/testsuite/g++.dg/coroutines/pr108620.C b/gcc/testsuite/g++.dg/coroutines/pr108620.C new file mode 100644 index 00000000000..e8016b9f8a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr108620.C @@ -0,0 +1,95 @@ +// https://gcc.gnu.org/PR108620 +#include +#include +#include + +template +struct task; + +template +struct task_private_data { + inline task_private_data() noexcept : data_(nullptr) {} + inline task_private_data(PrivateDataType* input) noexcept : data_(input) {} + inline task_private_data(task_private_data&& other) noexcept = default; + inline task_private_data& operator=(task_private_data&&) noexcept = default; + inline task_private_data(const task_private_data&) = delete; + inline task_private_data& operator=(const task_private_data&) = delete; + inline ~task_private_data() {} + + inline bool await_ready() const noexcept { return true; } + inline PrivateDataType* await_resume() const noexcept { return data_; } + inline void await_suspend(std::coroutine_handle<>) noexcept {} + + PrivateDataType* data_; +}; + +template +struct task_context { + PrivateDataType data_; +}; + +template +struct task { + using self_type = task; + std::shared_ptr> context_; + + task(const std::shared_ptr>& input): context_(input) {} + + static auto yield_private_data() noexcept { return task_private_data{}; } + + struct promise_type { + std::shared_ptr> context_; + + template + promise_type(Input&& input, Rest&&...) { + context_ = std::make_shared>(); + context_->data_ = std::forward(input); + } + + auto get_return_object() noexcept { return self_type{context_}; } + std::suspend_never initial_suspend() noexcept { return {}; } + std::suspend_never final_suspend() noexcept { return {}; } + void unhandled_exception() { throw; } + + template + void return_value(ReturnType&&) {} + + template + inline task_private_data yield_value( + task_private_data&& input) noexcept { + input.data_ = &context_->data_; + return task_private_data(input.data_); + } + }; +}; + +template +task call1(TArg&& arg, OutputType& output) { + OutputType* ptr = co_yield task::yield_private_data(); + output = *ptr; + co_return 0; +} + + +struct container { + std::string* ptr; +}; + +template +task call2(TArg&& arg, container& output) { + output.ptr = co_yield task::yield_private_data(); + co_return 0; +} + +int main() { + // success + std::string output1; + call1(std::string("hello1"), output1); + std::cout<< "output1: "<< output1<< std::endl; + + // crash + container output2; + auto task2 = call2(std::string("hello2"), output2); + std::cout<< "output2: "<< *output2.ptr<< std::endl; + return 0; +}