1 /* Include <coroutine> or the equivalent.  */
2 #include "coro.h"
3 
4 /* Allow for stand-alone testing with no headers installed.  */
5 #if __has_include(<new>)
6 #  include <new>
7 #else
8 
9 /* Required when get_return_object_on_allocation_failure() is defined by
10   the promise.  We need a no-throw new, and new etc.  build the relevant
11   pieces here to avoid needing the headers in the test.  */
12 
13 namespace std {
14   struct nothrow_t {};
15   constexpr nothrow_t nothrow = {};
16   typedef __SIZE_TYPE__ size_t;
17 } // end namespace std
18 
19 void* operator new(std::size_t, const std::nothrow_t&) noexcept;
20 void  operator delete(void* __p, const std::nothrow_t&) noexcept;
21 
22 #endif
23 
24 /* Flags and counters so that we can test that the methods we expected
25    to be called, were called (and the correct number of times).  */
26 
27 #ifdef USE_FAILING_OP_NEW
28 extern int used_failing_new;
29 #endif
30 
31 #if defined (PROVIDE_NEW_SZT) || defined (PROVIDE_NEW_SZT_INT)
32 extern int used_ovl_new;
33 #endif
34 
35 #ifdef PROVIDE_NEW_SZT_NT
36 extern void *malloc (size_t);
37 extern int used_ovl_new_nt;
38 #endif
39 
40 #ifdef PROVIDE_DEL_VP
41 extern int used_ovl_del;
42 #endif
43 
44 #ifdef PROVIDE_DEL_VP_SZT
45 extern int used_ovl_del_2arg;
46 #endif
47 
48 #ifdef PROVIDE_GROOAF
49 extern int used_grooaf;
50 #endif
51 
52 struct coro1 {
53   struct promise_type;
54   using handle_type = coro::coroutine_handle<coro1::promise_type>;
55   handle_type handle;
coro1coro156   coro1 () noexcept : handle(0) {}
coro1coro157   coro1 (handle_type _handle) noexcept
58     : handle(_handle)  {
59         PRINT("Created coro1 object from handle");
60   }
61   coro1 (const coro1 &) = delete; // no copying
coro1coro162   coro1 (coro1 &&s) noexcept : handle(s.handle)  {
63 	s.handle = nullptr;
64 	PRINT("coro1 mv ctor ");
65   }
66   coro1 &operator = (coro1 &&s) noexcept {
67 	handle = s.handle;
68 	s.handle = nullptr;
69 	PRINT("coro1 op=  ");
70 	return *this;
71   }
~coro1coro172   ~coro1() noexcept {
73         PRINT("Destroyed coro1");
74         if ( handle )
75           handle.destroy();
76   }
77 
78   struct suspend_never_prt {
await_readycoro1::suspend_never_prt79   bool await_ready() const noexcept { return true; }
await_suspendcoro1::suspend_never_prt80   void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp");}
await_resumecoro1::suspend_never_prt81   void await_resume() const noexcept { PRINT ("susp-never-resume");}
~suspend_never_prtcoro1::suspend_never_prt82   ~suspend_never_prt() {};
83   };
84 
85   struct  suspend_always_prt {
await_readycoro1::suspend_always_prt86   bool await_ready() const noexcept { return false; }
await_suspendcoro1::suspend_always_prt87   void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");}
await_resumecoro1::suspend_always_prt88   void await_resume() const noexcept { PRINT ("susp-always-resume");}
89   };
90 
91   struct promise_type {
promise_typecoro1::promise_type92   promise_type() {  PRINT ("Created Promise"); }
~promise_typecoro1::promise_type93   ~promise_type() { PRINT ("Destroyed Promise"); }
94 
get_return_objectcoro1::promise_type95   auto get_return_object () {
96     PRINT ("get_return_object: handle from promise");
97     return handle_type::from_promise (*this);
98   }
initial_suspendcoro1::promise_type99   auto initial_suspend () {
100     PRINT ("get initial_suspend (always)");
101     return suspend_always_prt{};
102   }
final_suspendcoro1::promise_type103   auto final_suspend () noexcept {
104     PRINT ("get final_suspend (always)");
105     return suspend_always_prt{};
106   }
return_voidcoro1::promise_type107   void return_void () {
108     PRINT ("return_void ()");
109   }
unhandled_exceptioncoro1::promise_type110   void unhandled_exception() { PRINT ("** unhandled exception"); }
111 
112 #ifdef USE_FAILING_OP_NEW
113   /* Provide an operator, that always fails.  */
newcoro1::promise_type114   void *operator new (std::size_t sz) noexcept {
115     PRINT ("promise_type: used failing op new");
116     used_failing_new++;
117     return nullptr;
118   }
119 #endif
120 
121 #ifdef PROVIDE_NEW_SZT
newcoro1::promise_type122   void *operator new (std::size_t sz) {
123     PRINT ("promise_type: used overloaded operator new");
124     used_ovl_new++;
125     return ::operator new(sz);
126   }
127 #endif
128 
129 #ifdef PROVIDE_NEW_SZT_NT
newcoro1::promise_type130   void *operator new (std::size_t sz, const std::nothrow_t&) noexcept {
131     PRINT ("promise_type: used overloaded operator new NT");
132     return malloc (sz);
133   }
134 #endif
135 
136 #ifdef PROVIDE_NEW_SZT_INT
newcoro1::promise_type137   void *operator new (std::size_t sz, int x) {
138     PRINT ("promise_type: used overloaded operator new with int arg");
139     used_ovl_new += x;
140     return ::operator new(sz);
141   }
142 #endif
143 
144 #ifdef PROVIDE_DEL_VP
deletecoro1::promise_type145   void operator delete (void *p) {
146     PRINT ("promise_type: used overloaded operator delete 1 arg");
147     used_ovl_del++;
148     return ::operator delete(p);
149   }
150 #endif
151 
152 #ifdef PROVIDE_DEL_VP_SZT
deletecoro1::promise_type153   void operator delete (void *p, std::size_t sz) {
154     PRINT ("promise_type: used overloaded operator delete 2 args");
155     used_ovl_del_2arg++;
156     return ::operator delete(p);
157   }
158 #endif
159 
160 #ifdef BOGUS_OPNEW_CASE1
161   /* Provide an operator, but it doesn't match on overload.  */
newcoro1::promise_type162   void *operator new (std::size_t sz, char *f) noexcept {
163     PRINT ("promise_type: used bogus op new");
164     return nullptr;
165   }
166 #endif
167 
168 #ifdef BOGUS_OPDEL_CASE1
169   /* Provide an operator, but it doesn't match on overload.  */
deletecoro1::promise_type170   void operator delete (void *p, char *f) {
171     PRINT ("promise_type: used bogus overloaded operator delete");
172   }
173 #endif
174 
175 #ifndef BAD_GROOAF_STATIC
176 # define BAD_GROOAF_STATIC static
177 #endif
178 #ifdef PROVIDE_GROOAF
get_return_object_on_allocation_failurecoro1::promise_type179   BAD_GROOAF_STATIC coro1 get_return_object_on_allocation_failure () noexcept {
180     PRINT ("alloc fail return");
181     used_grooaf++;
182     return coro1 (nullptr);
183   }
184 #endif
185 
186   }; // promise
187 }; // coro1
188