Mercurial > hg > CbC > CbC_gcc
view gcc/testsuite/g++.dg/coroutines/torture/exceptions-test-01-n4849-a.C @ 152:2b5abeee2509
update gcc11
author | anatofuz |
---|---|
date | Mon, 25 May 2020 07:50:57 +0900 |
parents | |
children |
line wrap: on
line source
// { dg-do run } // Test exceptions in the initial await expression, per n4849. #include "../coro.h" #include <exception> int gX = 0; struct coro1 { struct promise_type; using handle_type = coro::coroutine_handle<coro1::promise_type>; handle_type handle; coro1 () : handle(0) {} coro1 (handle_type _handle) : handle(_handle) { PRINT("Created coro1 object from handle"); } coro1 (const coro1 &) = delete; // no copying coro1 (coro1 &&s) : handle(s.handle) { s.handle = nullptr; PRINT("coro1 mv ctor "); } coro1 &operator = (coro1 &&s) { handle = s.handle; s.handle = nullptr; PRINT("coro1 op= "); return *this; } ~coro1() { PRINT("Destroyed coro1"); if ( handle ) handle.destroy(); } struct suspend_never_prt { bool await_ready() const noexcept { return true; } void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp"); } void await_resume() const noexcept { PRINT ("susp-never-resume");} }; struct suspend_always_prt { bool await_ready() const noexcept { return false; } void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp"); } void await_resume() const noexcept { PRINT ("susp-always-resume"); } ~suspend_always_prt() { PRINT ("susp-always-DTOR"); } }; /* Constructing this with: * a value of '1' will cause the initial suspend await_suspend() call to throw. * a value of '2' will cause the await resume to throw. */ struct suspend_always_susp_throws_prt { int thrower; suspend_always_susp_throws_prt (int _t) : thrower(_t) {} bool await_ready() const noexcept { return false; } void await_suspend(handle_type) const { PRINT ("suspend_always_susp_throws_prt:await_suspend"); if (thrower == 1) throw (42); } void await_resume() const { PRINT ("suspend_always_susp_throws_prt:await_resume"); if (thrower == 2) throw (6174); } ~suspend_always_susp_throws_prt() { PRINT ("suspend_always_susp_throws_prt-DTOR"); } }; struct promise_type { int throw_control = 0; int value; promise_type(int k) : throw_control(k), value(-373) { PRINTF ("Created Promise with %d\n", k);} ~promise_type() { PRINT ("Destroyed Promise"); } auto get_return_object () { PRINT ("get_return_object: handle from promise"); return handle_type::from_promise (*this); } // This provides the tests for what catches exceptions thrown at // different points in the initial await expression. auto initial_suspend () { PRINT ("get initial_suspend (always)"); return suspend_always_susp_throws_prt(throw_control); } auto final_suspend () { PRINT ("get final_suspend (always)"); return suspend_always_prt{}; } void return_value (int v) { PRINTF ("return_value () %d\n",v); value = v; } auto yield_value (int v) { PRINTF ("yield_value () %d and suspend always\n",v); value = v; return suspend_always_prt{}; } int get_value (void) { return value; } void unhandled_exception() { PRINT ("unhandled_exception: caught one!"); gX = -11; // returning from here should end up in final_suspend. } }; }; // This doesn't have to do much - we only need to exercise the initial // await expression. struct coro1 n4849_ia_thrower (int k) { int caught = 0; PRINT ("f: about to return 22"); co_return 22; } int main () { { /* Case 0 - nothing should throw. */ struct coro1 x0; try { x0 = n4849_ia_thrower (0); } catch (...) { PRINT ("main: case 0 ctor threw?"); abort (); } /* Resume the initial suspend expression. */ PRINT ("main: got coro, resuming.."); x0.handle.resume(); int y = x0.handle.promise().get_value(); if ( y != 22 ) { PRINT ("main: case 0 got the wrong answer."); abort (); } if (!x0.handle.done()) { PRINT ("main: case 0 not done."); abort (); } if (gX != 0) { PRINT ("main: case 0 body threw?"); abort (); } } { /* Case 1 - initial suspend should throw and thus be caught by the ramp's caller. */ struct coro1 x1; try { x1 = n4849_ia_thrower (1); } catch (int message) { PRINTF ("main: caught an int %d\n", message); if (message != 42) { PRINT ("main: unexpected value?"); abort (); } } catch (...) { PRINT ("main: case 1 ctor threw something else?"); abort (); } if (gX != 0) { PRINT ("main: case 0 body threw (how?)"); abort (); } } { /* Case 2 - the await_resume from the initial await expression throws this should be caught by the regular function body wrapper. */ struct coro1 x2; try { x2 = n4849_ia_thrower (2); } catch (...) { PRINT ("main: case 2 ctor threw?"); abort (); } // We now resume - and expect the await_resume to throw which should // be caught by unhandled_exception(). PRINT ("main: got coro, resuming.."); x2.handle.resume(); int y = x2.handle.promise().get_value(); if ( y != -373 ) { PRINT ("main: case 2 got the wrong answer."); abort (); } if (!x2.handle.done()) { PRINT ("main: case 2 not done."); abort (); } if (gX != -11) { PRINT ("main: n4849_is_thrower await_resume exception not caught"); abort (); } } PRINT ("main: returning"); return 0; }