1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 11 // See https://llvm.org/PR33271 12 // UNSUPPORTED: ubsan 13 14 #include <coroutine> 15 #include <cassert> 16 17 #include "test_macros.h" 18 19 struct coro_t { 20 struct promise_type { get_return_objectcoro_t::promise_type21 coro_t get_return_object() { 22 return std::coroutine_handle<promise_type>::from_promise(*this); 23 } initial_suspendcoro_t::promise_type24 std::suspend_never initial_suspend() { return {}; } final_suspendcoro_t::promise_type25 std::suspend_never final_suspend() noexcept { return {}; } return_voidcoro_t::promise_type26 void return_void() {} unhandled_exceptioncoro_t::promise_type27 void unhandled_exception() {} 28 }; coro_tcoro_t29 coro_t(std::coroutine_handle<promise_type> hh) : h(hh) {} 30 std::coroutine_handle<promise_type> h; 31 }; 32 33 struct NoSuspend { await_readyNoSuspend34 bool await_ready() { return false; } await_resumeNoSuspend35 void await_resume() {} await_suspendNoSuspend36 template <typename F> bool await_suspend(F) { return false; } 37 }; 38 39 struct DoSuspend { await_readyDoSuspend40 bool await_ready() { return false; } await_resumeDoSuspend41 void await_resume() {} await_suspendDoSuspend42 template <typename F> bool await_suspend(F) { return true; } 43 }; 44 45 bool f_started, f_resumed = false; f()46coro_t f() { 47 f_started = true; 48 co_await DoSuspend{}; 49 f_resumed = true; 50 } 51 52 bool g_started, g_resumed = false; g()53coro_t g() { 54 g_started = true; 55 co_await NoSuspend{}; 56 g_resumed = true; 57 } 58 main(int,char **)59int main(int, char**) { 60 assert(!f_started && !f_resumed && !g_started && !g_resumed); 61 auto fret = f(); 62 assert(f_started && !f_resumed); 63 fret.h.destroy(); 64 assert(f_started && !f_resumed); 65 g(); 66 assert(g_started && g_resumed); 67 68 return 0; 69 } 70