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)58resumable foo1(int t){ 59 int x = co_await resumable::promise_type::TestAwaiterCH(t); 60 co_return x; 61 } 62 foo2()63resumable foo2(){ 64 struct TestP TP; 65 int x = co_await TP.tp; 66 co_return x; 67 } 68 foo3()69resumable foo3(){ 70 int x = co_await TestP{}.tp; 71 co_return x; 72 } 73 main()74int 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