aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArsen Arsenović <arsen@aarsen.me>2024-09-03 20:58:55 +0200
committerArsen Arsenović <arsen@gcc.gnu.org>2024-09-04 16:52:03 +0200
commit858918ef4233c837ab85819ad159bf452df3a7fb (patch)
treef96e22885e3cceca442abf736092dcb19509cf1e
parent7b7ad3f4b2455072f42e7884b93fd96ebb920bc8 (diff)
downloadgcc-858918ef4233c837ab85819ad159bf452df3a7fb.zip
gcc-858918ef4233c837ab85819ad159bf452df3a7fb.tar.gz
gcc-858918ef4233c837ab85819ad159bf452df3a7fb.tar.bz2
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.
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr108620.C95
1 files changed, 95 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/coroutines/pr108620.C b/gcc/testsuite/g++.dg/coroutines/pr108620.C
new file mode 100644
index 0000000..e8016b9
--- /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;
+}