1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++03, c++11
11 
12 #include <experimental/coroutine>
13 #include <cassert>
14 
15 #include "test_macros.h"
16 
17 using namespace std::experimental;
18 
19 int alive = 0;
20 int ctor_called = 0;
21 int dtor_called = 0;
reset()22 void reset() {
23   assert(alive == 0);
24   alive = 0;
25   ctor_called = 0;
26   dtor_called = 0;
27 }
28 struct Noisy {
NoisyNoisy29   Noisy() { ++alive; ++ctor_called; }
~NoisyNoisy30   ~Noisy() { --alive; ++dtor_called; }
31 #if TEST_STD_VER > 14
32   Noisy(Noisy const&) = delete;
33 #else
34   // FIXME: This test depends on copy elision taking place in C++14
35   // (pre-C++17 guaranteed copy elision)
36   Noisy(Noisy const&);
37 #endif
38 };
39 
40 struct Bug {
await_readyBug41   bool await_ready() { return true; }
await_suspendBug42   void await_suspend(std::experimental::coroutine_handle<>) {}
await_resumeBug43   Noisy await_resume() { return {}; }
44 };
45 struct coro2 {
46   struct promise_type {
initial_suspendcoro2::promise_type47     suspend_never initial_suspend() { return{}; }
final_suspendcoro2::promise_type48     suspend_never final_suspend() noexcept { return {}; }
get_return_objectcoro2::promise_type49     coro2 get_return_object() { return{}; }
return_voidcoro2::promise_type50     void return_void() {}
yield_valuecoro2::promise_type51     Bug yield_value(int) { return {}; }
unhandled_exceptioncoro2::promise_type52     void unhandled_exception() {}
53   };
54 };
55 
56 // Checks that destructors are correctly invoked for the object returned by
57 // coawait.
a()58 coro2 a() {
59   reset();
60   {
61     auto x = co_await Bug{};
62     assert(alive == 1);
63     assert(ctor_called == 1);
64     assert(dtor_called == 0);
65     ((void)x);
66   }
67   assert(alive == 0);
68   assert(dtor_called == 1);
69 }
70 
b()71 coro2 b() {
72   reset();
73   {
74     (void)(co_await Bug{});
75     assert(ctor_called == 1);
76     assert(dtor_called == 1);
77     assert(alive == 0);
78   }
79   assert(ctor_called == 1);
80   assert(dtor_called == 1);
81   assert(alive == 0);
82 
83 }
84 
c()85 coro2 c() {
86   reset();
87   {
88     auto x = co_yield 42;
89     assert(alive == 1);
90     assert(ctor_called == 1);
91     assert(dtor_called == 0);
92   }
93   assert(alive == 0);
94   assert(ctor_called == 1);
95   assert(dtor_called == 1);
96 }
97 
d()98 coro2 d() {
99   reset();
100   {
101     (void)(co_yield 42);
102     assert(ctor_called == 1);
103     assert(dtor_called == 1);
104     assert(alive == 0);
105   }
106   assert(alive == 0);
107   assert(ctor_called == 1);
108   assert(dtor_called == 1);
109 }
110 
main(int,char **)111 int main(int, char**) {
112   a();
113   b();
114   c();
115   d();
116 
117   return 0;
118 }
119