1 //  { dg-do run }
2 
3 // test boolean return from await_suspend ().
4 
5 #include "../coro.h"
6 
7 int coro1_dtor_ran = 0;
8 int promise_dtor_ran = 0;
9 
10 struct coro1 {
11   struct promise_type;
12   using handle_type = coro::coroutine_handle<coro1::promise_type>;
13   handle_type handle;
coro1coro114   coro1 () : handle(0) {}
coro1coro115   coro1 (handle_type _handle)
16     : handle(_handle) {
17         PRINT("Created coro1 object from handle");
18   }
19   coro1 (const coro1 &) = delete; // no copying
coro1coro120   coro1 (coro1 &&s) : handle(s.handle) {
21 	s.handle = nullptr;
22 	PRINT("coro1 mv ctor ");
23   }
24   coro1 &operator = (coro1 &&s) {
25 	handle = s.handle;
26 	s.handle = nullptr;
27 	PRINT("coro1 op=  ");
28 	return *this;
29   }
30 
~coro1coro131   ~coro1() {
32         PRINT("Destroyed coro1");
33         coro1_dtor_ran++;
34         // The coro handle will point to an invalid frame by this stage,
35         // the coroutine will already have self-destroyed the frame and
36         // promise.
37   }
38 
39   struct suspend_never_prt {
await_readycoro1::suspend_never_prt40   bool await_ready() const noexcept { return true; }
await_suspendcoro1::suspend_never_prt41   bool await_suspend(handle_type) const noexcept {
42     PRINT ("susp-never-susp"); // never executed.
43     return true; // ...
44   }
await_resumecoro1::suspend_never_prt45   void await_resume() const noexcept {PRINT ("susp-never-resume");}
~suspend_never_prtcoro1::suspend_never_prt46   ~suspend_never_prt() {};
47   };
48 
49   struct  suspend_always_prt {
await_readycoro1::suspend_always_prt50   bool await_ready() const noexcept { return false; }
await_suspendcoro1::suspend_always_prt51   bool await_suspend(handle_type) const noexcept {
52     PRINT ("susp-always-susp, but we're going to continue.. ");
53     return false; // not going to suspend.
54   }
await_resumecoro1::suspend_always_prt55   void await_resume() const noexcept { PRINT ("susp-always-resume");}
56   };
57 
58   struct promise_type {
promise_typecoro1::promise_type59   promise_type() {  PRINT ("Created Promise"); }
~promise_typecoro1::promise_type60   ~promise_type() {
61      PRINT ("Destroyed Promise");
62      promise_dtor_ran++;
63    }
64 
get_return_objectcoro1::promise_type65   coro1 get_return_object () {
66     PRINT ("get_return_object: from handle from promise");
67     return coro1 (handle_type::from_promise (*this));
68   }
initial_suspendcoro1::promise_type69   auto initial_suspend () {
70     PRINT ("get initial_suspend (always, but really never) ");
71     return suspend_always_prt{};
72   }
final_suspendcoro1::promise_type73   auto final_suspend () noexcept {
74     PRINT ("get final_suspend (always, but never) ");
75     return suspend_always_prt{};
76   }
return_voidcoro1::promise_type77   void return_void () {
78     PRINT ("return_void ()");
79   }
unhandled_exceptioncoro1::promise_type80   void unhandled_exception() { PRINT ("** unhandled exception"); }
81   };
82 };
83 
84 struct coro1
my_coro()85 my_coro () noexcept
86 {
87   PRINT ("coro1: about to return");
88   co_return;
89 }
90 
main()91 int main ()
92 {
93   { // scope so that we can examine the coro dtor marker.
94     PRINT ("main: creating coro");
95 
96     // This should just run through to completion/destruction.
97     // In both the initial and final await expressions, the await_suspend()
98     // method will return 'false' and prevent the suspension.
99     struct coro1 x = my_coro ();
100 
101     PRINT ("main: the coro frame should be already destroyed");
102     // We will take the running of the promise DTOR as evidence that the
103     // frame was destroyed as expected.
104     if (promise_dtor_ran != 1)
105       {
106 	PRINT ("main: apparently we didn't destroy the frame");
107 	abort ();
108       }
109   }
110   if (coro1_dtor_ran != 1 || promise_dtor_ran != 1)
111     {
112       PRINT ("main: bad DTOR counts");
113       abort ();
114     }
115   PRINT ("main: returning");
116   return 0;
117 }
118