blob: 6394829f356aee4baccc6327aecf9c6d2bb2ea20 [file] [log] [blame]
Eric Fiseliera9fdb342017-03-23 00:33:33 +00001// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions
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
Eric Fiselier166c6e62017-07-10 01:27:22 +000069struct DummyVoidTag {};
70DummyVoidTag no_specialization() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<DummyVoidTag>' has no member named 'promise_type'}}
71 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000072}
73
Gor Nishanov3e048bb2016-10-04 00:31:16 +000074template <typename... T>
75struct std::experimental::coroutine_traits<int, T...> {};
Richard Smith9f690bd2015-10-27 06:02:45 +000076
Eric Fiselier89bf0e72017-03-06 22:52:28 +000077int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
78 co_await a;
Richard Smith9b2f53e2015-11-19 02:36:35 +000079}
80
Gor Nishanov3e048bb2016-10-04 00:31:16 +000081template <>
82struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
Eric Fiselier89bf0e72017-03-06 22:52:28 +000083double 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}}
84 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000085}
86
Gor Nishanov3e048bb2016-10-04 00:31:16 +000087template <>
88struct std::experimental::coroutine_traits<double, int> {
Richard Smith23da82c2015-11-20 22:40:06 +000089 struct promise_type {};
90};
Eric Fiselier20f25cb2017-03-06 23:38:15 +000091double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}}
Gor Nishanov3e048bb2016-10-04 00:31:16 +000092 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 +000093}
94
Eric Fiselier89bf0e72017-03-06 22:52:28 +000095struct promise; // expected-note {{forward declaration}}
Eric Fiselier98131312016-10-06 21:23:38 +000096struct promise_void;
97struct void_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000098template <typename... T>
99struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
Eric Fiselier98131312016-10-06 21:23:38 +0000100template <typename... T>
101struct std::experimental::coroutine_traits<void, void_tag, T...>
102{ using promise_type = promise_void; };
Richard Smith9f690bd2015-10-27 06:02:45 +0000103
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000104// FIXME: This diagnostic is terrible.
Eric Fiselier89bf0e72017-03-06 22:52:28 +0000105void 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 +0000106 co_await a;
107}
108
Richard Smithae3d1472015-11-20 22:47:10 +0000109struct yielded_thing { const char *p; short a, b; };
Richard Smith23da82c2015-11-20 22:40:06 +0000110
Richard Smithd7bed4d2015-11-22 02:57:17 +0000111struct not_awaitable {};
112
Richard Smith23da82c2015-11-20 22:40:06 +0000113struct promise {
Richard Smith2af65c42015-11-24 02:34:39 +0000114 void get_return_object();
115 suspend_always initial_suspend();
116 suspend_always final_suspend();
Richard Smith71d403e2015-11-22 07:33:28 +0000117 awaitable yield_value(int); // expected-note 2{{candidate}}
118 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
119 not_awaitable yield_value(void()); // expected-note 2{{candidate}}
Richard Smith71d403e2015-11-22 07:33:28 +0000120 void return_value(int); // expected-note 2{{here}}
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000121 void unhandled_exception();
Richard Smith23da82c2015-11-20 22:40:06 +0000122};
123
Eric Fiselier98131312016-10-06 21:23:38 +0000124struct promise_void {
125 void get_return_object();
126 suspend_always initial_suspend();
127 suspend_always final_suspend();
Eric Fiselier98131312016-10-06 21:23:38 +0000128 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000129 void unhandled_exception();
Eric Fiselier98131312016-10-06 21:23:38 +0000130};
131
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000132void no_coroutine_handle() { // expected-error {{std::experimental::coroutine_handle type was not found; include <experimental/coroutine> before defining a coroutine}}
133 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
134 co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}}
135}
136
137namespace std {
138namespace experimental {
139template <class PromiseType = void>
140struct coroutine_handle {
141 static coroutine_handle from_address(void *);
142};
143template <>
144struct coroutine_handle<void> {
145 template <class PromiseType>
146 coroutine_handle(coroutine_handle<PromiseType>);
147 static coroutine_handle from_address(void *);
148};
149}} // namespace std::experimental
150
Richard Smith23da82c2015-11-20 22:40:06 +0000151void yield() {
152 co_yield 0;
Richard Smithae3d1472015-11-20 22:47:10 +0000153 co_yield {"foo", 1, 2};
154 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}}
155 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
156 co_yield {"foo"};
Richard Smith23da82c2015-11-20 22:40:06 +0000157 co_yield "foo"; // expected-error {{no matching}}
Richard Smithd7bed4d2015-11-22 02:57:17 +0000158 co_yield 1.0;
159 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Richard Smith23da82c2015-11-20 22:40:06 +0000160}
Richard Smith9f690bd2015-10-27 06:02:45 +0000161
Richard Smith4ba66602015-11-22 07:05:16 +0000162void coreturn(int n) {
163 co_await a;
164 if (n == 0)
165 co_return 3;
166 if (n == 1)
Eric Fiselier98131312016-10-06 21:23:38 +0000167 co_return {4}; // expected-warning {{braces around scalar initializer}}
Richard Smith4ba66602015-11-22 07:05:16 +0000168 if (n == 2)
169 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 +0000170 co_return 42;
Richard Smith4ba66602015-11-22 07:05:16 +0000171}
172
Eric Fiselier8d409e82017-03-09 05:01:31 +0000173template <class T>
174void co_await_non_dependent_arg(T) {
175 co_await a;
176}
177template void co_await_non_dependent_arg(int);
178
Richard Smithcfd53b42015-10-22 06:13:50 +0000179void mixed_yield() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000180 co_yield 0; // expected-note {{use of 'co_yield'}}
181 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000182}
183
Eric Fiseliercac0a592017-03-11 02:35:37 +0000184void mixed_yield_invalid() {
185 co_yield blah; // expected-error {{use of undeclared identifier}}
186 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
187 return; // expected-error {{return statement not allowed in coroutine}}
188}
189
190template <class T>
191void mixed_yield_template(T) {
192 co_yield blah; // expected-error {{use of undeclared identifier}}
193 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
194 return; // expected-error {{return statement not allowed in coroutine}}
195}
196
197template <class T>
198void mixed_yield_template2(T) {
199 co_yield 42;
200 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
201 return; // expected-error {{return statement not allowed in coroutine}}
202}
203
204template <class T>
205void mixed_yield_template3(T v) {
206 co_yield blah(v);
207 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
208 return; // expected-error {{return statement not allowed in coroutine}}
209}
210
Richard Smithcfd53b42015-10-22 06:13:50 +0000211void mixed_await() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000212 co_await a; // expected-note {{use of 'co_await'}}
213 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000214}
215
Eric Fiseliercac0a592017-03-11 02:35:37 +0000216void mixed_await_invalid() {
217 co_await 42; // expected-error {{'int' is not a structure or union}}
218 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
219 return; // expected-error {{not allowed in coroutine}}
220}
221
222template <class T>
223void mixed_await_template(T) {
224 co_await 42;
225 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
226 return; // expected-error {{not allowed in coroutine}}
227}
228
229template <class T>
230void mixed_await_template2(T v) {
231 co_await v; // expected-error {{'long' is not a structure or union}}
232 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
233 return; // expected-error {{not allowed in coroutine}}
234}
235template void mixed_await_template2(long); // expected-note {{requested here}}
236
Eric Fiselier98131312016-10-06 21:23:38 +0000237void only_coreturn(void_tag) {
Gor Nishanovd97f6bf2017-01-10 00:08:31 +0000238 co_return; // OK
Richard Smithcfd53b42015-10-22 06:13:50 +0000239}
240
Eric Fiselier98131312016-10-06 21:23:38 +0000241void mixed_coreturn(void_tag, bool b) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000242 if (b)
Richard Smith9f690bd2015-10-27 06:02:45 +0000243 co_return; // expected-note {{use of 'co_return'}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000244 else
Richard Smith9f690bd2015-10-27 06:02:45 +0000245 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000246}
247
Eric Fiseliercac0a592017-03-11 02:35:37 +0000248void mixed_coreturn_invalid(bool b) {
249 if (b)
250 co_return; // expected-note {{use of 'co_return'}}
251 // expected-error@-1 {{no member named 'return_void' in 'promise'}}
252 else
253 return; // expected-error {{not allowed in coroutine}}
254}
255
256template <class T>
257void mixed_coreturn_template(void_tag, bool b, T v) {
258 if (b)
259 co_return v; // expected-note {{use of 'co_return'}}
260 // expected-error@-1 {{no member named 'return_value' in 'promise_void'}}
261 else
262 return; // expected-error {{not allowed in coroutine}}
263}
264template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}}
265
266template <class T>
267void mixed_coreturn_template2(bool b, T) {
268 if (b)
269 co_return v; // expected-note {{use of 'co_return'}}
270 // expected-error@-1 {{use of undeclared identifier 'v'}}
271 else
272 return; // expected-error {{not allowed in coroutine}}
273}
274
Richard Smithcfd53b42015-10-22 06:13:50 +0000275struct CtorDtor {
276 CtorDtor() {
277 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
278 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000279 CtorDtor(awaitable a) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000280 // The spec doesn't say this is ill-formed, but it must be.
Richard Smith9f690bd2015-10-27 06:02:45 +0000281 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000282 }
283 ~CtorDtor() {
284 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
285 }
286 // FIXME: The spec says this is ill-formed.
287 void operator=(CtorDtor&) {
Eric Fiselierc8efda72016-10-27 18:43:28 +0000288 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
289 }
290 void operator=(CtorDtor const &) {
291 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
292 }
293 void operator=(CtorDtor &&) {
294 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
295 }
296 void operator=(CtorDtor const &&) {
297 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
298 }
299 void operator=(int) {
300 co_await a; // OK. Not a special member
Richard Smithcfd53b42015-10-22 06:13:50 +0000301 }
302};
303
Richard Smith744b2242015-11-20 02:54:01 +0000304void unevaluated() {
305 decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
306 sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
307 typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
308 decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
309 sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
310 typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
311}
312
Eric Fiselierc8efda72016-10-27 18:43:28 +0000313constexpr auto constexpr_deduced_return_coroutine() {
Richard Smith744b2242015-11-20 02:54:01 +0000314 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
Eric Fiselierc8efda72016-10-27 18:43:28 +0000315 // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000316}
317
318void varargs_coroutine(const char *, ...) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000319 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
320}
321
Eric Fiselierc8efda72016-10-27 18:43:28 +0000322auto deduced_return_coroutine() {
323 co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
324}
325
Richard Smith9f690bd2015-10-27 06:02:45 +0000326struct outer {};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000327struct await_arg_1 {};
328struct await_arg_2 {};
329
330namespace adl_ns {
331struct coawait_arg_type {};
332awaitable operator co_await(coawait_arg_type);
333}
Richard Smith9f690bd2015-10-27 06:02:45 +0000334
335namespace dependent_operator_co_await_lookup {
336 template<typename T> void await_template(T t) {
337 // no unqualified lookup results
338 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
339 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
340 };
341 template void await_template(awaitable);
342
343 struct indirectly_awaitable { indirectly_awaitable(outer); };
344 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
345 template void await_template(indirectly_awaitable);
346
347 struct not_awaitable {};
348 template void await_template(not_awaitable); // expected-note {{instantiation}}
349
350 template<typename T> void await_template_2(T t) {
351 // one unqualified lookup result
352 co_await t;
353 };
354 template void await_template(outer); // expected-note {{instantiation}}
355 template void await_template_2(outer);
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000356
357 struct transform_awaitable {};
358 struct transformed {};
359
360 struct transform_promise {
361 typedef transform_awaitable await_arg;
362 coro<transform_promise> get_return_object();
363 transformed initial_suspend();
364 ::adl_ns::coawait_arg_type final_suspend();
365 transformed await_transform(transform_awaitable);
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000366 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000367 void return_void();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000368 };
369 template <class AwaitArg>
370 struct basic_promise {
371 typedef AwaitArg await_arg;
372 coro<basic_promise> get_return_object();
373 awaitable initial_suspend();
374 awaitable final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000375 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000376 void return_void();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000377 };
378
379 awaitable operator co_await(await_arg_1);
380
381 template <typename T, typename U>
382 coro<T> await_template_3(U t) {
383 co_await t;
384 }
385
386 template coro<basic_promise<await_arg_1>> await_template_3<basic_promise<await_arg_1>>(await_arg_1);
387
388 template <class T, int I = 0>
389 struct dependent_member {
390 coro<T> mem_fn() const {
391 co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}}
392 }
393 template <class U>
394 coro<T> dep_mem_fn(U t) {
395 co_await t;
396 }
397 };
398
399 template <>
400 struct dependent_member<long> {
401 // FIXME this diagnostic is terrible
402 coro<transform_promise> mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
403 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
404 // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
405 co_await transform_awaitable{};
406 // expected-error@-1 {{no member named 'await_ready'}}
407 }
408 template <class R, class U>
409 coro<R> dep_mem_fn(U u) { co_await u; }
410 };
411
412 awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}}
413
414 template struct dependent_member<basic_promise<await_arg_1>, 0>;
415 template struct dependent_member<basic_promise<await_arg_2>, 0>; // expected-note {{in instantiation}}
416
417 template <>
418 coro<transform_promise>
419 // FIXME this diagnostic is terrible
420 dependent_member<long>::dep_mem_fn<transform_promise>(int) { // 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
427 void operator co_await(transform_awaitable) = delete;
428 awaitable operator co_await(transformed);
429
430 template coro<transform_promise>
431 dependent_member<long>::dep_mem_fn<transform_promise>(transform_awaitable);
432
433 template <>
434 coro<transform_promise> dependent_member<long>::dep_mem_fn<transform_promise>(long) {
435 co_await transform_awaitable{};
436 }
437
438 template <>
439 struct dependent_member<int> {
440 coro<transform_promise> mem_fn() const {
441 co_await transform_awaitable{};
442 }
443 };
444
445 template coro<transform_promise> await_template_3<transform_promise>(transform_awaitable);
446 template struct dependent_member<transform_promise>;
447 template coro<transform_promise> dependent_member<transform_promise>::dep_mem_fn(transform_awaitable);
Richard Smithcfd53b42015-10-22 06:13:50 +0000448}
Richard Smith10610f72015-11-20 22:57:24 +0000449
Richard Smith71d403e2015-11-22 07:33:28 +0000450struct yield_fn_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000451template <>
452struct std::experimental::coroutine_traits<void, yield_fn_tag> {
Richard Smith71d403e2015-11-22 07:33:28 +0000453 struct promise_type {
454 // FIXME: add an await_transform overload for functions
455 awaitable yield_value(int());
456 void return_value(int());
Richard Smith2af65c42015-11-24 02:34:39 +0000457
458 suspend_never initial_suspend();
459 suspend_never final_suspend();
460 void get_return_object();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000461 void unhandled_exception();
Richard Smith71d403e2015-11-22 07:33:28 +0000462 };
463};
464
Richard Smith10610f72015-11-20 22:57:24 +0000465namespace placeholder {
Richard Smith71d403e2015-11-22 07:33:28 +0000466 awaitable f(), f(int); // expected-note 4{{possible target}}
467 int g(), g(int); // expected-note 2{{candidate}}
Richard Smith10610f72015-11-20 22:57:24 +0000468 void x() {
469 co_await f; // expected-error {{reference to overloaded function}}
470 }
471 void y() {
Richard Smith71d403e2015-11-22 07:33:28 +0000472 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
Richard Smith10610f72015-11-20 22:57:24 +0000473 }
474 void z() {
475 co_await a;
Richard Smith71d403e2015-11-22 07:33:28 +0000476 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
477 }
478
479 void x(yield_fn_tag) {
480 co_await f; // expected-error {{reference to overloaded function}}
481 }
482 void y(yield_fn_tag) {
483 co_yield g;
484 }
485 void z(yield_fn_tag) {
486 co_await a;
487 co_return g;
Richard Smith10610f72015-11-20 22:57:24 +0000488 }
489}
Richard Smith2af65c42015-11-24 02:34:39 +0000490
491struct bad_promise_1 {
492 suspend_always initial_suspend();
493 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000494 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000495 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000496};
497coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
498 co_await a;
499}
500
501struct bad_promise_2 {
502 coro<bad_promise_2> get_return_object();
503 // FIXME: We shouldn't offer a typo-correction here!
504 suspend_always final_suspend(); // expected-note {{here}}
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000505 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000506 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000507};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000508// FIXME: This shouldn't happen twice
Richard Smith2af65c42015-11-24 02:34:39 +0000509coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
510 co_await a;
511}
512
513struct bad_promise_3 {
514 coro<bad_promise_3> get_return_object();
515 // FIXME: We shouldn't offer a typo-correction here!
516 suspend_always initial_suspend(); // expected-note {{here}}
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000517 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000518 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000519};
520coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
521 co_await a;
522}
523
524struct bad_promise_4 {
525 coro<bad_promise_4> get_return_object();
526 not_awaitable initial_suspend();
527 suspend_always final_suspend();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000528 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000529};
530// FIXME: This diagnostic is terrible.
531coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000532 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
533 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000534}
535
536struct bad_promise_5 {
537 coro<bad_promise_5> get_return_object();
538 suspend_always initial_suspend();
539 not_awaitable final_suspend();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000540 void return_void();
Richard Smith2af65c42015-11-24 02:34:39 +0000541};
542// FIXME: This diagnostic is terrible.
543coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000544 // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}}
545 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000546}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000547
Eric Fiselier709d1b32016-10-27 07:30:31 +0000548struct bad_promise_6 {
549 coro<bad_promise_6> get_return_object();
550 suspend_always initial_suspend();
551 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000552 void unhandled_exception();
Eric Fiselierfc50f622017-05-25 14:59:39 +0000553 void return_void(); // expected-note 2 {{member 'return_void' first declared here}}
554 void return_value(int) const; // expected-note 2 {{member 'return_value' first declared here}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000555 void return_value(int);
556};
557coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
558 co_await a;
559}
560
Eric Fiselierbee782b2017-04-03 19:21:00 +0000561template <class T>
562coro<T> bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
563 co_await a;
564}
565template coro<bad_promise_6> bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}}
566
Gor Nishanov29ff6382017-05-24 14:34:19 +0000567struct bad_promise_7 { // expected-note 2 {{defined here}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000568 coro<bad_promise_7> get_return_object();
569 suspend_always initial_suspend();
570 suspend_always final_suspend();
571 void return_void();
Eric Fiselier709d1b32016-10-27 07:30:31 +0000572};
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000573coro<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 +0000574 co_await a;
575}
576
Eric Fiselierbee782b2017-04-03 19:21:00 +0000577template <class T>
578coro<T> no_unhandled_exception_dependent(T) { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}}
579 co_await a;
580}
581template coro<bad_promise_7> no_unhandled_exception_dependent(bad_promise_7); // expected-note {{in instantiation}}
582
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000583struct bad_promise_base {
584private:
585 void return_void();
586};
587struct bad_promise_8 : bad_promise_base {
Eric Fiselier709d1b32016-10-27 07:30:31 +0000588 coro<bad_promise_8> get_return_object();
589 suspend_always initial_suspend();
590 suspend_always final_suspend();
Eric Fiselierbee782b2017-04-03 19:21:00 +0000591 void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{made unavailable}}
592 void unhandled_exception() const; // expected-note 2 {{candidate}}
593 void unhandled_exception(void *) const; // expected-note 2 {{requires 1 argument, but 0 were provided}}
Eric Fiselier709d1b32016-10-27 07:30:31 +0000594};
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000595coro<bad_promise_8> calls_unhandled_exception() {
596 // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000597 // FIXME: also warn about private 'return_void' here. Even though building
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000598 // the call to unhandled_exception has already failed.
Eric Fiselier709d1b32016-10-27 07:30:31 +0000599 co_await a;
600}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000601
Eric Fiselierbee782b2017-04-03 19:21:00 +0000602template <class T>
603coro<T> calls_unhandled_exception_dependent(T) {
604 // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}}
605 co_await a;
606}
607template coro<bad_promise_8> calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}}
608
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000609struct bad_promise_9 {
610 coro<bad_promise_9> get_return_object();
611 suspend_always initial_suspend();
612 suspend_always final_suspend();
613 void await_transform(void *); // expected-note {{candidate}}
614 awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
615 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000616 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000617};
618coro<bad_promise_9> calls_await_transform() {
619 co_await 42; // expected-error {{call to unavailable member function 'await_transform'}}
620 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
621}
622
623struct bad_promise_10 {
624 coro<bad_promise_10> get_return_object();
625 suspend_always initial_suspend();
626 suspend_always final_suspend();
627 int await_transform;
628 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000629 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000630};
631coro<bad_promise_10> bad_coawait() {
632 // FIXME this diagnostic is terrible
633 co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}}
634 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
635}
636
637struct call_operator {
638 template <class... Args>
639 awaitable operator()(Args...) const { return a; }
640};
641void ret_void();
642struct good_promise_1 {
643 coro<good_promise_1> get_return_object();
644 suspend_always initial_suspend();
645 suspend_always final_suspend();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000646 void unhandled_exception();
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000647 static const call_operator await_transform;
648 using Fn = void (*)();
649 Fn return_void = ret_void;
650};
651const call_operator good_promise_1::await_transform;
652coro<good_promise_1> ok_static_coawait() {
653 // FIXME this diagnostic is terrible
654 co_await 42;
655}
656
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000657template<> struct std::experimental::coroutine_traits<int, int, const char**>
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000658{ using promise_type = promise; };
659
Eric Fiselierc8efda72016-10-27 18:43:28 +0000660int main(int, const char**) {
661 co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000662}
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000663
664struct good_promise_2 {
665 float get_return_object();
666 suspend_always initial_suspend();
667 suspend_always final_suspend();
668 void return_void();
Eric Fiseliera9fdb342017-03-23 00:33:33 +0000669 void unhandled_exception();
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000670};
671template<> struct std::experimental::coroutine_handle<good_promise_2> {};
672
673template<> struct std::experimental::coroutine_traits<float>
674{ using promise_type = good_promise_2; };
675
676float badly_specialized_coro_handle() { // expected-error {{std::experimental::coroutine_handle missing a member named 'from_address'}}
677 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
678 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
679}
Gor Nishanov3aa9eb32017-03-27 23:36:59 +0000680
Eric Fiselierf692e7d2017-04-18 03:12:48 +0000681namespace std {
682 struct nothrow_t {};
683 constexpr nothrow_t nothrow = {};
684}
685
686using SizeT = decltype(sizeof(int));
687
688void* operator new(SizeT __sz, const std::nothrow_t&) noexcept;
689void operator delete(void* __p, const std::nothrow_t&) noexcept;
690
691
692
Gor Nishanov3aa9eb32017-03-27 23:36:59 +0000693struct promise_on_alloc_failure_tag {};
694
695template<>
696struct std::experimental::coroutine_traits<int, promise_on_alloc_failure_tag> {
697 struct promise_type {
698 int get_return_object() {}
699 suspend_always initial_suspend() { return {}; }
700 suspend_always final_suspend() { return {}; }
701 void return_void() {}
702 int get_return_object_on_allocation_failure(); // expected-error{{'promise_type': 'get_return_object_on_allocation_failure()' must be a static member function}}
703 void unhandled_exception();
704 };
705};
706
707extern "C" int f(promise_on_alloc_failure_tag) {
708 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
709}
Eric Fiselierbee782b2017-04-03 19:21:00 +0000710
711struct bad_promise_11 {
712 coro<bad_promise_11> get_return_object();
713 suspend_always initial_suspend();
714 suspend_always final_suspend();
715 void unhandled_exception();
716 void return_void();
717
718private:
719 static coro<bad_promise_11> get_return_object_on_allocation_failure(); // expected-note 2 {{declared private here}}
720};
721coro<bad_promise_11> private_alloc_failure_handler() {
722 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
723 co_return; // FIXME: Add a "declared coroutine here" note.
724}
725
726template <class T>
727coro<T> dependent_private_alloc_failure_handler(T) {
728 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
729 co_return; // FIXME: Add a "declared coroutine here" note.
730}
731template coro<bad_promise_11> dependent_private_alloc_failure_handler(bad_promise_11);
732// expected-note@-1 {{requested here}}
Eric Fiselierf692e7d2017-04-18 03:12:48 +0000733
734struct bad_promise_12 {
735 coro<bad_promise_12> get_return_object();
736 suspend_always initial_suspend();
737 suspend_always final_suspend();
738 void unhandled_exception();
739 void return_void();
740 static coro<bad_promise_12> get_return_object_on_allocation_failure();
741
742 static void* operator new(SizeT);
743 // 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()'}}
744};
745coro<bad_promise_12> throwing_in_class_new() { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
746 co_return;
747}
748
749template <class T>
750coro<T> dependent_throwing_in_class_new(T) { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
751 co_return;
752}
753template coro<bad_promise_12> dependent_throwing_in_class_new(bad_promise_12); // expected-note {{requested here}}
754
755
756struct good_promise_13 {
757 coro<good_promise_13> get_return_object();
758 suspend_always initial_suspend();
759 suspend_always final_suspend();
760 void unhandled_exception();
761 void return_void();
762 static coro<good_promise_13> get_return_object_on_allocation_failure();
763};
764coro<good_promise_13> uses_nothrow_new() {
765 co_return;
766}
767
768template <class T>
769coro<T> dependent_uses_nothrow_new(T) {
770 co_return;
771}
772template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13);
Gor Nishanov6a470682017-05-22 20:22:23 +0000773
774struct mismatch_gro_type_tag1 {};
775template<>
776struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> {
777 struct promise_type {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000778 void get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000779 suspend_always initial_suspend() { return {}; }
780 suspend_always final_suspend() { return {}; }
781 void return_void() {}
782 void unhandled_exception();
783 };
784};
785
786extern "C" int f(mismatch_gro_type_tag1) {
787 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
788 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
789}
790
791struct mismatch_gro_type_tag2 {};
792template<>
793struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> {
794 struct promise_type {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000795 void *get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
Gor Nishanov6a470682017-05-22 20:22:23 +0000796 suspend_always initial_suspend() { return {}; }
797 suspend_always final_suspend() { return {}; }
798 void return_void() {}
799 void unhandled_exception();
800 };
801};
802
803extern "C" int f(mismatch_gro_type_tag2) {
804 // expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
805 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
806}
807
808struct mismatch_gro_type_tag3 {};
809template<>
810struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag3> {
811 struct promise_type {
812 int get_return_object() {}
Eric Fiselierfc50f622017-05-25 14:59:39 +0000813 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 +0000814 suspend_always initial_suspend() { return {}; }
815 suspend_always final_suspend() { return {}; }
816 void return_void() {}
817 void unhandled_exception();
818 };
819};
820
821extern "C" int f(mismatch_gro_type_tag3) {
822 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
823 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
824}
825
826
827struct mismatch_gro_type_tag4 {};
828template<>
829struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag4> {
830 struct promise_type {
831 int get_return_object() {}
Eric Fiselierfc50f622017-05-25 14:59:39 +0000832 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 +0000833 suspend_always initial_suspend() { return {}; }
834 suspend_always final_suspend() { return {}; }
835 void return_void() {}
836 void unhandled_exception();
837 };
838};
839
840extern "C" int f(mismatch_gro_type_tag4) {
841 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}}
842 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
843}
844
Eric Fiselierfc50f622017-05-25 14:59:39 +0000845struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}}
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000846 coro<bad_promise_no_return_func> get_return_object();
847 suspend_always initial_suspend();
848 suspend_always final_suspend();
849 void unhandled_exception();
850};
Eric Fiselierfc50f622017-05-25 14:59:39 +0000851// FIXME: The PDTS currently specifies this as UB, technically forbidding a
852// diagnostic.
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000853coro<bad_promise_no_return_func> no_return_value_or_return_void() {
Eric Fiselierfc50f622017-05-25 14:59:39 +0000854 // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}}
Eric Fiselierda8f9b52017-05-25 02:16:53 +0000855 co_await a;
856}
Eric Fiselierd978e532017-05-28 18:21:12 +0000857
858struct bad_await_suspend_return {
859 bool await_ready();
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000860 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
Eric Fiselierd978e532017-05-28 18:21:12 +0000861 char await_suspend(std::experimental::coroutine_handle<>);
862 void await_resume();
863};
864struct bad_await_ready_return {
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000865 // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}}
Eric Fiselierd978e532017-05-28 18:21:12 +0000866 void await_ready();
867 bool await_suspend(std::experimental::coroutine_handle<>);
868 void await_resume();
869};
870struct await_ready_explicit_bool {
871 struct BoolT {
872 explicit operator bool() const;
873 };
874 BoolT await_ready();
875 void await_suspend(std::experimental::coroutine_handle<>);
876 void await_resume();
877};
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000878template <class SuspendTy>
879struct await_suspend_type_test {
880 bool await_ready();
881 // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}}
882 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}}
883 SuspendTy await_suspend(std::experimental::coroutine_handle<>);
884 void await_resume();
885};
Eric Fiselierd978e532017-05-28 18:21:12 +0000886void test_bad_suspend() {
887 {
888 // FIXME: The actual error emitted here is terrible, and no number of notes can save it.
889 bad_await_ready_return a;
890 // expected-error@+1 {{value of type 'void' is not contextually convertible to 'bool'}}
891 co_await a; // expected-note {{call to 'await_ready' implicitly required by coroutine function here}}
892 }
893 {
894 bad_await_suspend_return b;
895 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
896 }
897 {
898 await_ready_explicit_bool c;
899 co_await c; // OK
900 }
Eric Fiselier84ee7ff2017-05-31 23:41:11 +0000901 {
902 await_suspend_type_test<bool &&> a;
903 await_suspend_type_test<bool &> b;
904 await_suspend_type_test<const void> c;
905 await_suspend_type_test<const volatile bool> d;
906 co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
907 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
908 co_await c; // OK
909 co_await d; // OK
910 }
Eric Fiselierd978e532017-05-28 18:21:12 +0000911}
Eric Fiselierde7943b2017-06-03 00:22:18 +0000912
913template <int ID = 0>
914struct NoCopy {
915 NoCopy(NoCopy const&) = delete; // expected-note 2 {{deleted here}}
916};
917template <class T, class U>
918void test_dependent_param(T t, U) {
919 // expected-error@-1 {{call to deleted constructor of 'NoCopy<0>'}}
920 // expected-error@-2 {{call to deleted constructor of 'NoCopy<1>'}}
921 ((void)t);
922 co_return 42;
923}
924template void test_dependent_param(NoCopy<0>, NoCopy<1>); // expected-note {{requested here}}
Eric Fiselier166c6e62017-07-10 01:27:22 +0000925
926namespace CoroHandleMemberFunctionTest {
927struct CoroMemberTag {};
928struct BadCoroMemberTag {};
929
930template <class T, class U>
931constexpr bool IsSameV = false;
932template <class T>
933constexpr bool IsSameV<T, T> = true;
934
935template <class T>
936struct TypeTest {
937 template <class U>
938 static constexpr bool IsSame = IsSameV<T, U>;
939
940 template <class... Args>
941 static constexpr bool MatchesArgs = IsSameV<T,
942 std::experimental::coroutine_traits<CoroMemberTag, Args...>>;
943};
944
945template <class T>
946struct AwaitReturnsType {
947 bool await_ready() const;
948 void await_suspend(...) const;
949 T await_resume() const;
950};
951
952template <class... CoroTraitsArgs>
953struct CoroMemberPromise {
954 using TraitsT = std::experimental::coroutine_traits<CoroTraitsArgs...>;
955 using TypeTestT = TypeTest<TraitsT>;
956 using AwaitTestT = AwaitReturnsType<TypeTestT>;
957
958 CoroMemberTag get_return_object();
959 suspend_always initial_suspend();
960 suspend_always final_suspend();
961
962 AwaitTestT yield_value(int);
963
964 void return_void();
965 void unhandled_exception();
966};
967
968} // namespace CoroHandleMemberFunctionTest
969
970template <class... Args>
971struct ::std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::CoroMemberTag, Args...> {
972 using promise_type = CoroHandleMemberFunctionTest::CoroMemberPromise<CoroHandleMemberFunctionTest::CoroMemberTag, Args...>;
973};
974
975namespace CoroHandleMemberFunctionTest {
976struct TestType {
977
978 CoroMemberTag test_qual() {
979 auto TC = co_yield 0;
980 static_assert(TC.MatchesArgs<TestType &>, "");
981 static_assert(!TC.MatchesArgs<TestType>, "");
982 static_assert(!TC.MatchesArgs<TestType *>, "");
983 }
984
985 CoroMemberTag test_sanity(int *) const {
986 auto TC = co_yield 0;
987 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static_assert failed}}
988 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static_assert failed}}
989 static_assert(TC.MatchesArgs<const TestType &, int *>, "");
990 }
991
992 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
993 auto TC = co_yield 0;
994 static_assert(TC.MatchesArgs<const TestType &, int *, const float &&, volatile void *volatile>, "");
995 }
996
997 CoroMemberTag test_qual() const volatile {
998 auto TC = co_yield 0;
999 static_assert(TC.MatchesArgs<const volatile TestType &>, "");
1000 }
1001
1002 CoroMemberTag test_ref_qual() & {
1003 auto TC = co_yield 0;
1004 static_assert(TC.MatchesArgs<TestType &>, "");
1005 }
1006 CoroMemberTag test_ref_qual() const & {
1007 auto TC = co_yield 0;
1008 static_assert(TC.MatchesArgs<TestType const &>, "");
1009 }
1010 CoroMemberTag test_ref_qual() && {
1011 auto TC = co_yield 0;
1012 static_assert(TC.MatchesArgs<TestType &&>, "");
1013 }
1014 CoroMemberTag test_ref_qual(const char *&) const volatile && {
1015 auto TC = co_yield 0;
1016 static_assert(TC.MatchesArgs<TestType const volatile &&, const char *&>, "");
1017 }
1018
1019 CoroMemberTag test_args(int) {
1020 auto TC = co_yield 0;
1021 static_assert(TC.MatchesArgs<TestType &, int>, "");
1022 }
1023 CoroMemberTag test_args(int, long &, void *) const {
1024 auto TC = co_yield 0;
1025 static_assert(TC.MatchesArgs<TestType const &, int, long &, void *>, "");
1026 }
1027
1028 template <class... Args>
1029 CoroMemberTag test_member_template(Args...) const && {
1030 auto TC = co_yield 0;
1031 static_assert(TC.template MatchesArgs<TestType const &&, Args...>, "");
1032 }
1033
1034 static CoroMemberTag test_static() {
1035 auto TC = co_yield 0;
1036 static_assert(TC.MatchesArgs<>, "");
1037 static_assert(!TC.MatchesArgs<TestType>, "");
1038 static_assert(!TC.MatchesArgs<TestType &>, "");
1039 static_assert(!TC.MatchesArgs<TestType *>, "");
1040 }
1041
1042 static CoroMemberTag test_static(volatile void *const, char &&) {
1043 auto TC = co_yield 0;
1044 static_assert(TC.MatchesArgs<volatile void *const, char &&>, "");
1045 }
1046
1047 template <class Dummy>
1048 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1049 auto TC = co_yield 0;
1050 using TCT = decltype(TC);
1051 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1052 static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
1053 }
1054
1055 BadCoroMemberTag test_diagnostics() {
1056 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, CoroHandleMemberFunctionTest::TestType &>' has no member named 'promise_type'}}
1057 co_return;
1058 }
1059 BadCoroMemberTag test_diagnostics(int) const && {
1060 // 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'}}
1061 co_return;
1062 }
1063
1064 static BadCoroMemberTag test_static_diagnostics(long *) {
1065 // expected-error@-1 {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, long *>' has no member named 'promise_type'}}
1066 co_return;
1067 }
1068};
1069
1070template CoroMemberTag TestType::test_member_template(long, const char *) const &&;
1071template CoroMemberTag TestType::test_static_template<void>(const char *volatile &, unsigned);
1072
1073template <class... Args>
1074struct DepTestType {
1075
1076 CoroMemberTag test_sanity(int *) const {
1077 auto TC = co_yield 0;
1078 static_assert(TC.template MatchesArgs<const DepTestType &>, ""); // expected-error {{static_assert failed}}
1079 static_assert(TC.template MatchesArgs<>, ""); // expected-error {{static_assert failed}}
1080 static_assert(TC.template MatchesArgs<const DepTestType &, int *>, "");
1081 }
1082
1083 CoroMemberTag test_qual() {
1084 auto TC = co_yield 0;
1085 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1086 static_assert(!TC.template MatchesArgs<DepTestType>, "");
1087 static_assert(!TC.template MatchesArgs<DepTestType *>, "");
1088 }
1089
1090 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1091 auto TC = co_yield 0;
1092 static_assert(TC.template MatchesArgs<const DepTestType &, int *, const float &&, volatile void *volatile>, "");
1093 }
1094
1095 CoroMemberTag test_qual() const volatile {
1096 auto TC = co_yield 0;
1097 static_assert(TC.template MatchesArgs<const volatile DepTestType &>, "");
1098 }
1099
1100 CoroMemberTag test_ref_qual() & {
1101 auto TC = co_yield 0;
1102 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1103 }
1104 CoroMemberTag test_ref_qual() const & {
1105 auto TC = co_yield 0;
1106 static_assert(TC.template MatchesArgs<DepTestType const &>, "");
1107 }
1108 CoroMemberTag test_ref_qual() && {
1109 auto TC = co_yield 0;
1110 static_assert(TC.template MatchesArgs<DepTestType &&>, "");
1111 }
1112 CoroMemberTag test_ref_qual(const char *&) const volatile && {
1113 auto TC = co_yield 0;
1114 static_assert(TC.template MatchesArgs<DepTestType const volatile &&, const char *&>, "");
1115 }
1116
1117 CoroMemberTag test_args(int) {
1118 auto TC = co_yield 0;
1119 static_assert(TC.template MatchesArgs<DepTestType &, int>, "");
1120 }
1121 CoroMemberTag test_args(int, long &, void *) const {
1122 auto TC = co_yield 0;
1123 static_assert(TC.template MatchesArgs<DepTestType const &, int, long &, void *>, "");
1124 }
1125
1126 template <class... UArgs>
1127 CoroMemberTag test_member_template(UArgs...) const && {
1128 auto TC = co_yield 0;
1129 static_assert(TC.template MatchesArgs<DepTestType const &&, UArgs...>, "");
1130 }
1131
1132 static CoroMemberTag test_static() {
1133 auto TC = co_yield 0;
1134 using TCT = decltype(TC);
1135 static_assert(TCT::MatchesArgs<>, "");
1136 static_assert(!TCT::MatchesArgs<DepTestType>, "");
1137 static_assert(!TCT::MatchesArgs<DepTestType &>, "");
1138 static_assert(!TCT::MatchesArgs<DepTestType *>, "");
1139
1140 // Ensure diagnostics are actually being generated here
1141 static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static_assert failed}}
1142 }
1143
1144 static CoroMemberTag test_static(volatile void *const, char &&) {
1145 auto TC = co_yield 0;
1146 using TCT = decltype(TC);
1147 static_assert(TCT::MatchesArgs<volatile void *const, char &&>, "");
1148 }
1149
1150 template <class Dummy>
1151 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1152 auto TC = co_yield 0;
1153 using TCT = decltype(TC);
1154 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1155 static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
1156 }
1157};
1158
1159template struct DepTestType<int>; // expected-note {{requested here}}
1160template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&;
1161
1162template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);
1163
1164} // namespace CoroHandleMemberFunctionTest