diff mbox series

[pushed] c++: add a testcase for [PR 108620]

Message ID 20240904145836.643680-1-arsen@aarsen.me
State New
Headers show
Series [pushed] c++: add a testcase for [PR 108620] | expand

Commit Message

Arsen Arsenović Sept. 4, 2024, 2:53 p.m. UTC
Pushed as obvious.
---------- >8 ----------
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 mbox series

Patch

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;
+}