1 //  { dg-do run { target c++17 } }
2 
3 #include "../coro.h"
4 
5 class resumable {
6 public:
7   struct promise_type;
8   using coro_handle = std::coroutine_handle<promise_type>;
9   resumable(coro_handle handle) : handle_(handle) { }
10   resumable(resumable&) = delete;
11   resumable(resumable&&) = delete;
12   ~resumable() { handle_.destroy(); }
13   coro_handle handle_;
14 };
15 
16 struct resumable::promise_type {
17   using coro_handle = std::coroutine_handle<promise_type>;
18   int used;
19   auto get_return_object() {
20     return coro_handle::from_promise(*this);
21   }
22   auto initial_suspend() { return std::suspend_never(); }
23   auto final_suspend() noexcept { return std::suspend_always(); }
24   void return_value(int x) {used = x;}
25   void unhandled_exception() {}
26 
27   struct TestAwaiter {
28     int recent_test;
29     TestAwaiter(int test) : recent_test{test} {}
30     bool await_ready() { return false; }
31     void await_suspend(std::coroutine_handle<promise_type>) {}
32     int await_resume() {
33       return recent_test;
34     }
35     auto operator co_await() {
36       return *this;
37     }
38   };
39 
40   struct TestAwaiterCH :TestAwaiter {
41     TestAwaiterCH(int test) : TestAwaiter(test) {};
42   };
43 
44   struct TestAwaiterCHCH :TestAwaiterCH {
45     TestAwaiterCHCH(int test) : TestAwaiterCH(test) {};
46 
47     resumable foo(){
48     int x = co_await *this;
49     co_return x;
50     }
51   };
52 };
53 
54 struct TestP {
55  resumable::promise_type::TestAwaiterCHCH  tp = resumable::promise_type::TestAwaiterCHCH(6);
56 };
57 
58 resumable foo1(int t){
59   int x = co_await resumable::promise_type::TestAwaiterCH(t);
60   co_return x;
61 }
62 
63 resumable foo2(){
64   struct TestP  TP;
65   int x = co_await TP.tp;
66   co_return x;
67 }
68 
69 resumable foo3(){
70   int x = co_await TestP{}.tp;
71   co_return x;
72 }
73 
74 int main(){
75   auto t = resumable::promise_type::TestAwaiterCHCH(4);
76   resumable res = t.foo();
77   while (!res.handle_.done())
78     res.handle_.resume();
79   if (res.handle_.promise().used != 4)
80     abort();
81 
82   resumable res1 = foo1(5);
83   while (!res1.handle_.done())
84     res1.handle_.resume();
85   if (res1.handle_.promise().used != 5)
86     abort();
87 
88   resumable res2 = foo2();
89   while (!res2.handle_.done())
90     res2.handle_.resume();
91   if (res2.handle_.promise().used != 6)
92     abort();
93 
94   resumable res3 = foo2();
95   while (!res3.handle_.done())
96     res3.handle_.resume();
97   if (res3.handle_.promise().used != 6)
98     abort();
99 }
100