annotate gcc/testsuite/g++.dg/coroutines/co-await-syntax-11.C @ 152:2b5abeee2509

update gcc11
author anatofuz
date Mon, 25 May 2020 07:50:57 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
152
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
1 // { dg-additional-options "-std=c++17 -w" }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
2
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
3 #include <utility>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
4 #include <type_traits>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
5 #include <tuple>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
6 #include <functional>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
7 #include <coroutine>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
8
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
9 struct any {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
10 template <typename T> any(T &&) noexcept;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
11 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
12
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
13 template <typename T>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
14 auto get_awaiter_impl(T &&value, int) noexcept
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
15 -> decltype(static_cast<T &&>(value).operator co_await()) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
16 return static_cast<T &&>(value).operator co_await();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
17 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
18 template <typename T, int = 0>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
19 T &&get_awaiter_impl(T &&value, any) noexcept;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
20 template <typename T>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
21 auto get_awaiter(T &&value) noexcept
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
22 -> decltype(get_awaiter_impl(static_cast<T &&>(value), 123)) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
23 return get_awaiter_impl(static_cast<T &&>(value), 123);
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
24 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
25
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
26 template <typename T, typename = void> struct awaitable_traits {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
27 using awaiter_t = decltype(get_awaiter(std::declval<T>()));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
28 using await_result_t = decltype(std::declval<awaiter_t>().await_resume());
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
29 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
30
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
31 template <typename TASK_CONTAINER> class when_all_ready_awaitable;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
32 template <typename... TASKS>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
33 class when_all_ready_awaitable<std::tuple<TASKS...>> {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
34 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
35 explicit when_all_ready_awaitable(std::tuple<TASKS...> &&tasks) noexcept
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
36 : m_tasks(std::move(tasks)) {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
37 auto operator co_await() &&noexcept {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
38 struct awaiter {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
39 awaiter(when_all_ready_awaitable &awaitable) noexcept
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
40 : m_awaitable(awaitable) {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
41 bool await_ready() const noexcept { return false; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
42 bool await_suspend() noexcept { return false; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
43 std::tuple<TASKS...> &&await_resume() noexcept {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
44 return std::move(m_awaitable.m_tasks);
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
45 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
46 when_all_ready_awaitable& m_awaitable;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
47 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
48 return awaiter{*this};
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
49 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
50 std::tuple<TASKS...> m_tasks;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
51 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
52
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
53 inline void *operator new(std::size_t, void *__p) noexcept;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
54
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
55 template <typename RESULT>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
56 class when_all_task_promise final{
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
57 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
58 using coroutine_handle_t = std::coroutine_handle<when_all_task_promise>;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
59 RESULT &&result() &&;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
60 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
61 template <typename RESULT> class when_all_task final {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
62 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
63 using promise_type = when_all_task_promise<RESULT>;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
64 using coroutine_handle_t = typename promise_type::coroutine_handle_t;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
65 decltype(auto) result() &;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
66 decltype(auto) result() && {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
67 return std::move(m_coroutine.promise()).result();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
68 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
69 decltype(auto) non_void_result() && {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
70 if constexpr (std::is_void_v<decltype(0)>)
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
71 ;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
72 else
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
73 return std::move(*this).result();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
74 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
75 coroutine_handle_t m_coroutine;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
76 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
77 class task;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
78 template <typename AWAITABLE,
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
79 typename RESULT =
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
80 typename awaitable_traits<AWAITABLE &&>::await_result_t,
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
81 std::enable_if_t<!std::is_void_v<RESULT>, int> = 0>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
82 when_all_task<RESULT> make_when_all_task(AWAITABLE awaitable);
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
83
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
84 template <typename... AWAITABLES>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
85 inline auto when_all_ready(AWAITABLES &&... awaitables) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
86 return when_all_ready_awaitable<
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
87 std::tuple<when_all_task<typename awaitable_traits<
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
88 std::remove_reference_t<AWAITABLES>>::await_result_t>...>>(
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
89 std::make_tuple(
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
90 make_when_all_task(std::forward<AWAITABLES>(awaitables))...));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
91 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
92
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
93 template <typename FUNC, typename AWAITABLE> class fmap_awaiter {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
94 using awaiter_t = typename awaitable_traits<AWAITABLE &&>::awaiter_t;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
95
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
96 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
97 fmap_awaiter(FUNC &&func, AWAITABLE &&awaitable) noexcept
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
98 : m_func(static_cast<FUNC &&>(func)),
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
99 m_awaiter(get_awaiter(static_cast<AWAITABLE &&>(awaitable))) {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
100 decltype(auto) await_ready() noexcept {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
101 return static_cast<awaiter_t &&>(m_awaiter).await_ready();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
102 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
103 template <typename PROMISE>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
104 decltype(auto) await_suspend(std::coroutine_handle<PROMISE> coro) noexcept {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
105 template <typename AWAIT_RESULT =
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
106 decltype(std::declval<awaiter_t>().await_resume()),
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
107 std::enable_if_t<!std::is_void_v<AWAIT_RESULT>, int> = 0>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
108 decltype(auto) await_resume() noexcept {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
109 return std::invoke(static_cast<FUNC &&>(m_func),
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
110 static_cast<awaiter_t &&>(m_awaiter).await_resume());
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
111 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
112
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
113 private:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
114 FUNC &&m_func;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
115 awaiter_t m_awaiter;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
116 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
117 template <typename FUNC, typename AWAITABLE> class fmap_awaitable {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
118 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
119 template <
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
120 typename FUNC_ARG, typename AWAITABLE_ARG,
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
121 std::enable_if_t<std::is_constructible_v<FUNC, FUNC_ARG &&> &&
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
122 std::is_constructible_v<AWAITABLE, AWAITABLE_ARG &&>,
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
123 int> = 0>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
124 explicit fmap_awaitable(FUNC_ARG &&func, AWAITABLE_ARG &&awaitable) noexcept
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
125 : m_func(static_cast<FUNC_ARG &&>(func)),
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
126 m_awaitable(static_cast<AWAITABLE_ARG &&>(awaitable)) {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
127 auto operator co_await() && {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
128 return fmap_awaiter(static_cast<FUNC &&>(m_func),
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
129 static_cast<AWAITABLE &&>(m_awaitable));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
130 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
131
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
132 private:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
133 FUNC m_func;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
134 AWAITABLE m_awaitable;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
135 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
136
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
137 template <typename FUNC, typename AWAITABLE>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
138 auto fmap(FUNC &&func, AWAITABLE &&awaitable) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
139 return fmap_awaitable<std::remove_cv_t<std::remove_reference_t<FUNC>>,
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
140 std::remove_cv_t<std::remove_reference_t<AWAITABLE>>>(
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
141 std::forward<FUNC>(func), std::forward<AWAITABLE>(awaitable));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
142 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
143 template <typename... AWAITABLES>
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
144 auto when_all(AWAITABLES &&... awaitables) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
145 return fmap(
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
146 [](auto &&taskTuple) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
147 decltype(auto) __trans_tmp_1 = std::apply(
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
148 [](auto &&... tasks) {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
149 return std::make_tuple(
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
150 static_cast<decltype(tasks)>(tasks).non_void_result()...);
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
151 },
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
152 static_cast<decltype(taskTuple)>(taskTuple));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
153 return __trans_tmp_1;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
154 },
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
155 when_all_ready(std::forward<AWAITABLES>(awaitables)...));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
156 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
157 class async_mutex_scoped_lock_operation;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
158 class async_mutex {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
159 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
160 async_mutex() noexcept;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
161 async_mutex_scoped_lock_operation scoped_lock_async() noexcept;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
162 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
163 class async_mutex_lock {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
164 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
165 explicit async_mutex_lock();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
166 ~async_mutex_lock();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
167
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
168 private:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
169 async_mutex *m_mutex;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
170 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
171 class async_mutex_scoped_lock_operation {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
172 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
173 async_mutex_lock await_resume() const noexcept;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
174 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
175 class task {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
176 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
177 class promise_type {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
178 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
179 auto initial_suspend() noexcept { return std::suspend_always{}; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
180 auto final_suspend() noexcept { return std::suspend_always{}; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
181 task get_return_object() noexcept { return task{}; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
182 void unhandled_exception() noexcept {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
183 void return_value(int value) noexcept { v = value; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
184 int result(){ return v; }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
185 int v = 0;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
186 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
187 public:
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
188 task() noexcept {}
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
189 auto operator co_await() const &noexcept {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
190 struct awaitable {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
191 std::coroutine_handle<promise_type> m_coroutine;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
192 decltype(auto) await_resume() {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
193 return this->m_coroutine.promise().result();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
194 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
195 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
196 return awaitable{};
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
197 }
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
198 };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
199 void foo() {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
200 (void) []() -> task {
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
201 auto makeTask = [](int x) -> task { co_return x; };
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
202 async_mutex_scoped_lock_operation op;
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
203 co_await when_all(std::move(op), makeTask(123));
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
204 }();
2b5abeee2509 update gcc11
anatofuz
parents:
diff changeset
205 }