1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is dual licensed under the MIT and the University of Illinois Open 7 // Source Licenses. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 // UNSUPPORTED: c++98, c++03, c++11 12 13 // See https://bugs.llvm.org/show_bug.cgi?id=33271 14 // UNSUPPORTED: ubsan 15 16 #include <experimental/coroutine> 17 #include <cassert> 18 19 using namespace std::experimental; 20 21 struct coro_t { 22 struct promise_type { get_return_objectcoro_t::promise_type23 coro_t get_return_object() { 24 return coroutine_handle<promise_type>::from_promise(*this); 25 } initial_suspendcoro_t::promise_type26 suspend_never initial_suspend() { return {}; } final_suspendcoro_t::promise_type27 suspend_never final_suspend() { return {}; } return_voidcoro_t::promise_type28 void return_void() {} unhandled_exceptioncoro_t::promise_type29 void unhandled_exception() {} 30 }; coro_tcoro_t31 coro_t(coroutine_handle<promise_type> hh) : h(hh) {} 32 coroutine_handle<promise_type> h; 33 }; 34 35 struct NoSuspend { await_readyNoSuspend36 bool await_ready() { return false; } await_resumeNoSuspend37 void await_resume() {} await_suspendNoSuspend38 template <typename F> bool await_suspend(F) { return false; } 39 }; 40 41 struct DoSuspend { await_readyDoSuspend42 bool await_ready() { return false; } await_resumeDoSuspend43 void await_resume() {} await_suspendDoSuspend44 template <typename F> bool await_suspend(F) { return true; } 45 }; 46 47 bool f_started, f_resumed = false; f()48coro_t f() { 49 f_started = true; 50 co_await DoSuspend{}; 51 f_resumed = true; 52 } 53 54 bool g_started, g_resumed = false; g()55coro_t g() { 56 g_started = true; 57 co_await NoSuspend{}; 58 g_resumed = true; 59 } 60 main()61int main() { 62 assert(!f_started && !f_resumed && !g_started && !g_resumed); 63 auto fret = f(); 64 assert(f_started && !f_resumed); 65 fret.h.destroy(); 66 assert(f_started && !f_resumed); 67 g(); 68 assert(g_started && g_resumed); 69 } 70