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()46 coro_t f() {
47   f_started = true;
48   co_await DoSuspend{};
49   f_resumed = true;
50 }
51 
52 bool g_started, g_resumed = false;
g()53 coro_t g() {
54   g_started = true;
55   co_await NoSuspend{};
56   g_resumed = true;
57 }
58 
main(int,char **)59 int 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