blob: d58cedf414f8287217977613f9795a72a86481e3 [file] [log] [blame]
Brian Gesiakc1b173a2018-06-23 18:01:02 +00001// This file contains references to sections of the Coroutines TS, which can be
2// found at http://wg21.link/coroutines.
3
Eric Fiselier16269a82018-03-27 00:58:16 +00004// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result
Richard Smithcfd53b42015-10-22 06:13:50 +00005
Eric Fiseliera5465282016-09-29 21:47:39 +00006void no_coroutine_traits_bad_arg_await() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +00007 co_await a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +00008 // expected-error@-1 {{use of undeclared identifier 'a'}}
9}
10
11void no_coroutine_traits_bad_arg_yield() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000012 co_yield a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +000013 // expected-error@-1 {{use of undeclared identifier 'a'}}
14}
15
16
17void no_coroutine_traits_bad_arg_return() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000018 co_return a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +000019 // expected-error@-1 {{use of undeclared identifier 'a'}}
20}
21
Richard Smith9f690bd2015-10-27 06:02:45 +000022void no_coroutine_traits() {
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000023 co_await 4; // expected-error {{std::experimental::coroutine_traits type was not found; include <experimental/coroutine>}}
Richard Smith9f690bd2015-10-27 06:02:45 +000024}
25
26namespace std {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000027namespace experimental {
Eric Fiselier166c6e62017-07-10 01:27:22 +000028
29template <class... Args>
30struct void_t_imp {
31 using type = void;
32};
33template <class... Args>
34using void_t = typename void_t_imp<Args...>::type;
35
36template <class T, class = void>
37struct traits_sfinae_base {};
38
39template <class T>
40struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
41 using promise_type = typename T::promise_type;
42};
43
44template <class Ret, class... Args>
45struct coroutine_traits : public traits_sfinae_base<Ret> {};
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000046}} // namespace std::experimental
Richard Smith9f690bd2015-10-27 06:02:45 +000047
Richard Smith2af65c42015-11-24 02:34:39 +000048template<typename Promise> struct coro {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000049template <typename Promise, typename... Ps>
50struct std::experimental::coroutine_traits<coro<Promise>, Ps...> {
Richard Smith2af65c42015-11-24 02:34:39 +000051 using promise_type = Promise;
52};
53
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000054struct awaitable {
55 bool await_ready();
56 template <typename F> void await_suspend(F);
57 void await_resume();
58} a;
59
60struct suspend_always {
61 bool await_ready() { return false; }
62 template <typename F> void await_suspend(F);
63 void await_resume() {}
64};
65
66struct suspend_never {
67 bool await_ready() { return true; }
68 template <typename F> void await_suspend(F);
69 void await_resume() {}
70};
71
Gor Nishanovdb419a62017-09-05 19:31:52 +000072struct auto_await_suspend {
73 bool await_ready();
74 template <typename F> auto await_suspend(F) {}
75 void await_resume();
76};
77
Eric Fiselier166c6e62017-07-10 01:27:22 +000078struct DummyVoidTag {};
79DummyVoidTag no_specialization() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<DummyVoidTag>' has no member named 'promise_type'}}
80 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000081}
82
Gor Nishanov3e048bb2016-10-04 00:31:16 +000083template <typename... T>
84struct std::experimental::coroutine_traits<int, T...> {};
Richard Smith9f690bd2015-10-27 06:02:45 +000085
Eric Fiselier89bf0e72017-03-06 22:52:28 +000086int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
87 co_await a;
Richard Smith9b2f53e2015-11-19 02:36:35 +000088}
89
Gor Nishanov3e048bb2016-10-04 00:31:16 +000090template <>
91struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
Eric Fiselier89bf0e72017-03-06 22:52:28 +000092double bad_promise_type(double) { // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
93 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000094}
95
Gor Nishanov3e048bb2016-10-04 00:31:16 +000096template <>
97struct std::experimental::coroutine_traits<double, int> {
Richard Smith23da82c2015-11-20 22:40:06 +000098 struct promise_type {};
99};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000100double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}}
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000101 co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits<double, int>::promise_type'}}
Richard Smith23da82c2015-11-20 22:40:06 +0000102}
103
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000104struct promise; // expected-note {{forward declaration}}
Eric Fiselier98131312016-10-06 21:23:38 +0000105struct promise_void;
106struct void_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000107template <typename... T>
108struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
Eric Fiselier98131312016-10-06 21:23:38 +0000109template <typename... T>
110struct std::experimental::coroutine_traits<void, void_tag, T...>
111{ using promise_type = promise_void; };
Richard Smith9f690bd2015-10-27 06:02:45 +0000112
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000113// FIXME: This diagnostic is terrible.
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000114void undefined_promise() { // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits<void>::promise_type' (aka 'promise') is an incomplete type}}
Richard Smith9f690bd2015-10-27 06:02:45 +0000115 co_await a;
116}
117
Richard Smithae3d1472015-11-20 22:47:10 +0000118struct yielded_thing { const char *p; short a, b; };
Richard Smith23da82c2015-11-20 22:40:06 +0000119
Richard Smithd7bed4d2015-11-22 02:57:17 +0000120struct not_awaitable {};
121
Richard Smith23da82c2015-11-20 22:40:06 +0000122struct promise {
Richard Smith2af65c42015-11-24 02:34:39 +0000123 void get_return_object();
124 suspend_always initial_suspend();
125 suspend_always final_suspend();
Richard Smith71d403e2015-11-22 07:33:28 +0000126 awaitable yield_value(int); // expected-note 2{{candidate}}
127 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
128 not_awaitable yield_value(void()); // expected-note 2{{candidate}}
Richard Smith71d403e2015-11-22 07:33:28 +0000129 void return_value(int); // expected-note 2{{here}}
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000130 void unhandled_exception();
Richard Smith23da82c2015-11-20 22:40:06 +0000131};
132
Eric Fiselier98131312016-10-06 21:23:38 +0000133struct promise_void {
134 void get_return_object();
135 suspend_always initial_suspend();
136 suspend_always final_suspend();
Eric Fiselier98131312016-10-06 21:23:38 +0000137 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000138 void unhandled_exception();
Eric Fiselier98131312016-10-06 21:23:38 +0000139};
140
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000141void no_coroutine_handle() { // expected-error {{std::experimental::coroutine_handle type was not found; include <experimental/coroutine> before defining a coroutine}}
142 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
143 co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}}
144}
145
146namespace std {
147namespace experimental {
148template <class PromiseType = void>
149struct coroutine_handle {
150 static coroutine_handle from_address(void *);
151};
152template <>
153struct coroutine_handle<void> {
154 template <class PromiseType>
155 coroutine_handle(coroutine_handle<PromiseType>);
156 static coroutine_handle from_address(void *);
157};
158}} // namespace std::experimental
159
Richard Smith23da82c2015-11-20 22:40:06 +0000160void yield() {
161 co_yield 0;
Richard Smithae3d1472015-11-20 22:47:10 +0000162 co_yield {"foo", 1, 2};
Erich Keane7130a932018-05-07 20:52:56 +0000163 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{implicit conversion}} expected-warning {{braces around scalar}}
Richard Smithae3d1472015-11-20 22:47:10 +0000164 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
165 co_yield {"foo"};
Richard Smith23da82c2015-11-20 22:40:06 +0000166 co_yield "foo"; // expected-error {{no matching}}
Richard Smithd7bed4d2015-11-22 02:57:17 +0000167 co_yield 1.0;
168 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Richard Smith23da82c2015-11-20 22:40:06 +0000169}
Richard Smith9f690bd2015-10-27 06:02:45 +0000170
Gor Nishanovdb419a62017-09-05 19:31:52 +0000171void check_auto_await_suspend() {
172 co_await auto_await_suspend{}; // Should compile successfully.
173}
174
Richard Smith4ba66602015-11-22 07:05:16 +0000175void coreturn(int n) {
176 co_await a;
177 if (n == 0)
178 co_return 3;
179 if (n == 1)
Eric Fiselier98131312016-10-06 21:23:38 +0000180 co_return {4}; // expected-warning {{braces around scalar initializer}}
Richard Smith4ba66602015-11-22 07:05:16 +0000181 if (n == 2)
182 co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}}
Eric Fiselier98131312016-10-06 21:23:38 +0000183 co_return 42;
Richard Smith4ba66602015-11-22 07:05:16 +0000184}
185
Eric Fiselier8d409e82017-03-09 05:01:31 +0000186template <class T>
187void co_await_non_dependent_arg(T) {
188 co_await a;
189}
190template void co_await_non_dependent_arg(int);
191
Richard Smithcfd53b42015-10-22 06:13:50 +0000192void mixed_yield() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000193 co_yield 0; // expected-note {{use of 'co_yield'}}
194 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000195}
196
Eric Fiseliercac0a592017-03-11 02:35:37 +0000197void mixed_yield_invalid() {
198 co_yield blah; // expected-error {{use of undeclared identifier}}
199 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
200 return; // expected-error {{return statement not allowed in coroutine}}
201}
202
203template <class T>
204void mixed_yield_template(T) {
205 co_yield blah; // expected-error {{use of undeclared identifier}}
206 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
207 return; // expected-error {{return statement not allowed in coroutine}}
208}
209
210template <class T>
211void mixed_yield_template2(T) {
212 co_yield 42;
213 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
214 return; // expected-error {{return statement not allowed in coroutine}}
215}
216
217template <class T>
218void mixed_yield_template3(T v) {
219 co_yield blah(v);
220 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
221 return; // expected-error {{return statement not allowed in coroutine}}
222}
223
Richard Smithcfd53b42015-10-22 06:13:50 +0000224void mixed_await() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000225 co_await a; // expected-note {{use of 'co_await'}}
226 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000227}
228
Eric Fiseliercac0a592017-03-11 02:35:37 +0000229void mixed_await_invalid() {
230 co_await 42; // expected-error {{'int' is not a structure or union}}
231 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
232 return; // expected-error {{not allowed in coroutine}}
233}
234
235template <class T>
236void mixed_await_template(T) {
237 co_await 42;
238 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
239 return; // expected-error {{not allowed in coroutine}}
240}
241
242template <class T>
243void mixed_await_template2(T v) {
244 co_await v; // expected-error {{'long' is not a structure or union}}
245 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
246 return; // expected-error {{not allowed in coroutine}}
247}
248template void mixed_await_template2(long); // expected-note {{requested here}}
249
Eric Fiselier98131312016-10-06 21:23:38 +0000250void only_coreturn(void_tag) {
Gor Nishanovd97f6bf2017-01-10 00:08:31 +0000251 co_return; // OK
Richard Smithcfd53b42015-10-22 06:13:50 +0000252}
253
Eric Fiselier98131312016-10-06 21:23:38 +0000254void mixed_coreturn(void_tag, bool b) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000255 if (b)
Richard Smith9f690bd2015-10-27 06:02:45 +0000256 co_return; // expected-note {{use of 'co_return'}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000257 else
Richard Smith9f690bd2015-10-27 06:02:45 +0000258 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000259}
260
Eric Fiseliercac0a592017-03-11 02:35:37 +0000261void mixed_coreturn_invalid(bool b) {
262 if (b)
263 co_return; // expected-note {{use of 'co_return'}}
264 // expected-error@-1 {{no member named 'return_void' in 'promise'}}
265 else
266 return; // expected-error {{not allowed in coroutine}}
267}
268
269template <class T>
270void mixed_coreturn_template(void_tag, bool b, T v) {
271 if (b)
272 co_return v; // expected-note {{use of 'co_return'}}
273 // expected-error@-1 {{no member named 'return_value' in 'promise_void'}}
274 else
275 return; // expected-error {{not allowed in coroutine}}
276}
277template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}}
278
279template <class T>
280void mixed_coreturn_template2(bool b, T) {
281 if (b)
282 co_return v; // expected-note {{use of 'co_return'}}
283 // expected-error@-1 {{use of undeclared identifier 'v'}}
284 else
285 return; // expected-error {{not allowed in coroutine}}
286}
287
Richard Smithcfd53b42015-10-22 06:13:50 +0000288struct CtorDtor {
289 CtorDtor() {
290 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
291 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000292 CtorDtor(awaitable a) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000293 // The spec doesn't say this is ill-formed, but it must be.
Richard Smith9f690bd2015-10-27 06:02:45 +0000294 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000295 }
296 ~CtorDtor() {
297 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
298 }
299 // FIXME: The spec says this is ill-formed.
300 void operator=(CtorDtor&) {
Eric Fiselierc8efda72016-10-27 18:43:28 +0000301 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
302 }
303 void operator=(CtorDtor const &) {
304 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
305 }
306 void operator=(CtorDtor &&) {
307 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
308 }
309 void operator=(CtorDtor const &&) {
310 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
311 }
312 void operator=(int) {
313 co_await a; // OK. Not a special member
Richard Smithcfd53b42015-10-22 06:13:50 +0000314 }
315};
316
Richard Smith744b2242015-11-20 02:54:01 +0000317void unevaluated() {
318 decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
319 sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
320 typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
321 decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
322 sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
323 typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
324}
325
Brian Gesiakc1b173a2018-06-23 18:01:02 +0000326// [expr.await]p2: "An await-expression shall not appear in a default argument."
327// FIXME: A better diagnostic would explicitly state that default arguments are
328// not allowed. A user may not understand that this is "outside a function."
329void default_argument(int arg = co_await 0) {} // expected-error {{'co_await' cannot be used outside a function}}
330
Eric Fiselierc8efda72016-10-27 18:43:28 +0000331constexpr auto constexpr_deduced_return_coroutine() {
Richard Smith744b2242015-11-20 02:54:01 +0000332 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
Eric Fiselierc8efda72016-10-27 18:43:28 +0000333 // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000334}
335
336void varargs_coroutine(const char *, ...) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000337 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
338}
339
Eric Fiselierc8efda72016-10-27 18:43:28 +0000340auto deduced_return_coroutine() {
341 co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
342}
343
Richard Smith9f690bd2015-10-27 06:02:45 +0000344struct outer {};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000345struct await_arg_1 {};
346struct await_arg_2 {};
347
348namespace adl_ns {
349struct coawait_arg_type {};
350awaitable operator co_await(coawait_arg_type);
351}
Richard Smith9f690bd2015-10-27 06:02:45 +0000352
353namespace dependent_operator_co_await_lookup {
354 template<typename T> void await_template(T t) {
355 // no unqualified lookup results
356 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
357 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
358 };
359 template void await_template(awaitable);
360
361 struct indirectly_awaitable { indirectly_awaitable(outer); };
362 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
363 template void await_template(indirectly_awaitable);
364
365 struct not_awaitable {};
366 template void await_template(not_awaitable); // expected-note {{instantiation}}
367
368 template<typename T> void await_template_2(T t) {
369 // one unqualified lookup result
370 co_await t;
371 };
372 template void await_template(outer); // expected-note {{instantiation}}
373 template void await_template_2(outer);
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000374
375 struct transform_awaitable {};
376 struct transformed {};
377
378 struct transform_promise {
379 typedef transform_awaitable await_arg;
380 coro<transform_promise> get_return_object();
381 transformed initial_suspend();
382 ::adl_ns::coawait_arg_type final_suspend();
383 transformed await_transform(transform_awaitable);
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000384 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000385 void return_void();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000386 };
387 template <class AwaitArg>
388 struct basic_promise {
389 typedef AwaitArg await_arg;
390 coro<basic_promise> get_return_object();
391 awaitable initial_suspend();
392 awaitable final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000393 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000394 void return_void();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000395 };
396
397 awaitable operator co_await(await_arg_1);
398
399 template <typename T, typename U>
400 coro<T> await_template_3(U t) {
401 co_await t;
402 }
403
404 template coro<basic_promise<await_arg_1>> await_template_3<basic_promise<await_arg_1>>(await_arg_1);
405
406 template <class T, int I = 0>
407 struct dependent_member {
408 coro<T> mem_fn() const {
409 co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}}
410 }
411 template <class U>
412 coro<T> dep_mem_fn(U t) {
413 co_await t;
414 }
415 };
416
417 template <>
418 struct dependent_member<long> {
419 // FIXME this diagnostic is terrible
420 coro<transform_promise> mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
421 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
422 // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
423 co_await transform_awaitable{};
424 // expected-error@-1 {{no member named 'await_ready'}}
425 }
426 template <class R, class U>
427 coro<R> dep_mem_fn(U u) { co_await u; }
428 };
429
430 awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}}
431
432 template struct dependent_member<basic_promise<await_arg_1>, 0>;
433 template struct dependent_member<basic_promise<await_arg_2>, 0>; // expected-note {{in instantiation}}
434
435 template <>
436 coro<transform_promise>
437 // FIXME this diagnostic is terrible
438 dependent_member<long>::dep_mem_fn<transform_promise>(int) { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
439 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
440 //expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
441 co_await transform_awaitable{};
442 // expected-error@-1 {{no member named 'await_ready'}}
443 }
444
445 void operator co_await(transform_awaitable) = delete;
446 awaitable operator co_await(transformed);
447
448 template coro<transform_promise>
449 dependent_member<long>::dep_mem_fn<transform_promise>(transform_awaitable);
450
451 template <>
452 coro<transform_promise> dependent_member<long>::dep_mem_fn<transform_promise>(long) {
453 co_await transform_awaitable{};
454 }
455
456 template <>
457 struct dependent_member<int> {
458 coro<transform_promise> mem_fn() const {
459 co_await transform_awaitable{};
460 }
461 };
462
463 template coro<transform_promise> await_template_3<transform_promise>(transform_awaitable);
464 template struct dependent_member<transform_promise>;
465 template coro<transform_promise> dependent_member<transform_promise>::dep_mem_fn(transform_awaitable);
Richard Smithcfd53b42015-10-22 06:13:50 +0000466}
Richard Smith10610f72015-11-20 22:57:24 +0000467
Richard Smith71d403e2015-11-22 07:33:28 +0000468struct yield_fn_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000469template <>
470struct std::experimental::coroutine_traits<void, yield_fn_tag> {
Richard Smith71d403e2015-11-22 07:33:28 +0000471 struct promise_type {
472 // FIXME: add an await_transform overload for functions
473 awaitable yield_value(int());
474 void return_value(int());
Richard Smith2af65c42015-11-24 02:34:39 +0000475
476 suspend_never initial_suspend();
477 suspend_never final_suspend();
478 void get_return_object();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000479 void unhandled_exception();
Richard Smith71d403e2015-11-22 07:33:28 +0000480 };
481};
482
Richard Smith10610f72015-11-20 22:57:24 +0000483namespace placeholder {
Richard Smith71d403e2015-11-22 07:33:28 +0000484 awaitable f(), f(int); // expected-note 4{{possible target}}
485 int g(), g(int); // expected-note 2{{candidate}}
Richard Smith10610f72015-11-20 22:57:24 +0000486 void x() {
487 co_await f; // expected-error {{reference to overloaded function}}
488 }
489 void y() {
Richard Smith71d403e2015-11-22 07:33:28 +0000490 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
Richard Smith10610f72015-11-20 22:57:24 +0000491 }
492 void z() {
493 co_await a;
Richard Smith71d403e2015-11-22 07:33:28 +0000494 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
495 }
496
497 void x(yield_fn_tag) {
498 co_await f; // expected-error {{reference to overloaded function}}
499 }
500 void y(yield_fn_tag) {
501 co_yield g;
502 }
503 void z(yield_fn_tag) {
504 co_await a;
505 co_return g;
Richard Smith10610f72015-11-20 22:57:24 +0000506 }
507}
Richard Smith2af65c42015-11-24 02:34:39 +0000508
509struct bad_promise_1 {
510 suspend_always initial_suspend();
511 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000512 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000513 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000514};
515coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
516 co_await a;
517}
518
519struct bad_promise_2 {
520 coro<bad_promise_2> get_return_object();
Gor Nishanovd4507262018-03-27 20:38:19 +0000521 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000522 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000523 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000524};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000525// FIXME: This shouldn't happen twice
Richard Smith2af65c42015-11-24 02:34:39 +0000526coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
527 co_await a;
528}
529
530struct bad_promise_3 {
531 coro<bad_promise_3> get_return_object();
Gor Nishanovd4507262018-03-27 20:38:19 +0000532 suspend_always initial_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000533 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000534 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000535};
536coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
537 co_await a;
538}
539
540struct bad_promise_4 {
541 coro<bad_promise_4> get_return_object();
542 not_awaitable initial_suspend();
543 suspend_always final_suspend();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000544 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000545};
546// FIXME: This diagnostic is terrible.
547coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000548 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
549 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000550}
551
552struct bad_promise_5 {
553 coro<bad_promise_5> get_return_object();
554 suspend_always initial_suspend();
555 not_awaitable final_suspend();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000556 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000557};
558// FIXME: This diagnostic is terrible.
559coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000560 // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}}
561 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000562}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000563
Eric Fiselier709d1b32016-10-27 07:30:31 +0000564struct bad_promise_6 {
565 coro<bad_promise_6> get_return_object();
566 suspend_always initial_suspend();
567 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000568 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000569 void return_void(); // expected-note 2 {{member 'return_void' first declared here}}
570 void return_value(int) const; // expected-note 2 {{member 'return_value' first declared here}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000571 void return_value(int);
572};
573coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
574 co_await a;
575}
576
Eric Fiselierbee782b2017-04-03 19:21:00 +0000577template <class T>
578coro<T> bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
579 co_await a;
580}
581template coro<bad_promise_6> bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}}
582
Gor Nishanov29ff6382017-05-24 14:34:19 +0000583struct bad_promise_7 { // expected-note 2 {{defined here}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000584 coro<bad_promise_7> get_return_object();
585 suspend_always initial_suspend();
586 suspend_always final_suspend();
587 void return_void();
Eric Fiselier709d1b32016-10-27 07:30:31 +0000588};
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000589coro<bad_promise_7> no_unhandled_exception() { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000590 co_await a;
591}
592
Eric Fiselierbee782b2017-04-03 19:21:00 +0000593template <class T>
594coro<T> no_unhandled_exception_dependent(T) { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}}
595 co_await a;
596}
597template coro<bad_promise_7> no_unhandled_exception_dependent(bad_promise_7); // expected-note {{in instantiation}}
598
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000599struct bad_promise_base {
600private:
601 void return_void();
602};
603struct bad_promise_8 : bad_promise_base {
Eric Fiselier709d1b32016-10-27 07:30:31 +0000604 coro<bad_promise_8> get_return_object();
605 suspend_always initial_suspend();
606 suspend_always final_suspend();
Eric Fiselierbee782b2017-04-03 19:21:00 +0000607 void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{made unavailable}}
608 void unhandled_exception() const; // expected-note 2 {{candidate}}
609 void unhandled_exception(void *) const; // expected-note 2 {{requires 1 argument, but 0 were provided}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000610};
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000611coro<bad_promise_8> calls_unhandled_exception() {
612 // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000613 // FIXME: also warn about private 'return_void' here. Even though building
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000614 // the call to unhandled_exception has already failed.
Eric Fiselier709d1b32016-10-27 07:30:31 +0000615 co_await a;
616}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000617
Eric Fiselierbee782b2017-04-03 19:21:00 +0000618template <class T>
619coro<T> calls_unhandled_exception_dependent(T) {
620 // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}}
621 co_await a;
622}
623template coro<bad_promise_8> calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}}
624
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000625struct bad_promise_9 {
626 coro<bad_promise_9> get_return_object();
627 suspend_always initial_suspend();
628 suspend_always final_suspend();
629 void await_transform(void *); // expected-note {{candidate}}
630 awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
631 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000632 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000633};
634coro<bad_promise_9> calls_await_transform() {
635 co_await 42; // expected-error {{call to unavailable member function 'await_transform'}}
636 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
637}
638
639struct bad_promise_10 {
640 coro<bad_promise_10> get_return_object();
641 suspend_always initial_suspend();
642 suspend_always final_suspend();
643 int await_transform;
644 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000645 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000646};
647coro<bad_promise_10> bad_coawait() {
648 // FIXME this diagnostic is terrible
649 co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}}
650 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
651}
652
653struct call_operator {
654 template <class... Args>
655 awaitable operator()(Args...) const { return a; }
656};
657void ret_void();
658struct good_promise_1 {
659 coro<good_promise_1> get_return_object();
660 suspend_always initial_suspend();
661 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000662 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000663 static const call_operator await_transform;
664 using Fn = void (*)();
665 Fn return_void = ret_void;
666};
667const call_operator good_promise_1::await_transform;
668coro<good_promise_1> ok_static_coawait() {
669 // FIXME this diagnostic is terrible
670 co_await 42;
671}
672
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000673template<> struct std::experimental::coroutine_traits<int, int, const char**>
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000674{ using promise_type = promise; };
675
Eric Fiselierc8efda72016-10-27 18:43:28 +0000676int main(int, const char**) {
677 co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000678}
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000679
680struct good_promise_2 {
681 float get_return_object();
682 suspend_always initial_suspend();
683 suspend_always final_suspend();
684 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000685 void unhandled_exception();
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000686};
687template<> struct std::experimental::coroutine_handle<good_promise_2> {};
688
689template<> struct std::experimental::coroutine_traits<float>
690{ using promise_type = good_promise_2; };
691
692float badly_specialized_coro_handle() { // expected-error {{std::experimental::coroutine_handle missing a member named 'from_address'}}
693 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
694 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
695}
Gor Nishanov3aa9eb32017-03-27 23:36:59 +0000696
Eric Fiselierf692e7d2017-04-18 03:12:48 +0000697namespace std {
698 struct nothrow_t {};
699 constexpr nothrow_t nothrow = {};
700}
701
702using SizeT = decltype(sizeof(int));
703
704void* operator new(SizeT __sz, const std::nothrow_t&) noexcept;
705void operator delete(void* __p, const std::nothrow_t&) noexcept;
706
707
708
Gor Nishanov3aa9eb32017-03-27 23:36:59 +0000709struct promise_on_alloc_failure_tag {};
710
711template<>
712struct std::experimental::coroutine_traits<int, promise_on_alloc_failure_tag> {
713 struct promise_type {
714 int get_return_object() {}
715 suspend_always initial_suspend() { return {}; }
716 suspend_always final_suspend() { return {}; }
717 void return_void() {}
718 int get_return_object_on_allocation_failure(); // expected-error{{'promise_type': 'get_return_object_on_allocation_failure()' must be a static member function}}
719 void unhandled_exception();
720 };
721};
722
723extern "C" int f(promise_on_alloc_failure_tag) {
724 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
725}
Eric Fiselierbee782b2017-04-03 19:21:00 +0000726
727struct bad_promise_11 {
728 coro<bad_promise_11> get_return_object();
729 suspend_always initial_suspend();
730 suspend_always final_suspend();
731 void unhandled_exception();
732 void return_void();
733
734private:
735 static coro<bad_promise_11> get_return_object_on_allocation_failure(); // expected-note 2 {{declared private here}}
736};
737coro<bad_promise_11> private_alloc_failure_handler() {
738 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
739 co_return; // FIXME: Add a "declared coroutine here" note.
740}
741
742template <class T>
743coro<T> dependent_private_alloc_failure_handler(T) {
744 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
745 co_return; // FIXME: Add a "declared coroutine here" note.
746}
747template coro<bad_promise_11> dependent_private_alloc_failure_handler(bad_promise_11);
748// expected-note@-1 {{requested here}}
Eric Fiselierf692e7d2017-04-18 03:12:48 +0000749
750struct bad_promise_12 {
751 coro<bad_promise_12> get_return_object();
752 suspend_always initial_suspend();
753 suspend_always final_suspend();
754 void unhandled_exception();
755 void return_void();
756 static coro<bad_promise_12> get_return_object_on_allocation_failure();
757
758 static void* operator new(SizeT);
759 // expected-error@-1 2 {{'operator new' is required to have a non-throwing noexcept specification when the promise type declares 'get_return_object_on_allocation_failure()'}}
760};
761coro<bad_promise_12> throwing_in_class_new() { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
762 co_return;
763}
764
765template <class T>
766coro<T> dependent_throwing_in_class_new(T) { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
767 co_return;
768}
769template coro<bad_promise_12> dependent_throwing_in_class_new(bad_promise_12); // expected-note {{requested here}}
770
771
772struct good_promise_13 {
773 coro<good_promise_13> get_return_object();
774 suspend_always initial_suspend();
775 suspend_always final_suspend();
776 void unhandled_exception();
777 void return_void();
778 static coro<good_promise_13> get_return_object_on_allocation_failure();
779};
780coro<good_promise_13> uses_nothrow_new() {
781 co_return;
782}
783
784template <class T>
785coro<T> dependent_uses_nothrow_new(T) {
786 co_return;
787}
788template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13);
Gor Nishanov6a470682017-05-22 20:22:23 +0000789
Brian Gesiak98606222018-02-15 20:37:22 +0000790struct good_promise_custom_new_operator {
791 coro<good_promise_custom_new_operator> get_return_object();
792 suspend_always initial_suspend();
793 suspend_always final_suspend();
794 void return_void();
795 void unhandled_exception();
Brian Gesiak521b13b2018-02-16 14:11:27 +0000796 void *operator new(SizeT, double, float, int);
Brian Gesiak98606222018-02-15 20:37:22 +0000797};
798
799coro<good_promise_custom_new_operator>
800good_coroutine_calls_custom_new_operator(double, float, int) {
801 co_return;
802}
803
804struct coroutine_nonstatic_member_struct;
805
806struct good_promise_nonstatic_member_custom_new_operator {
807 coro<good_promise_nonstatic_member_custom_new_operator> get_return_object();
808 suspend_always initial_suspend();
809 suspend_always final_suspend();
810 void return_void();
811 void unhandled_exception();
Brian Gesiak521b13b2018-02-16 14:11:27 +0000812 void *operator new(SizeT, coroutine_nonstatic_member_struct &, double);
Brian Gesiak98606222018-02-15 20:37:22 +0000813};
814
Brian Gesiak98606222018-02-15 20:37:22 +0000815struct good_promise_noexcept_custom_new_operator {
816 static coro<good_promise_noexcept_custom_new_operator> get_return_object_on_allocation_failure();
817 coro<good_promise_noexcept_custom_new_operator> get_return_object();
818 suspend_always initial_suspend();
819 suspend_always final_suspend();
820 void return_void();
821 void unhandled_exception();
Brian Gesiak521b13b2018-02-16 14:11:27 +0000822 void *operator new(SizeT, double, float, int) noexcept;
Brian Gesiak98606222018-02-15 20:37:22 +0000823};
824
825coro<good_promise_noexcept_custom_new_operator>
826good_coroutine_calls_noexcept_custom_new_operator(double, float, int) {
827 co_return;
828}
829
Gor Nishanov6a470682017-05-22 20:22:23 +0000830struct mismatch_gro_type_tag1 {};
831template<>
832struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> {
833 struct promise_type {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000834 void get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000835 suspend_always initial_suspend() { return {}; }
836 suspend_always final_suspend() { return {}; }
837 void return_void() {}
838 void unhandled_exception();
839 };
840};
841
Gor Nishanov07ac63f2018-05-28 18:08:47 +0000842extern "C" int f(mismatch_gro_type_tag1) {
Gor Nishanov6a470682017-05-22 20:22:23 +0000843 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
844 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
845}
846
847struct mismatch_gro_type_tag2 {};
848template<>
849struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> {
850 struct promise_type {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000851 void *get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000852 suspend_always initial_suspend() { return {}; }
853 suspend_always final_suspend() { return {}; }
854 void return_void() {}
855 void unhandled_exception();
856 };
857};
858
Gor Nishanov07ac63f2018-05-28 18:08:47 +0000859extern "C" int f(mismatch_gro_type_tag2) {
Gor Nishanov6a470682017-05-22 20:22:23 +0000860 // expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
861 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
862}
863
864struct mismatch_gro_type_tag3 {};
865template<>
866struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag3> {
867 struct promise_type {
868 int get_return_object() {}
Eric Fiselierfc50f622017-05-25 14:59:39 +0000869 static void get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000870 suspend_always initial_suspend() { return {}; }
871 suspend_always final_suspend() { return {}; }
872 void return_void() {}
873 void unhandled_exception();
874 };
875};
876
Gor Nishanov07ac63f2018-05-28 18:08:47 +0000877extern "C" int f(mismatch_gro_type_tag3) {
Gor Nishanov6a470682017-05-22 20:22:23 +0000878 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
879 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
880}
881
882
883struct mismatch_gro_type_tag4 {};
884template<>
885struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag4> {
886 struct promise_type {
887 int get_return_object() {}
Eric Fiselierfc50f622017-05-25 14:59:39 +0000888 static char *get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000889 suspend_always initial_suspend() { return {}; }
890 suspend_always final_suspend() { return {}; }
891 void return_void() {}
892 void unhandled_exception();
893 };
894};
895
Gor Nishanov07ac63f2018-05-28 18:08:47 +0000896extern "C" int f(mismatch_gro_type_tag4) {
Gor Nishanov6a470682017-05-22 20:22:23 +0000897 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}}
898 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
899}
900
Eric Fiselierfc50f622017-05-25 14:59:39 +0000901struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000902 coro<bad_promise_no_return_func> get_return_object();
903 suspend_always initial_suspend();
904 suspend_always final_suspend();
905 void unhandled_exception();
906};
Eric Fiselierfc50f622017-05-25 14:59:39 +0000907// FIXME: The PDTS currently specifies this as UB, technically forbidding a
908// diagnostic.
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000909coro<bad_promise_no_return_func> no_return_value_or_return_void() {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000910 // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000911 co_await a;
912}
Eric Fiselierd978e532017-05-28 18:21:12 +0000913
914struct bad_await_suspend_return {
915 bool await_ready();
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000916 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Eric Fiselierd978e532017-05-28 18:21:12 +0000917 char await_suspend(std::experimental::coroutine_handle<>);
918 void await_resume();
919};
920struct bad_await_ready_return {
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000921 // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}}
Eric Fiselierd978e532017-05-28 18:21:12 +0000922 void await_ready();
923 bool await_suspend(std::experimental::coroutine_handle<>);
924 void await_resume();
925};
926struct await_ready_explicit_bool {
927 struct BoolT {
928 explicit operator bool() const;
929 };
930 BoolT await_ready();
931 void await_suspend(std::experimental::coroutine_handle<>);
932 void await_resume();
933};
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000934template <class SuspendTy>
935struct await_suspend_type_test {
936 bool await_ready();
937 // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}}
938 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}}
939 SuspendTy await_suspend(std::experimental::coroutine_handle<>);
940 void await_resume();
941};
Eric Fiselierd978e532017-05-28 18:21:12 +0000942void test_bad_suspend() {
943 {
944 // FIXME: The actual error emitted here is terrible, and no number of notes can save it.
945 bad_await_ready_return a;
946 // expected-error@+1 {{value of type 'void' is not contextually convertible to 'bool'}}
947 co_await a; // expected-note {{call to 'await_ready' implicitly required by coroutine function here}}
948 }
949 {
950 bad_await_suspend_return b;
951 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
952 }
953 {
954 await_ready_explicit_bool c;
955 co_await c; // OK
956 }
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000957 {
958 await_suspend_type_test<bool &&> a;
959 await_suspend_type_test<bool &> b;
960 await_suspend_type_test<const void> c;
961 await_suspend_type_test<const volatile bool> d;
962 co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
963 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
964 co_await c; // OK
965 co_await d; // OK
966 }
Eric Fiselierd978e532017-05-28 18:21:12 +0000967}
Eric Fiselierde7943b2017-06-03 00:22:18 +0000968
969template <int ID = 0>
970struct NoCopy {
971 NoCopy(NoCopy const&) = delete; // expected-note 2 {{deleted here}}
972};
973template <class T, class U>
974void test_dependent_param(T t, U) {
975 // expected-error@-1 {{call to deleted constructor of 'NoCopy<0>'}}
976 // expected-error@-2 {{call to deleted constructor of 'NoCopy<1>'}}
977 ((void)t);
978 co_return 42;
979}
980template void test_dependent_param(NoCopy<0>, NoCopy<1>); // expected-note {{requested here}}
Eric Fiselier166c6e62017-07-10 01:27:22 +0000981
982namespace CoroHandleMemberFunctionTest {
983struct CoroMemberTag {};
984struct BadCoroMemberTag {};
985
986template <class T, class U>
987constexpr bool IsSameV = false;
988template <class T>
989constexpr bool IsSameV<T, T> = true;
990
991template <class T>
992struct TypeTest {
993 template <class U>
994 static constexpr bool IsSame = IsSameV<T, U>;
995
996 template <class... Args>
997 static constexpr bool MatchesArgs = IsSameV<T,
998 std::experimental::coroutine_traits<CoroMemberTag, Args...>>;
999};
1000
1001template <class T>
1002struct AwaitReturnsType {
1003 bool await_ready() const;
1004 void await_suspend(...) const;
1005 T await_resume() const;
1006};
1007
1008template <class... CoroTraitsArgs>
1009struct CoroMemberPromise {
1010 using TraitsT = std::experimental::coroutine_traits<CoroTraitsArgs...>;
1011 using TypeTestT = TypeTest<TraitsT>;
1012 using AwaitTestT = AwaitReturnsType<TypeTestT>;
1013
1014 CoroMemberTag get_return_object();
1015 suspend_always initial_suspend();
1016 suspend_always final_suspend();
1017
1018 AwaitTestT yield_value(int);
1019
1020 void return_void();
1021 void unhandled_exception();
1022};
1023
1024} // namespace CoroHandleMemberFunctionTest
1025
1026template <class... Args>
1027struct ::std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::CoroMemberTag, Args...> {
1028 using promise_type = CoroHandleMemberFunctionTest::CoroMemberPromise<CoroHandleMemberFunctionTest::CoroMemberTag, Args...>;
1029};
1030
1031namespace CoroHandleMemberFunctionTest {
1032struct TestType {
1033
1034 CoroMemberTag test_qual() {
1035 auto TC = co_yield 0;
1036 static_assert(TC.MatchesArgs<TestType &>, "");
1037 static_assert(!TC.MatchesArgs<TestType>, "");
1038 static_assert(!TC.MatchesArgs<TestType *>, "");
1039 }
1040
1041 CoroMemberTag test_sanity(int *) const {
1042 auto TC = co_yield 0;
1043 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static_assert failed}}
1044 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static_assert failed}}
1045 static_assert(TC.MatchesArgs<const TestType &, int *>, "");
1046 }
1047
1048 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1049 auto TC = co_yield 0;
1050 static_assert(TC.MatchesArgs<const TestType &, int *, const float &&, volatile void *volatile>, "");
1051 }
1052
1053 CoroMemberTag test_qual() const volatile {
1054 auto TC = co_yield 0;
1055 static_assert(TC.MatchesArgs<const volatile TestType &>, "");
1056 }
1057
1058 CoroMemberTag test_ref_qual() & {
1059 auto TC = co_yield 0;
1060 static_assert(TC.MatchesArgs<TestType &>, "");
1061 }
1062 CoroMemberTag test_ref_qual() const & {
1063 auto TC = co_yield 0;
1064 static_assert(TC.MatchesArgs<TestType const &>, "");
1065 }
1066 CoroMemberTag test_ref_qual() && {
1067 auto TC = co_yield 0;
1068 static_assert(TC.MatchesArgs<TestType &&>, "");
1069 }
1070 CoroMemberTag test_ref_qual(const char *&) const volatile && {
1071 auto TC = co_yield 0;
1072 static_assert(TC.MatchesArgs<TestType const volatile &&, const char *&>, "");
1073 }
1074
1075 CoroMemberTag test_args(int) {
1076 auto TC = co_yield 0;
1077 static_assert(TC.MatchesArgs<TestType &, int>, "");
1078 }
1079 CoroMemberTag test_args(int, long &, void *) const {
1080 auto TC = co_yield 0;
1081 static_assert(TC.MatchesArgs<TestType const &, int, long &, void *>, "");
1082 }
1083
1084 template <class... Args>
1085 CoroMemberTag test_member_template(Args...) const && {
1086 auto TC = co_yield 0;
1087 static_assert(TC.template MatchesArgs<TestType const &&, Args...>, "");
1088 }
1089
1090 static CoroMemberTag test_static() {
1091 auto TC = co_yield 0;
1092 static_assert(TC.MatchesArgs<>, "");
1093 static_assert(!TC.MatchesArgs<TestType>, "");
1094 static_assert(!TC.MatchesArgs<TestType &>, "");
1095 static_assert(!TC.MatchesArgs<TestType *>, "");
1096 }
1097
1098 static CoroMemberTag test_static(volatile void *const, char &&) {
1099 auto TC = co_yield 0;
1100 static_assert(TC.MatchesArgs<volatile void *const, char &&>, "");
1101 }
1102
1103 template <class Dummy>
1104 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1105 auto TC = co_yield 0;
1106 using TCT = decltype(TC);
1107 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1108 static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
1109 }
1110
1111 BadCoroMemberTag test_diagnostics() {
1112 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, CoroHandleMemberFunctionTest::TestType &>' has no member named 'promise_type'}}
1113 co_return;
1114 }
1115 BadCoroMemberTag test_diagnostics(int) const && {
1116 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, const CoroHandleMemberFunctionTest::TestType &&, int>' has no member named 'promise_type'}}
1117 co_return;
1118 }
1119
1120 static BadCoroMemberTag test_static_diagnostics(long *) {
1121 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, long *>' has no member named 'promise_type'}}
1122 co_return;
1123 }
1124};
1125
1126template CoroMemberTag TestType::test_member_template(long, const char *) const &&;
1127template CoroMemberTag TestType::test_static_template<void>(const char *volatile &, unsigned);
1128
1129template <class... Args>
1130struct DepTestType {
1131
1132 CoroMemberTag test_sanity(int *) const {
1133 auto TC = co_yield 0;
1134 static_assert(TC.template MatchesArgs<const DepTestType &>, ""); // expected-error {{static_assert failed}}
1135 static_assert(TC.template MatchesArgs<>, ""); // expected-error {{static_assert failed}}
1136 static_assert(TC.template MatchesArgs<const DepTestType &, int *>, "");
1137 }
1138
1139 CoroMemberTag test_qual() {
1140 auto TC = co_yield 0;
1141 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1142 static_assert(!TC.template MatchesArgs<DepTestType>, "");
1143 static_assert(!TC.template MatchesArgs<DepTestType *>, "");
1144 }
1145
1146 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1147 auto TC = co_yield 0;
1148 static_assert(TC.template MatchesArgs<const DepTestType &, int *, const float &&, volatile void *volatile>, "");
1149 }
1150
1151 CoroMemberTag test_qual() const volatile {
1152 auto TC = co_yield 0;
1153 static_assert(TC.template MatchesArgs<const volatile DepTestType &>, "");
1154 }
1155
1156 CoroMemberTag test_ref_qual() & {
1157 auto TC = co_yield 0;
1158 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1159 }
1160 CoroMemberTag test_ref_qual() const & {
1161 auto TC = co_yield 0;
1162 static_assert(TC.template MatchesArgs<DepTestType const &>, "");
1163 }
1164 CoroMemberTag test_ref_qual() && {
1165 auto TC = co_yield 0;
1166 static_assert(TC.template MatchesArgs<DepTestType &&>, "");
1167 }
1168 CoroMemberTag test_ref_qual(const char *&) const volatile && {
1169 auto TC = co_yield 0;
1170 static_assert(TC.template MatchesArgs<DepTestType const volatile &&, const char *&>, "");
1171 }
1172
1173 CoroMemberTag test_args(int) {
1174 auto TC = co_yield 0;
1175 static_assert(TC.template MatchesArgs<DepTestType &, int>, "");
1176 }
1177 CoroMemberTag test_args(int, long &, void *) const {
1178 auto TC = co_yield 0;
1179 static_assert(TC.template MatchesArgs<DepTestType const &, int, long &, void *>, "");
1180 }
1181
1182 template <class... UArgs>
1183 CoroMemberTag test_member_template(UArgs...) const && {
1184 auto TC = co_yield 0;
1185 static_assert(TC.template MatchesArgs<DepTestType const &&, UArgs...>, "");
1186 }
1187
1188 static CoroMemberTag test_static() {
1189 auto TC = co_yield 0;
1190 using TCT = decltype(TC);
1191 static_assert(TCT::MatchesArgs<>, "");
1192 static_assert(!TCT::MatchesArgs<DepTestType>, "");
1193 static_assert(!TCT::MatchesArgs<DepTestType &>, "");
1194 static_assert(!TCT::MatchesArgs<DepTestType *>, "");
1195
1196 // Ensure diagnostics are actually being generated here
1197 static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
1198 }
1199
1200 static CoroMemberTag test_static(volatile void *const, char &&) {
1201 auto TC = co_yield 0;
1202 using TCT = decltype(TC);
1203 static_assert(TCT::MatchesArgs<volatile void *const, char &&>, "");
1204 }
1205
1206 template <class Dummy>
1207 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1208 auto TC = co_yield 0;
1209 using TCT = decltype(TC);
1210 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1211 static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
1212 }
1213};
1214
1215template struct DepTestType<int>; // expected-note {{requested here}}
1216template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&;
1217
1218template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);
1219
Brian Gesiak61f4ac92018-01-24 22:15:42 +00001220struct bad_promise_deleted_constructor {
1221 // expected-note@+1 {{'bad_promise_deleted_constructor' has been explicitly marked deleted here}}
1222 bad_promise_deleted_constructor() = delete;
1223 coro<bad_promise_deleted_constructor> get_return_object();
1224 suspend_always initial_suspend();
1225 suspend_always final_suspend();
1226 void return_void();
1227 void unhandled_exception();
1228};
1229
1230coro<bad_promise_deleted_constructor>
1231bad_coroutine_calls_deleted_promise_constructor() {
1232 // expected-error@-1 {{call to deleted constructor of 'std::experimental::coroutine_traits<coro<CoroHandleMemberFunctionTest::bad_promise_deleted_constructor>>::promise_type' (aka 'CoroHandleMemberFunctionTest::bad_promise_deleted_constructor')}}
1233 co_return;
1234}
1235
1236// Test that, when the promise type has a constructor whose signature matches
1237// that of the coroutine function, that constructor is used. If no matching
1238// constructor exists, the default constructor is used as a fallback. If no
1239// matching constructors exist at all, an error is emitted. This is an
1240// experimental feature that will be proposed for the Coroutines TS.
1241
1242struct good_promise_default_constructor {
1243 good_promise_default_constructor(double, float, int);
1244 good_promise_default_constructor() = default;
1245 coro<good_promise_default_constructor> get_return_object();
1246 suspend_always initial_suspend();
1247 suspend_always final_suspend();
1248 void return_void();
1249 void unhandled_exception();
1250};
1251
1252coro<good_promise_default_constructor>
1253good_coroutine_calls_default_constructor() {
1254 co_return;
1255}
1256
Gor Nishanov07ac63f2018-05-28 18:08:47 +00001257struct some_class;
1258
Brian Gesiak61f4ac92018-01-24 22:15:42 +00001259struct good_promise_custom_constructor {
Gor Nishanov07ac63f2018-05-28 18:08:47 +00001260 good_promise_custom_constructor(some_class&, float, int);
Brian Gesiak61f4ac92018-01-24 22:15:42 +00001261 good_promise_custom_constructor(double, float, int);
1262 good_promise_custom_constructor() = delete;
1263 coro<good_promise_custom_constructor> get_return_object();
1264 suspend_always initial_suspend();
1265 suspend_always final_suspend();
1266 void return_void();
1267 void unhandled_exception();
1268};
1269
1270coro<good_promise_custom_constructor>
1271good_coroutine_calls_custom_constructor(double, float, int) {
1272 co_return;
1273}
1274
Gor Nishanov07ac63f2018-05-28 18:08:47 +00001275struct some_class {
1276 coro<good_promise_custom_constructor>
1277 good_coroutine_calls_custom_constructor(float, int) {
1278 co_return;
1279 }
1280 coro<good_promise_custom_constructor>
1281 static good_coroutine_calls_custom_constructor(double, float, int) {
1282 co_return;
1283 }
1284};
1285
Brian Gesiak61f4ac92018-01-24 22:15:42 +00001286struct bad_promise_no_matching_constructor {
1287 bad_promise_no_matching_constructor(int, int, int);
Gor Nishanov07ac63f2018-05-28 18:08:47 +00001288 // expected-note@+1 2 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}}
Brian Gesiak61f4ac92018-01-24 22:15:42 +00001289 bad_promise_no_matching_constructor() = delete;
1290 coro<bad_promise_no_matching_constructor> get_return_object();
1291 suspend_always initial_suspend();
1292 suspend_always final_suspend();
1293 void return_void();
1294 void unhandled_exception();
1295};
1296
1297coro<bad_promise_no_matching_constructor>
1298bad_coroutine_calls_with_no_matching_constructor(int, int) {
1299 // expected-error@-1 {{call to deleted constructor of 'std::experimental::coroutine_traits<coro<CoroHandleMemberFunctionTest::bad_promise_no_matching_constructor>, int, int>::promise_type' (aka 'CoroHandleMemberFunctionTest::bad_promise_no_matching_constructor')}}
1300 co_return;
1301}
1302
Gor Nishanov07ac63f2018-05-28 18:08:47 +00001303struct some_class2 {
1304coro<bad_promise_no_matching_constructor>
1305bad_coroutine_calls_with_no_matching_constructor(int, int, int) {
1306 // expected-error@-1 {{call to deleted constructor}}
1307 co_return;
1308}
1309};
1310
Eric Fiselier166c6e62017-07-10 01:27:22 +00001311} // namespace CoroHandleMemberFunctionTest
Eric Fiselier16269a82018-03-27 00:58:16 +00001312
Eric Fiselier16269a82018-03-27 00:58:16 +00001313class awaitable_no_unused_warn {
1314public:
1315 using handle_type = std::experimental::coroutine_handle<>;
1316 constexpr bool await_ready() { return false; }
1317 void await_suspend(handle_type) noexcept {}
1318 int await_resume() { return 1; }
1319};
1320
1321
1322class awaitable_unused_warn {
1323public:
1324 using handle_type = std::experimental::coroutine_handle<>;
1325 constexpr bool await_ready() { return false; }
1326 void await_suspend(handle_type) noexcept {}
1327 [[nodiscard]]
1328 int await_resume() { return 1; }
1329};
1330
Eric Fiselier855c0922018-03-27 03:33:06 +00001331template <class Await>
1332struct check_warning_promise {
1333 coro<check_warning_promise> get_return_object();
1334 Await initial_suspend();
1335 Await final_suspend();
1336 Await yield_value(int);
1337 void return_void();
1338 void unhandled_exception();
1339};
1340
1341
1342coro<check_warning_promise<awaitable_no_unused_warn>>
1343test_no_unused_warning() {
Eric Fiselier16269a82018-03-27 00:58:16 +00001344 co_await awaitable_no_unused_warn();
Eric Fiselier855c0922018-03-27 03:33:06 +00001345 co_yield 42;
1346}
1347
1348coro<check_warning_promise<awaitable_unused_warn>>
1349test_unused_warning() {
Eric Fiselier16269a82018-03-27 00:58:16 +00001350 co_await awaitable_unused_warn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
Eric Fiselier855c0922018-03-27 03:33:06 +00001351 co_yield 42; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
Eric Fiselier16269a82018-03-27 00:58:16 +00001352}
Gor Nishanovd4507262018-03-27 20:38:19 +00001353
1354struct missing_await_ready {
1355 void await_suspend(std::experimental::coroutine_handle<>);
1356 void await_resume();
1357};
1358struct missing_await_suspend {
1359 bool await_ready();
1360 void await_resume();
1361};
1362struct missing_await_resume {
1363 bool await_ready();
1364 void await_suspend(std::experimental::coroutine_handle<>);
1365};
1366
1367void test_missing_awaitable_members() {
1368 co_await missing_await_ready{}; // expected-error {{no member named 'await_ready' in 'missing_await_ready'}}
1369 co_await missing_await_suspend{}; // expected-error {{no member named 'await_suspend' in 'missing_await_suspend'}}
1370 co_await missing_await_resume{}; // expected-error {{no member named 'await_resume' in 'missing_await_resume'}}
1371}