1 //  { dg-do run }
2 
3 // Test returning a T.
4 // We will use the promise to contain this to avoid having to include
5 // additional C++ headers.
6 
7 #include "../coro.h"
8 
9 struct suspend_never_prt {
await_readysuspend_never_prt10   bool await_ready() const noexcept { return true; }
await_suspendsuspend_never_prt11   void await_suspend(coro::coroutine_handle<>) const noexcept
12     { PRINT ("susp-never-susp"); }
await_resumesuspend_never_prt13   void await_resume() const noexcept { PRINT ("susp-never-resume");}
14 };
15 
16 /* NOTE: this has a DTOR to test that pathway.  */
17 struct  suspend_always_prt {
await_readysuspend_always_prt18   bool await_ready() const noexcept { return false; }
await_suspendsuspend_always_prt19   void await_suspend(coro::coroutine_handle<>) const noexcept
20     { PRINT ("susp-always-susp"); }
await_resumesuspend_always_prt21   void await_resume() const noexcept { PRINT ("susp-always-resume"); }
~suspend_always_prtsuspend_always_prt22   ~suspend_always_prt() { PRINT ("susp-always-DTOR"); }
23 };
24 
25 template <typename T>
26 struct coro1 {
27   struct promise_type;
28   using handle_type = coro::coroutine_handle<coro1::promise_type>;
29   handle_type handle;
coro1coro130   coro1 () : handle(0) {}
coro1coro131   coro1 (handle_type _handle)
32     : handle(_handle) {
33     PRINT("Created coro1 object from handle");
34   }
35   coro1 (const coro1 &) = delete; // no copying
coro1coro136   coro1 (coro1 &&s) : handle(s.handle) {
37     s.handle = nullptr;
38     PRINT("coro1 mv ctor ");
39   }
40   coro1 &operator = (coro1 &&s) {
41     handle = s.handle;
42     s.handle = nullptr;
43     PRINT("coro1 op=  ");
44     return *this;
45   }
~coro1coro146   ~coro1() {
47     PRINT("Destroyed coro1");
48     if ( handle )
49       handle.destroy();
50   }
51 
52   struct promise_type {
53   T value;
promise_typecoro1::promise_type54   promise_type() {  PRINT ("Created Promise"); }
~promise_typecoro1::promise_type55   ~promise_type() { PRINT ("Destroyed Promise"); }
56 
get_return_objectcoro1::promise_type57   auto get_return_object () {
58     PRINT ("get_return_object: handle from promise");
59     return handle_type::from_promise (*this);
60   }
61 
initial_suspendcoro1::promise_type62   auto initial_suspend () const {
63     PRINT ("get initial_suspend (always)");
64     return suspend_always_prt{};
65   }
final_suspendcoro1::promise_type66   auto final_suspend () const noexcept {
67     PRINT ("get final_suspend (always)");
68     return suspend_always_prt{};
69   }
return_valuecoro1::promise_type70   void return_value (T v) {
71     PRINTF ("return_value () %d\n",v);
72     value = v;
73   }
get_valuecoro1::promise_type74   T get_value (void) { return value; }
unhandled_exceptioncoro1::promise_type75   void unhandled_exception() { PRINT ("** unhandled exception"); }
76   };
77 };
78 
79 coro1<float>
f()80 f () noexcept
81 {
82   PRINT ("coro1: about to return");
83   co_return (float) 42;
84 }
85 
main()86 int main ()
87 {
88   PRINT ("main: create coro1");
89   coro1<float> x = f ();
90   PRINT ("main: got coro1 - resuming");
91   if (x.handle.done())
92     abort();
93   x.handle.resume();
94   PRINT ("main: after resume");
95   int y = x.handle.promise().get_value();
96   if ( y != (float)42 )
97     abort ();
98   if (!x.handle.done())
99     {
100       PRINT ("main: apparently not done...");
101       abort ();
102     }
103   PRINT ("main: returning");
104   return 0;
105 }
106