From 858918ef4233c837ab85819ad159bf452df3a7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= <arsen@aarsen.me> Date: Tue, 3 Sep 2024 20:58:55 +0200 Subject: [PATCH] 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. --- gcc/testsuite/g++.dg/coroutines/pr108620.C | 95 ++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr108620.C diff --git a/gcc/testsuite/g++.dg/coroutines/pr108620.C b/gcc/testsuite/g++.dg/coroutines/pr108620.C new file mode 100644 index 000000000000..e8016b9f8a23 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr108620.C @@ -0,0 +1,95 @@ +// https://gcc.gnu.org/PR108620 +#include <iostream> +#include <memory> +#include <coroutine> + +template<class PrivateDataType> +struct task; + +template <class PrivateDataType> +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<class PrivateDataType> +struct task_context { + PrivateDataType data_; +}; + +template<class PrivateDataType> +struct task { + using self_type = task<PrivateDataType>; + std::shared_ptr<task_context<PrivateDataType>> context_; + + task(const std::shared_ptr<task_context<PrivateDataType>>& input): context_(input) {} + + static auto yield_private_data() noexcept { return task_private_data<PrivateDataType>{}; } + + struct promise_type { + std::shared_ptr<task_context<PrivateDataType>> context_; + + template<class Input, class... Rest> + promise_type(Input&& input, Rest&&...) { + context_ = std::make_shared<task_context<PrivateDataType>>(); + context_->data_ = std::forward<Input>(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<class ReturnType> + void return_value(ReturnType&&) {} + + template <class InputPrivateDataType> + inline task_private_data<InputPrivateDataType> yield_value( + task_private_data<InputPrivateDataType>&& input) noexcept { + input.data_ = &context_->data_; + return task_private_data<InputPrivateDataType>(input.data_); + } + }; +}; + +template<class TArg, class OutputType> +task<std::string> call1(TArg&& arg, OutputType& output) { + OutputType* ptr = co_yield task<TArg>::yield_private_data(); + output = *ptr; + co_return 0; +} + + +struct container { + std::string* ptr; +}; + +template<class TArg> +task<std::string> call2(TArg&& arg, container& output) { + output.ptr = co_yield task<TArg>::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; +} -- GitLab