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