blob: 0d0588dbbf0029565e741fa1b89d468681df1439 [file] [log] [blame]
Eric Fiselier16269a82018-03-27 00:58:16 +00001// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -Wunused-result
Richard Smithcfd53b42015-10-22 06:13:50 +00002
Eric Fiseliera5465282016-09-29 21:47:39 +00003void no_coroutine_traits_bad_arg_await() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +00004 co_await a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +00005 // expected-error@-1 {{use of undeclared identifier 'a'}}
6}
7
8void no_coroutine_traits_bad_arg_yield() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +00009 co_yield a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +000010 // expected-error@-1 {{use of undeclared identifier 'a'}}
11}
12
13
14void no_coroutine_traits_bad_arg_return() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000015 co_return a; // expected-error {{include <experimental/coroutine>}}
Eric Fiseliera5465282016-09-29 21:47:39 +000016 // expected-error@-1 {{use of undeclared identifier 'a'}}
17}
18
Richard Smith9f690bd2015-10-27 06:02:45 +000019void no_coroutine_traits() {
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000020 co_await 4; // expected-error {{std::experimental::coroutine_traits type was not found; include <experimental/coroutine>}}
Richard Smith9f690bd2015-10-27 06:02:45 +000021}
22
23namespace std {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000024namespace experimental {
Eric Fiselier166c6e62017-07-10 01:27:22 +000025
26template <class... Args>
27struct void_t_imp {
28 using type = void;
29};
30template <class... Args>
31using void_t = typename void_t_imp<Args...>::type;
32
33template <class T, class = void>
34struct traits_sfinae_base {};
35
36template <class T>
37struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
38 using promise_type = typename T::promise_type;
39};
40
41template <class Ret, class... Args>
42struct coroutine_traits : public traits_sfinae_base<Ret> {};
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000043}} // namespace std::experimental
Richard Smith9f690bd2015-10-27 06:02:45 +000044
Richard Smith2af65c42015-11-24 02:34:39 +000045template<typename Promise> struct coro {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000046template <typename Promise, typename... Ps>
47struct std::experimental::coroutine_traits<coro<Promise>, Ps...> {
Richard Smith2af65c42015-11-24 02:34:39 +000048 using promise_type = Promise;
49};
50
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000051struct awaitable {
52 bool await_ready();
53 template <typename F> void await_suspend(F);
54 void await_resume();
55} a;
56
57struct suspend_always {
58 bool await_ready() { return false; }
59 template <typename F> void await_suspend(F);
60 void await_resume() {}
61};
62
63struct suspend_never {
64 bool await_ready() { return true; }
65 template <typename F> void await_suspend(F);
66 void await_resume() {}
67};
68
Gor Nishanovdb419a62017-09-05 19:31:52 +000069struct auto_await_suspend {
70 bool await_ready();
71 template <typename F> auto await_suspend(F) {}
72 void await_resume();
73};
74
Eric Fiselier166c6e62017-07-10 01:27:22 +000075struct DummyVoidTag {};
76DummyVoidTag no_specialization() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<DummyVoidTag>' has no member named 'promise_type'}}
77 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000078}
79
Gor Nishanov3e048bb2016-10-04 00:31:16 +000080template <typename... T>
81struct std::experimental::coroutine_traits<int, T...> {};
Richard Smith9f690bd2015-10-27 06:02:45 +000082
Eric Fiselier89bf0e72017-03-06 22:52:28 +000083int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
84 co_await a;
Richard Smith9b2f53e2015-11-19 02:36:35 +000085}
86
Gor Nishanov3e048bb2016-10-04 00:31:16 +000087template <>
88struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
Eric Fiselier89bf0e72017-03-06 22:52:28 +000089double 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}}
90 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000091}
92
Gor Nishanov3e048bb2016-10-04 00:31:16 +000093template <>
94struct std::experimental::coroutine_traits<double, int> {
Richard Smith23da82c2015-11-20 22:40:06 +000095 struct promise_type {};
96};
Eric Fiselier20f25cb2017-03-06 23:38:15 +000097double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}}
Gor Nishanov3e048bb2016-10-04 00:31:16 +000098 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 +000099}
100
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000101struct promise; // expected-note {{forward declaration}}
Eric Fiselier98131312016-10-06 21:23:38 +0000102struct promise_void;
103struct void_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000104template <typename... T>
105struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
Eric Fiselier98131312016-10-06 21:23:38 +0000106template <typename... T>
107struct std::experimental::coroutine_traits<void, void_tag, T...>
108{ using promise_type = promise_void; };
Richard Smith9f690bd2015-10-27 06:02:45 +0000109
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000110// FIXME: This diagnostic is terrible.
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000111void 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 +0000112 co_await a;
113}
114
Richard Smithae3d1472015-11-20 22:47:10 +0000115struct yielded_thing { const char *p; short a, b; };
Richard Smith23da82c2015-11-20 22:40:06 +0000116
Richard Smithd7bed4d2015-11-22 02:57:17 +0000117struct not_awaitable {};
118
Richard Smith23da82c2015-11-20 22:40:06 +0000119struct promise {
Richard Smith2af65c42015-11-24 02:34:39 +0000120 void get_return_object();
121 suspend_always initial_suspend();
122 suspend_always final_suspend();
Richard Smith71d403e2015-11-22 07:33:28 +0000123 awaitable yield_value(int); // expected-note 2{{candidate}}
124 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
125 not_awaitable yield_value(void()); // expected-note 2{{candidate}}
Richard Smith71d403e2015-11-22 07:33:28 +0000126 void return_value(int); // expected-note 2{{here}}
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000127 void unhandled_exception();
Richard Smith23da82c2015-11-20 22:40:06 +0000128};
129
Eric Fiselier98131312016-10-06 21:23:38 +0000130struct promise_void {
131 void get_return_object();
132 suspend_always initial_suspend();
133 suspend_always final_suspend();
Eric Fiselier98131312016-10-06 21:23:38 +0000134 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000135 void unhandled_exception();
Eric Fiselier98131312016-10-06 21:23:38 +0000136};
137
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000138void no_coroutine_handle() { // expected-error {{std::experimental::coroutine_handle type was not found; include <experimental/coroutine> before defining a coroutine}}
139 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
140 co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}}
141}
142
143namespace std {
144namespace experimental {
145template <class PromiseType = void>
146struct coroutine_handle {
147 static coroutine_handle from_address(void *);
148};
149template <>
150struct coroutine_handle<void> {
151 template <class PromiseType>
152 coroutine_handle(coroutine_handle<PromiseType>);
153 static coroutine_handle from_address(void *);
154};
155}} // namespace std::experimental
156
Richard Smith23da82c2015-11-20 22:40:06 +0000157void yield() {
158 co_yield 0;
Richard Smithae3d1472015-11-20 22:47:10 +0000159 co_yield {"foo", 1, 2};
Erich Keane7130a932018-05-07 20:52:56 +0000160 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 +0000161 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
162 co_yield {"foo"};
Richard Smith23da82c2015-11-20 22:40:06 +0000163 co_yield "foo"; // expected-error {{no matching}}
Richard Smithd7bed4d2015-11-22 02:57:17 +0000164 co_yield 1.0;
165 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Richard Smith23da82c2015-11-20 22:40:06 +0000166}
Richard Smith9f690bd2015-10-27 06:02:45 +0000167
Gor Nishanovdb419a62017-09-05 19:31:52 +0000168void check_auto_await_suspend() {
169 co_await auto_await_suspend{}; // Should compile successfully.
170}
171
Richard Smith4ba66602015-11-22 07:05:16 +0000172void coreturn(int n) {
173 co_await a;
174 if (n == 0)
175 co_return 3;
176 if (n == 1)
Eric Fiselier98131312016-10-06 21:23:38 +0000177 co_return {4}; // expected-warning {{braces around scalar initializer}}
Richard Smith4ba66602015-11-22 07:05:16 +0000178 if (n == 2)
179 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 +0000180 co_return 42;
Richard Smith4ba66602015-11-22 07:05:16 +0000181}
182
Eric Fiselier8d409e82017-03-09 05:01:31 +0000183template <class T>
184void co_await_non_dependent_arg(T) {
185 co_await a;
186}
187template void co_await_non_dependent_arg(int);
188
Richard Smithcfd53b42015-10-22 06:13:50 +0000189void mixed_yield() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000190 co_yield 0; // expected-note {{use of 'co_yield'}}
191 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000192}
193
Eric Fiseliercac0a592017-03-11 02:35:37 +0000194void mixed_yield_invalid() {
195 co_yield blah; // expected-error {{use of undeclared identifier}}
196 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
197 return; // expected-error {{return statement not allowed in coroutine}}
198}
199
200template <class T>
201void mixed_yield_template(T) {
202 co_yield blah; // expected-error {{use of undeclared identifier}}
203 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
204 return; // expected-error {{return statement not allowed in coroutine}}
205}
206
207template <class T>
208void mixed_yield_template2(T) {
209 co_yield 42;
210 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
211 return; // expected-error {{return statement not allowed in coroutine}}
212}
213
214template <class T>
215void mixed_yield_template3(T v) {
216 co_yield blah(v);
217 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
218 return; // expected-error {{return statement not allowed in coroutine}}
219}
220
Richard Smithcfd53b42015-10-22 06:13:50 +0000221void mixed_await() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000222 co_await a; // expected-note {{use of 'co_await'}}
223 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000224}
225
Eric Fiseliercac0a592017-03-11 02:35:37 +0000226void mixed_await_invalid() {
227 co_await 42; // expected-error {{'int' is not a structure or union}}
228 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
229 return; // expected-error {{not allowed in coroutine}}
230}
231
232template <class T>
233void mixed_await_template(T) {
234 co_await 42;
235 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
236 return; // expected-error {{not allowed in coroutine}}
237}
238
239template <class T>
240void mixed_await_template2(T v) {
241 co_await v; // expected-error {{'long' is not a structure or union}}
242 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
243 return; // expected-error {{not allowed in coroutine}}
244}
245template void mixed_await_template2(long); // expected-note {{requested here}}
246
Eric Fiselier98131312016-10-06 21:23:38 +0000247void only_coreturn(void_tag) {
Gor Nishanovd97f6bf2017-01-10 00:08:31 +0000248 co_return; // OK
Richard Smithcfd53b42015-10-22 06:13:50 +0000249}
250
Eric Fiselier98131312016-10-06 21:23:38 +0000251void mixed_coreturn(void_tag, bool b) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000252 if (b)
Richard Smith9f690bd2015-10-27 06:02:45 +0000253 co_return; // expected-note {{use of 'co_return'}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000254 else
Richard Smith9f690bd2015-10-27 06:02:45 +0000255 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000256}
257
Eric Fiseliercac0a592017-03-11 02:35:37 +0000258void mixed_coreturn_invalid(bool b) {
259 if (b)
260 co_return; // expected-note {{use of 'co_return'}}
261 // expected-error@-1 {{no member named 'return_void' in 'promise'}}
262 else
263 return; // expected-error {{not allowed in coroutine}}
264}
265
266template <class T>
267void mixed_coreturn_template(void_tag, bool b, T v) {
268 if (b)
269 co_return v; // expected-note {{use of 'co_return'}}
270 // expected-error@-1 {{no member named 'return_value' in 'promise_void'}}
271 else
272 return; // expected-error {{not allowed in coroutine}}
273}
274template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}}
275
276template <class T>
277void mixed_coreturn_template2(bool b, T) {
278 if (b)
279 co_return v; // expected-note {{use of 'co_return'}}
280 // expected-error@-1 {{use of undeclared identifier 'v'}}
281 else
282 return; // expected-error {{not allowed in coroutine}}
283}
284
Richard Smithcfd53b42015-10-22 06:13:50 +0000285struct CtorDtor {
286 CtorDtor() {
287 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
288 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000289 CtorDtor(awaitable a) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000290 // The spec doesn't say this is ill-formed, but it must be.
Richard Smith9f690bd2015-10-27 06:02:45 +0000291 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000292 }
293 ~CtorDtor() {
294 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
295 }
296 // FIXME: The spec says this is ill-formed.
297 void operator=(CtorDtor&) {
Eric Fiselierc8efda72016-10-27 18:43:28 +0000298 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
299 }
300 void operator=(CtorDtor const &) {
301 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
302 }
303 void operator=(CtorDtor &&) {
304 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
305 }
306 void operator=(CtorDtor const &&) {
307 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
308 }
309 void operator=(int) {
310 co_await a; // OK. Not a special member
Richard Smithcfd53b42015-10-22 06:13:50 +0000311 }
312};
313
Richard Smith744b2242015-11-20 02:54:01 +0000314void unevaluated() {
315 decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
316 sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
317 typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
318 decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
319 sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
320 typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
321}
322
Eric Fiselierc8efda72016-10-27 18:43:28 +0000323constexpr auto constexpr_deduced_return_coroutine() {
Richard Smith744b2242015-11-20 02:54:01 +0000324 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
Eric Fiselierc8efda72016-10-27 18:43:28 +0000325 // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000326}
327
328void varargs_coroutine(const char *, ...) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000329 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
330}
331
Eric Fiselierc8efda72016-10-27 18:43:28 +0000332auto deduced_return_coroutine() {
333 co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
334}
335
Richard Smith9f690bd2015-10-27 06:02:45 +0000336struct outer {};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000337struct await_arg_1 {};
338struct await_arg_2 {};
339
340namespace adl_ns {
341struct coawait_arg_type {};
342awaitable operator co_await(coawait_arg_type);
343}
Richard Smith9f690bd2015-10-27 06:02:45 +0000344
345namespace dependent_operator_co_await_lookup {
346 template<typename T> void await_template(T t) {
347 // no unqualified lookup results
348 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
349 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
350 };
351 template void await_template(awaitable);
352
353 struct indirectly_awaitable { indirectly_awaitable(outer); };
354 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
355 template void await_template(indirectly_awaitable);
356
357 struct not_awaitable {};
358 template void await_template(not_awaitable); // expected-note {{instantiation}}
359
360 template<typename T> void await_template_2(T t) {
361 // one unqualified lookup result
362 co_await t;
363 };
364 template void await_template(outer); // expected-note {{instantiation}}
365 template void await_template_2(outer);
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000366
367 struct transform_awaitable {};
368 struct transformed {};
369
370 struct transform_promise {
371 typedef transform_awaitable await_arg;
372 coro<transform_promise> get_return_object();
373 transformed initial_suspend();
374 ::adl_ns::coawait_arg_type final_suspend();
375 transformed await_transform(transform_awaitable);
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000376 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000377 void return_void();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000378 };
379 template <class AwaitArg>
380 struct basic_promise {
381 typedef AwaitArg await_arg;
382 coro<basic_promise> get_return_object();
383 awaitable initial_suspend();
384 awaitable final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000385 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000386 void return_void();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000387 };
388
389 awaitable operator co_await(await_arg_1);
390
391 template <typename T, typename U>
392 coro<T> await_template_3(U t) {
393 co_await t;
394 }
395
396 template coro<basic_promise<await_arg_1>> await_template_3<basic_promise<await_arg_1>>(await_arg_1);
397
398 template <class T, int I = 0>
399 struct dependent_member {
400 coro<T> mem_fn() const {
401 co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}}
402 }
403 template <class U>
404 coro<T> dep_mem_fn(U t) {
405 co_await t;
406 }
407 };
408
409 template <>
410 struct dependent_member<long> {
411 // FIXME this diagnostic is terrible
412 coro<transform_promise> mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
413 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
414 // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
415 co_await transform_awaitable{};
416 // expected-error@-1 {{no member named 'await_ready'}}
417 }
418 template <class R, class U>
419 coro<R> dep_mem_fn(U u) { co_await u; }
420 };
421
422 awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}}
423
424 template struct dependent_member<basic_promise<await_arg_1>, 0>;
425 template struct dependent_member<basic_promise<await_arg_2>, 0>; // expected-note {{in instantiation}}
426
427 template <>
428 coro<transform_promise>
429 // FIXME this diagnostic is terrible
430 dependent_member<long>::dep_mem_fn<transform_promise>(int) { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
431 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
432 //expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
433 co_await transform_awaitable{};
434 // expected-error@-1 {{no member named 'await_ready'}}
435 }
436
437 void operator co_await(transform_awaitable) = delete;
438 awaitable operator co_await(transformed);
439
440 template coro<transform_promise>
441 dependent_member<long>::dep_mem_fn<transform_promise>(transform_awaitable);
442
443 template <>
444 coro<transform_promise> dependent_member<long>::dep_mem_fn<transform_promise>(long) {
445 co_await transform_awaitable{};
446 }
447
448 template <>
449 struct dependent_member<int> {
450 coro<transform_promise> mem_fn() const {
451 co_await transform_awaitable{};
452 }
453 };
454
455 template coro<transform_promise> await_template_3<transform_promise>(transform_awaitable);
456 template struct dependent_member<transform_promise>;
457 template coro<transform_promise> dependent_member<transform_promise>::dep_mem_fn(transform_awaitable);
Richard Smithcfd53b42015-10-22 06:13:50 +0000458}
Richard Smith10610f72015-11-20 22:57:24 +0000459
Richard Smith71d403e2015-11-22 07:33:28 +0000460struct yield_fn_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000461template <>
462struct std::experimental::coroutine_traits<void, yield_fn_tag> {
Richard Smith71d403e2015-11-22 07:33:28 +0000463 struct promise_type {
464 // FIXME: add an await_transform overload for functions
465 awaitable yield_value(int());
466 void return_value(int());
Richard Smith2af65c42015-11-24 02:34:39 +0000467
468 suspend_never initial_suspend();
469 suspend_never final_suspend();
470 void get_return_object();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000471 void unhandled_exception();
Richard Smith71d403e2015-11-22 07:33:28 +0000472 };
473};
474
Richard Smith10610f72015-11-20 22:57:24 +0000475namespace placeholder {
Richard Smith71d403e2015-11-22 07:33:28 +0000476 awaitable f(), f(int); // expected-note 4{{possible target}}
477 int g(), g(int); // expected-note 2{{candidate}}
Richard Smith10610f72015-11-20 22:57:24 +0000478 void x() {
479 co_await f; // expected-error {{reference to overloaded function}}
480 }
481 void y() {
Richard Smith71d403e2015-11-22 07:33:28 +0000482 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
Richard Smith10610f72015-11-20 22:57:24 +0000483 }
484 void z() {
485 co_await a;
Richard Smith71d403e2015-11-22 07:33:28 +0000486 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
487 }
488
489 void x(yield_fn_tag) {
490 co_await f; // expected-error {{reference to overloaded function}}
491 }
492 void y(yield_fn_tag) {
493 co_yield g;
494 }
495 void z(yield_fn_tag) {
496 co_await a;
497 co_return g;
Richard Smith10610f72015-11-20 22:57:24 +0000498 }
499}
Richard Smith2af65c42015-11-24 02:34:39 +0000500
501struct bad_promise_1 {
502 suspend_always initial_suspend();
503 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000504 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000505 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000506};
507coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
508 co_await a;
509}
510
511struct bad_promise_2 {
512 coro<bad_promise_2> get_return_object();
Gor Nishanovd4507262018-03-27 20:38:19 +0000513 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000514 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000515 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000516};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000517// FIXME: This shouldn't happen twice
Richard Smith2af65c42015-11-24 02:34:39 +0000518coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
519 co_await a;
520}
521
522struct bad_promise_3 {
523 coro<bad_promise_3> get_return_object();
Gor Nishanovd4507262018-03-27 20:38:19 +0000524 suspend_always initial_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000525 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000526 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000527};
528coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
529 co_await a;
530}
531
532struct bad_promise_4 {
533 coro<bad_promise_4> get_return_object();
534 not_awaitable initial_suspend();
535 suspend_always final_suspend();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000536 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000537};
538// FIXME: This diagnostic is terrible.
539coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000540 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
541 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000542}
543
544struct bad_promise_5 {
545 coro<bad_promise_5> get_return_object();
546 suspend_always initial_suspend();
547 not_awaitable final_suspend();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000548 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000549};
550// FIXME: This diagnostic is terrible.
551coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000552 // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}}
553 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000554}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000555
Eric Fiselier709d1b32016-10-27 07:30:31 +0000556struct bad_promise_6 {
557 coro<bad_promise_6> get_return_object();
558 suspend_always initial_suspend();
559 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000560 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000561 void return_void(); // expected-note 2 {{member 'return_void' first declared here}}
562 void return_value(int) const; // expected-note 2 {{member 'return_value' first declared here}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000563 void return_value(int);
564};
565coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
566 co_await a;
567}
568
Eric Fiselierbee782b2017-04-03 19:21:00 +0000569template <class T>
570coro<T> bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
571 co_await a;
572}
573template coro<bad_promise_6> bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}}
574
Gor Nishanov29ff6382017-05-24 14:34:19 +0000575struct bad_promise_7 { // expected-note 2 {{defined here}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000576 coro<bad_promise_7> get_return_object();
577 suspend_always initial_suspend();
578 suspend_always final_suspend();
579 void return_void();
Eric Fiselier709d1b32016-10-27 07:30:31 +0000580};
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000581coro<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 +0000582 co_await a;
583}
584
Eric Fiselierbee782b2017-04-03 19:21:00 +0000585template <class T>
586coro<T> no_unhandled_exception_dependent(T) { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}}
587 co_await a;
588}
589template coro<bad_promise_7> no_unhandled_exception_dependent(bad_promise_7); // expected-note {{in instantiation}}
590
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000591struct bad_promise_base {
592private:
593 void return_void();
594};
595struct bad_promise_8 : bad_promise_base {
Eric Fiselier709d1b32016-10-27 07:30:31 +0000596 coro<bad_promise_8> get_return_object();
597 suspend_always initial_suspend();
598 suspend_always final_suspend();
Eric Fiselierbee782b2017-04-03 19:21:00 +0000599 void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{made unavailable}}
600 void unhandled_exception() const; // expected-note 2 {{candidate}}
601 void unhandled_exception(void *) const; // expected-note 2 {{requires 1 argument, but 0 were provided}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000602};
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000603coro<bad_promise_8> calls_unhandled_exception() {
604 // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000605 // FIXME: also warn about private 'return_void' here. Even though building
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000606 // the call to unhandled_exception has already failed.
Eric Fiselier709d1b32016-10-27 07:30:31 +0000607 co_await a;
608}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000609
Eric Fiselierbee782b2017-04-03 19:21:00 +0000610template <class T>
611coro<T> calls_unhandled_exception_dependent(T) {
612 // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}}
613 co_await a;
614}
615template coro<bad_promise_8> calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}}
616
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000617struct bad_promise_9 {
618 coro<bad_promise_9> get_return_object();
619 suspend_always initial_suspend();
620 suspend_always final_suspend();
621 void await_transform(void *); // expected-note {{candidate}}
622 awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
623 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000624 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000625};
626coro<bad_promise_9> calls_await_transform() {
627 co_await 42; // expected-error {{call to unavailable member function 'await_transform'}}
628 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
629}
630
631struct bad_promise_10 {
632 coro<bad_promise_10> get_return_object();
633 suspend_always initial_suspend();
634 suspend_always final_suspend();
635 int await_transform;
636 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000637 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000638};
639coro<bad_promise_10> bad_coawait() {
640 // FIXME this diagnostic is terrible
641 co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}}
642 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
643}
644
645struct call_operator {
646 template <class... Args>
647 awaitable operator()(Args...) const { return a; }
648};
649void ret_void();
650struct good_promise_1 {
651 coro<good_promise_1> get_return_object();
652 suspend_always initial_suspend();
653 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000654 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000655 static const call_operator await_transform;
656 using Fn = void (*)();
657 Fn return_void = ret_void;
658};
659const call_operator good_promise_1::await_transform;
660coro<good_promise_1> ok_static_coawait() {
661 // FIXME this diagnostic is terrible
662 co_await 42;
663}
664
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000665template<> struct std::experimental::coroutine_traits<int, int, const char**>
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000666{ using promise_type = promise; };
667
Eric Fiselierc8efda72016-10-27 18:43:28 +0000668int main(int, const char**) {
669 co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000670}
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000671
672struct good_promise_2 {
673 float get_return_object();
674 suspend_always initial_suspend();
675 suspend_always final_suspend();
676 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000677 void unhandled_exception();
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000678};
679template<> struct std::experimental::coroutine_handle<good_promise_2> {};
680
681template<> struct std::experimental::coroutine_traits<float>
682{ using promise_type = good_promise_2; };
683
684float badly_specialized_coro_handle() { // expected-error {{std::experimental::coroutine_handle missing a member named 'from_address'}}
685 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
686 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
687}
Gor Nishanov3aa9eb32017-03-27 23:36:59 +0000688
Eric Fiselierf692e7d2017-04-18 03:12:48 +0000689namespace std {
690 struct nothrow_t {};
691 constexpr nothrow_t nothrow = {};
692}
693
694using SizeT = decltype(sizeof(int));
695
696void* operator new(SizeT __sz, const std::nothrow_t&) noexcept;
697void operator delete(void* __p, const std::nothrow_t&) noexcept;
698
699
700
Gor Nishanov3aa9eb32017-03-27 23:36:59 +0000701struct promise_on_alloc_failure_tag {};
702
703template<>
704struct std::experimental::coroutine_traits<int, promise_on_alloc_failure_tag> {
705 struct promise_type {
706 int get_return_object() {}
707 suspend_always initial_suspend() { return {}; }
708 suspend_always final_suspend() { return {}; }
709 void return_void() {}
710 int get_return_object_on_allocation_failure(); // expected-error{{'promise_type': 'get_return_object_on_allocation_failure()' must be a static member function}}
711 void unhandled_exception();
712 };
713};
714
715extern "C" int f(promise_on_alloc_failure_tag) {
716 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
717}
Eric Fiselierbee782b2017-04-03 19:21:00 +0000718
719struct bad_promise_11 {
720 coro<bad_promise_11> get_return_object();
721 suspend_always initial_suspend();
722 suspend_always final_suspend();
723 void unhandled_exception();
724 void return_void();
725
726private:
727 static coro<bad_promise_11> get_return_object_on_allocation_failure(); // expected-note 2 {{declared private here}}
728};
729coro<bad_promise_11> private_alloc_failure_handler() {
730 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
731 co_return; // FIXME: Add a "declared coroutine here" note.
732}
733
734template <class T>
735coro<T> dependent_private_alloc_failure_handler(T) {
736 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
737 co_return; // FIXME: Add a "declared coroutine here" note.
738}
739template coro<bad_promise_11> dependent_private_alloc_failure_handler(bad_promise_11);
740// expected-note@-1 {{requested here}}
Eric Fiselierf692e7d2017-04-18 03:12:48 +0000741
742struct bad_promise_12 {
743 coro<bad_promise_12> get_return_object();
744 suspend_always initial_suspend();
745 suspend_always final_suspend();
746 void unhandled_exception();
747 void return_void();
748 static coro<bad_promise_12> get_return_object_on_allocation_failure();
749
750 static void* operator new(SizeT);
751 // 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()'}}
752};
753coro<bad_promise_12> throwing_in_class_new() { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
754 co_return;
755}
756
757template <class T>
758coro<T> dependent_throwing_in_class_new(T) { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
759 co_return;
760}
761template coro<bad_promise_12> dependent_throwing_in_class_new(bad_promise_12); // expected-note {{requested here}}
762
763
764struct good_promise_13 {
765 coro<good_promise_13> get_return_object();
766 suspend_always initial_suspend();
767 suspend_always final_suspend();
768 void unhandled_exception();
769 void return_void();
770 static coro<good_promise_13> get_return_object_on_allocation_failure();
771};
772coro<good_promise_13> uses_nothrow_new() {
773 co_return;
774}
775
776template <class T>
777coro<T> dependent_uses_nothrow_new(T) {
778 co_return;
779}
780template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13);
Gor Nishanov6a470682017-05-22 20:22:23 +0000781
Brian Gesiak98606222018-02-15 20:37:22 +0000782struct good_promise_custom_new_operator {
783 coro<good_promise_custom_new_operator> get_return_object();
784 suspend_always initial_suspend();
785 suspend_always final_suspend();
786 void return_void();
787 void unhandled_exception();
Brian Gesiak521b13b2018-02-16 14:11:27 +0000788 void *operator new(SizeT, double, float, int);
Brian Gesiak98606222018-02-15 20:37:22 +0000789};
790
791coro<good_promise_custom_new_operator>
792good_coroutine_calls_custom_new_operator(double, float, int) {
793 co_return;
794}
795
796struct coroutine_nonstatic_member_struct;
797
798struct good_promise_nonstatic_member_custom_new_operator {
799 coro<good_promise_nonstatic_member_custom_new_operator> get_return_object();
800 suspend_always initial_suspend();
801 suspend_always final_suspend();
802 void return_void();
803 void unhandled_exception();
Brian Gesiak521b13b2018-02-16 14:11:27 +0000804 void *operator new(SizeT, coroutine_nonstatic_member_struct &, double);
Brian Gesiak98606222018-02-15 20:37:22 +0000805};
806
Brian Gesiak98606222018-02-15 20:37:22 +0000807struct good_promise_noexcept_custom_new_operator {
808 static coro<good_promise_noexcept_custom_new_operator> get_return_object_on_allocation_failure();
809 coro<good_promise_noexcept_custom_new_operator> get_return_object();
810 suspend_always initial_suspend();
811 suspend_always final_suspend();
812 void return_void();
813 void unhandled_exception();
Brian Gesiak521b13b2018-02-16 14:11:27 +0000814 void *operator new(SizeT, double, float, int) noexcept;
Brian Gesiak98606222018-02-15 20:37:22 +0000815};
816
817coro<good_promise_noexcept_custom_new_operator>
818good_coroutine_calls_noexcept_custom_new_operator(double, float, int) {
819 co_return;
820}
821
Gor Nishanov6a470682017-05-22 20:22:23 +0000822struct mismatch_gro_type_tag1 {};
823template<>
824struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> {
825 struct promise_type {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000826 void get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000827 suspend_always initial_suspend() { return {}; }
828 suspend_always final_suspend() { return {}; }
829 void return_void() {}
830 void unhandled_exception();
831 };
832};
833
834extern "C" int f(mismatch_gro_type_tag1) {
835 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
836 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
837}
838
839struct mismatch_gro_type_tag2 {};
840template<>
841struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> {
842 struct promise_type {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000843 void *get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000844 suspend_always initial_suspend() { return {}; }
845 suspend_always final_suspend() { return {}; }
846 void return_void() {}
847 void unhandled_exception();
848 };
849};
850
851extern "C" int f(mismatch_gro_type_tag2) {
852 // expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
853 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
854}
855
856struct mismatch_gro_type_tag3 {};
857template<>
858struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag3> {
859 struct promise_type {
860 int get_return_object() {}
Eric Fiselierfc50f622017-05-25 14:59:39 +0000861 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 +0000862 suspend_always initial_suspend() { return {}; }
863 suspend_always final_suspend() { return {}; }
864 void return_void() {}
865 void unhandled_exception();
866 };
867};
868
869extern "C" int f(mismatch_gro_type_tag3) {
870 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
871 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
872}
873
874
875struct mismatch_gro_type_tag4 {};
876template<>
877struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag4> {
878 struct promise_type {
879 int get_return_object() {}
Eric Fiselierfc50f622017-05-25 14:59:39 +0000880 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 +0000881 suspend_always initial_suspend() { return {}; }
882 suspend_always final_suspend() { return {}; }
883 void return_void() {}
884 void unhandled_exception();
885 };
886};
887
888extern "C" int f(mismatch_gro_type_tag4) {
889 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}}
890 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
891}
892
Eric Fiselierfc50f622017-05-25 14:59:39 +0000893struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000894 coro<bad_promise_no_return_func> get_return_object();
895 suspend_always initial_suspend();
896 suspend_always final_suspend();
897 void unhandled_exception();
898};
Eric Fiselierfc50f622017-05-25 14:59:39 +0000899// FIXME: The PDTS currently specifies this as UB, technically forbidding a
900// diagnostic.
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000901coro<bad_promise_no_return_func> no_return_value_or_return_void() {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000902 // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000903 co_await a;
904}
Eric Fiselierd978e532017-05-28 18:21:12 +0000905
906struct bad_await_suspend_return {
907 bool await_ready();
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000908 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Eric Fiselierd978e532017-05-28 18:21:12 +0000909 char await_suspend(std::experimental::coroutine_handle<>);
910 void await_resume();
911};
912struct bad_await_ready_return {
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000913 // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}}
Eric Fiselierd978e532017-05-28 18:21:12 +0000914 void await_ready();
915 bool await_suspend(std::experimental::coroutine_handle<>);
916 void await_resume();
917};
918struct await_ready_explicit_bool {
919 struct BoolT {
920 explicit operator bool() const;
921 };
922 BoolT await_ready();
923 void await_suspend(std::experimental::coroutine_handle<>);
924 void await_resume();
925};
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000926template <class SuspendTy>
927struct await_suspend_type_test {
928 bool await_ready();
929 // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}}
930 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}}
931 SuspendTy await_suspend(std::experimental::coroutine_handle<>);
932 void await_resume();
933};
Eric Fiselierd978e532017-05-28 18:21:12 +0000934void test_bad_suspend() {
935 {
936 // FIXME: The actual error emitted here is terrible, and no number of notes can save it.
937 bad_await_ready_return a;
938 // expected-error@+1 {{value of type 'void' is not contextually convertible to 'bool'}}
939 co_await a; // expected-note {{call to 'await_ready' implicitly required by coroutine function here}}
940 }
941 {
942 bad_await_suspend_return b;
943 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
944 }
945 {
946 await_ready_explicit_bool c;
947 co_await c; // OK
948 }
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000949 {
950 await_suspend_type_test<bool &&> a;
951 await_suspend_type_test<bool &> b;
952 await_suspend_type_test<const void> c;
953 await_suspend_type_test<const volatile bool> d;
954 co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
955 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
956 co_await c; // OK
957 co_await d; // OK
958 }
Eric Fiselierd978e532017-05-28 18:21:12 +0000959}
Eric Fiselierde7943b2017-06-03 00:22:18 +0000960
961template <int ID = 0>
962struct NoCopy {
963 NoCopy(NoCopy const&) = delete; // expected-note 2 {{deleted here}}
964};
965template <class T, class U>
966void test_dependent_param(T t, U) {
967 // expected-error@-1 {{call to deleted constructor of 'NoCopy<0>'}}
968 // expected-error@-2 {{call to deleted constructor of 'NoCopy<1>'}}
969 ((void)t);
970 co_return 42;
971}
972template void test_dependent_param(NoCopy<0>, NoCopy<1>); // expected-note {{requested here}}
Eric Fiselier166c6e62017-07-10 01:27:22 +0000973
974namespace CoroHandleMemberFunctionTest {
975struct CoroMemberTag {};
976struct BadCoroMemberTag {};
977
978template <class T, class U>
979constexpr bool IsSameV = false;
980template <class T>
981constexpr bool IsSameV<T, T> = true;
982
983template <class T>
984struct TypeTest {
985 template <class U>
986 static constexpr bool IsSame = IsSameV<T, U>;
987
988 template <class... Args>
989 static constexpr bool MatchesArgs = IsSameV<T,
990 std::experimental::coroutine_traits<CoroMemberTag, Args...>>;
991};
992
993template <class T>
994struct AwaitReturnsType {
995 bool await_ready() const;
996 void await_suspend(...) const;
997 T await_resume() const;
998};
999
1000template <class... CoroTraitsArgs>
1001struct CoroMemberPromise {
1002 using TraitsT = std::experimental::coroutine_traits<CoroTraitsArgs...>;
1003 using TypeTestT = TypeTest<TraitsT>;
1004 using AwaitTestT = AwaitReturnsType<TypeTestT>;
1005
1006 CoroMemberTag get_return_object();
1007 suspend_always initial_suspend();
1008 suspend_always final_suspend();
1009
1010 AwaitTestT yield_value(int);
1011
1012 void return_void();
1013 void unhandled_exception();
1014};
1015
1016} // namespace CoroHandleMemberFunctionTest
1017
1018template <class... Args>
1019struct ::std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::CoroMemberTag, Args...> {
1020 using promise_type = CoroHandleMemberFunctionTest::CoroMemberPromise<CoroHandleMemberFunctionTest::CoroMemberTag, Args...>;
1021};
1022
1023namespace CoroHandleMemberFunctionTest {
1024struct TestType {
1025
1026 CoroMemberTag test_qual() {
1027 auto TC = co_yield 0;
1028 static_assert(TC.MatchesArgs<TestType &>, "");
1029 static_assert(!TC.MatchesArgs<TestType>, "");
1030 static_assert(!TC.MatchesArgs<TestType *>, "");
1031 }
1032
1033 CoroMemberTag test_sanity(int *) const {
1034 auto TC = co_yield 0;
1035 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static_assert failed}}
1036 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static_assert failed}}
1037 static_assert(TC.MatchesArgs<const TestType &, int *>, "");
1038 }
1039
1040 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1041 auto TC = co_yield 0;
1042 static_assert(TC.MatchesArgs<const TestType &, int *, const float &&, volatile void *volatile>, "");
1043 }
1044
1045 CoroMemberTag test_qual() const volatile {
1046 auto TC = co_yield 0;
1047 static_assert(TC.MatchesArgs<const volatile TestType &>, "");
1048 }
1049
1050 CoroMemberTag test_ref_qual() & {
1051 auto TC = co_yield 0;
1052 static_assert(TC.MatchesArgs<TestType &>, "");
1053 }
1054 CoroMemberTag test_ref_qual() const & {
1055 auto TC = co_yield 0;
1056 static_assert(TC.MatchesArgs<TestType const &>, "");
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 char *&) const volatile && {
1063 auto TC = co_yield 0;
1064 static_assert(TC.MatchesArgs<TestType const volatile &&, const char *&>, "");
1065 }
1066
1067 CoroMemberTag test_args(int) {
1068 auto TC = co_yield 0;
1069 static_assert(TC.MatchesArgs<TestType &, int>, "");
1070 }
1071 CoroMemberTag test_args(int, long &, void *) const {
1072 auto TC = co_yield 0;
1073 static_assert(TC.MatchesArgs<TestType const &, int, long &, void *>, "");
1074 }
1075
1076 template <class... Args>
1077 CoroMemberTag test_member_template(Args...) const && {
1078 auto TC = co_yield 0;
1079 static_assert(TC.template MatchesArgs<TestType const &&, Args...>, "");
1080 }
1081
1082 static CoroMemberTag test_static() {
1083 auto TC = co_yield 0;
1084 static_assert(TC.MatchesArgs<>, "");
1085 static_assert(!TC.MatchesArgs<TestType>, "");
1086 static_assert(!TC.MatchesArgs<TestType &>, "");
1087 static_assert(!TC.MatchesArgs<TestType *>, "");
1088 }
1089
1090 static CoroMemberTag test_static(volatile void *const, char &&) {
1091 auto TC = co_yield 0;
1092 static_assert(TC.MatchesArgs<volatile void *const, char &&>, "");
1093 }
1094
1095 template <class Dummy>
1096 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1097 auto TC = co_yield 0;
1098 using TCT = decltype(TC);
1099 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1100 static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
1101 }
1102
1103 BadCoroMemberTag test_diagnostics() {
1104 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, CoroHandleMemberFunctionTest::TestType &>' has no member named 'promise_type'}}
1105 co_return;
1106 }
1107 BadCoroMemberTag test_diagnostics(int) const && {
1108 // 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'}}
1109 co_return;
1110 }
1111
1112 static BadCoroMemberTag test_static_diagnostics(long *) {
1113 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, long *>' has no member named 'promise_type'}}
1114 co_return;
1115 }
1116};
1117
1118template CoroMemberTag TestType::test_member_template(long, const char *) const &&;
1119template CoroMemberTag TestType::test_static_template<void>(const char *volatile &, unsigned);
1120
1121template <class... Args>
1122struct DepTestType {
1123
1124 CoroMemberTag test_sanity(int *) const {
1125 auto TC = co_yield 0;
1126 static_assert(TC.template MatchesArgs<const DepTestType &>, ""); // expected-error {{static_assert failed}}
1127 static_assert(TC.template MatchesArgs<>, ""); // expected-error {{static_assert failed}}
1128 static_assert(TC.template MatchesArgs<const DepTestType &, int *>, "");
1129 }
1130
1131 CoroMemberTag test_qual() {
1132 auto TC = co_yield 0;
1133 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1134 static_assert(!TC.template MatchesArgs<DepTestType>, "");
1135 static_assert(!TC.template MatchesArgs<DepTestType *>, "");
1136 }
1137
1138 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1139 auto TC = co_yield 0;
1140 static_assert(TC.template MatchesArgs<const DepTestType &, int *, const float &&, volatile void *volatile>, "");
1141 }
1142
1143 CoroMemberTag test_qual() const volatile {
1144 auto TC = co_yield 0;
1145 static_assert(TC.template MatchesArgs<const volatile DepTestType &>, "");
1146 }
1147
1148 CoroMemberTag test_ref_qual() & {
1149 auto TC = co_yield 0;
1150 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1151 }
1152 CoroMemberTag test_ref_qual() const & {
1153 auto TC = co_yield 0;
1154 static_assert(TC.template MatchesArgs<DepTestType const &>, "");
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 char *&) const volatile && {
1161 auto TC = co_yield 0;
1162 static_assert(TC.template MatchesArgs<DepTestType const volatile &&, const char *&>, "");
1163 }
1164
1165 CoroMemberTag test_args(int) {
1166 auto TC = co_yield 0;
1167 static_assert(TC.template MatchesArgs<DepTestType &, int>, "");
1168 }
1169 CoroMemberTag test_args(int, long &, void *) const {
1170 auto TC = co_yield 0;
1171 static_assert(TC.template MatchesArgs<DepTestType const &, int, long &, void *>, "");
1172 }
1173
1174 template <class... UArgs>
1175 CoroMemberTag test_member_template(UArgs...) const && {
1176 auto TC = co_yield 0;
1177 static_assert(TC.template MatchesArgs<DepTestType const &&, UArgs...>, "");
1178 }
1179
1180 static CoroMemberTag test_static() {
1181 auto TC = co_yield 0;
1182 using TCT = decltype(TC);
1183 static_assert(TCT::MatchesArgs<>, "");
1184 static_assert(!TCT::MatchesArgs<DepTestType>, "");
1185 static_assert(!TCT::MatchesArgs<DepTestType &>, "");
1186 static_assert(!TCT::MatchesArgs<DepTestType *>, "");
1187
1188 // Ensure diagnostics are actually being generated here
1189 static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
1190 }
1191
1192 static CoroMemberTag test_static(volatile void *const, char &&) {
1193 auto TC = co_yield 0;
1194 using TCT = decltype(TC);
1195 static_assert(TCT::MatchesArgs<volatile void *const, char &&>, "");
1196 }
1197
1198 template <class Dummy>
1199 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1200 auto TC = co_yield 0;
1201 using TCT = decltype(TC);
1202 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1203 static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
1204 }
1205};
1206
1207template struct DepTestType<int>; // expected-note {{requested here}}
1208template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&;
1209
1210template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);
1211
Brian Gesiak61f4ac92018-01-24 22:15:42 +00001212struct bad_promise_deleted_constructor {
1213 // expected-note@+1 {{'bad_promise_deleted_constructor' has been explicitly marked deleted here}}
1214 bad_promise_deleted_constructor() = delete;
1215 coro<bad_promise_deleted_constructor> get_return_object();
1216 suspend_always initial_suspend();
1217 suspend_always final_suspend();
1218 void return_void();
1219 void unhandled_exception();
1220};
1221
1222coro<bad_promise_deleted_constructor>
1223bad_coroutine_calls_deleted_promise_constructor() {
1224 // 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')}}
1225 co_return;
1226}
1227
1228// Test that, when the promise type has a constructor whose signature matches
1229// that of the coroutine function, that constructor is used. If no matching
1230// constructor exists, the default constructor is used as a fallback. If no
1231// matching constructors exist at all, an error is emitted. This is an
1232// experimental feature that will be proposed for the Coroutines TS.
1233
1234struct good_promise_default_constructor {
1235 good_promise_default_constructor(double, float, int);
1236 good_promise_default_constructor() = default;
1237 coro<good_promise_default_constructor> get_return_object();
1238 suspend_always initial_suspend();
1239 suspend_always final_suspend();
1240 void return_void();
1241 void unhandled_exception();
1242};
1243
1244coro<good_promise_default_constructor>
1245good_coroutine_calls_default_constructor() {
1246 co_return;
1247}
1248
1249struct good_promise_custom_constructor {
1250 good_promise_custom_constructor(double, float, int);
1251 good_promise_custom_constructor() = delete;
1252 coro<good_promise_custom_constructor> get_return_object();
1253 suspend_always initial_suspend();
1254 suspend_always final_suspend();
1255 void return_void();
1256 void unhandled_exception();
1257};
1258
1259coro<good_promise_custom_constructor>
1260good_coroutine_calls_custom_constructor(double, float, int) {
1261 co_return;
1262}
1263
1264struct bad_promise_no_matching_constructor {
1265 bad_promise_no_matching_constructor(int, int, int);
1266 // expected-note@+1 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}}
1267 bad_promise_no_matching_constructor() = delete;
1268 coro<bad_promise_no_matching_constructor> get_return_object();
1269 suspend_always initial_suspend();
1270 suspend_always final_suspend();
1271 void return_void();
1272 void unhandled_exception();
1273};
1274
1275coro<bad_promise_no_matching_constructor>
1276bad_coroutine_calls_with_no_matching_constructor(int, int) {
1277 // 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')}}
1278 co_return;
1279}
1280
Eric Fiselier166c6e62017-07-10 01:27:22 +00001281} // namespace CoroHandleMemberFunctionTest
Eric Fiselier16269a82018-03-27 00:58:16 +00001282
Eric Fiselier16269a82018-03-27 00:58:16 +00001283class awaitable_no_unused_warn {
1284public:
1285 using handle_type = std::experimental::coroutine_handle<>;
1286 constexpr bool await_ready() { return false; }
1287 void await_suspend(handle_type) noexcept {}
1288 int await_resume() { return 1; }
1289};
1290
1291
1292class awaitable_unused_warn {
1293public:
1294 using handle_type = std::experimental::coroutine_handle<>;
1295 constexpr bool await_ready() { return false; }
1296 void await_suspend(handle_type) noexcept {}
1297 [[nodiscard]]
1298 int await_resume() { return 1; }
1299};
1300
Eric Fiselier855c0922018-03-27 03:33:06 +00001301template <class Await>
1302struct check_warning_promise {
1303 coro<check_warning_promise> get_return_object();
1304 Await initial_suspend();
1305 Await final_suspend();
1306 Await yield_value(int);
1307 void return_void();
1308 void unhandled_exception();
1309};
1310
1311
1312coro<check_warning_promise<awaitable_no_unused_warn>>
1313test_no_unused_warning() {
Eric Fiselier16269a82018-03-27 00:58:16 +00001314 co_await awaitable_no_unused_warn();
Eric Fiselier855c0922018-03-27 03:33:06 +00001315 co_yield 42;
1316}
1317
1318coro<check_warning_promise<awaitable_unused_warn>>
1319test_unused_warning() {
Eric Fiselier16269a82018-03-27 00:58:16 +00001320 co_await awaitable_unused_warn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
Eric Fiselier855c0922018-03-27 03:33:06 +00001321 co_yield 42; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
Eric Fiselier16269a82018-03-27 00:58:16 +00001322}
Gor Nishanovd4507262018-03-27 20:38:19 +00001323
1324struct missing_await_ready {
1325 void await_suspend(std::experimental::coroutine_handle<>);
1326 void await_resume();
1327};
1328struct missing_await_suspend {
1329 bool await_ready();
1330 void await_resume();
1331};
1332struct missing_await_resume {
1333 bool await_ready();
1334 void await_suspend(std::experimental::coroutine_handle<>);
1335};
1336
1337void test_missing_awaitable_members() {
1338 co_await missing_await_ready{}; // expected-error {{no member named 'await_ready' in 'missing_await_ready'}}
1339 co_await missing_await_suspend{}; // expected-error {{no member named 'await_suspend' in 'missing_await_suspend'}}
1340 co_await missing_await_resume{}; // expected-error {{no member named 'await_resume' in 'missing_await_resume'}}
1341}