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>;
resumable(coro_handle handle)9   resumable(coro_handle handle) : handle_(handle) { }
10   resumable(resumable&) = delete;
11   resumable(resumable&&) = delete;
~resumable()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;
get_return_objectpromise_type19   auto get_return_object() {
20     return coro_handle::from_promise(*this);
21   }
initial_suspendpromise_type22   auto initial_suspend() { return std::suspend_never(); }
final_suspendpromise_type23   auto final_suspend() noexcept { return std::suspend_always(); }
return_valuepromise_type24   void return_value(int x) {used = x;}
unhandled_exceptionpromise_type25   void unhandled_exception() {}
26 
27   struct TestAwaiter {
28     int recent_test;
TestAwaiterpromise_type::TestAwaiter29     TestAwaiter(int test) : recent_test{test} {}
await_readypromise_type::TestAwaiter30     bool await_ready() { return false; }
await_suspendpromise_type::TestAwaiter31     void await_suspend(std::coroutine_handle<promise_type>) {}
await_resumepromise_type::TestAwaiter32     int await_resume() {
33       return recent_test;
34     }
co_awaitpromise_type::TestAwaiter35     auto operator co_await() {
36       return *this;
37     }
38   };
39 
40   struct TestAwaiterCH :TestAwaiter {
TestAwaiterCHpromise_type::TestAwaiterCH41     TestAwaiterCH(int test) : TestAwaiter(test) {};
42   };
43 
44   struct TestAwaiterCHCH :TestAwaiterCH {
TestAwaiterCHCHpromise_type::TestAwaiterCHCH45     TestAwaiterCHCH(int test) : TestAwaiterCH(test) {};
46 
foopromise_type::TestAwaiterCHCH47     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 
foo1(int t)58 resumable foo1(int t){
59   int x = co_await resumable::promise_type::TestAwaiterCH(t);
60   co_return x;
61 }
62 
foo2()63 resumable foo2(){
64   struct TestP  TP;
65   int x = co_await TP.tp;
66   co_return x;
67 }
68 
foo3()69 resumable foo3(){
70   int x = co_await TestP{}.tp;
71   co_return x;
72 }
73 
main()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