blob: 8876a146557fcf6e9971748a46b4869e16cf887c [file] [log] [blame]
Gor Nishanovbbe1c072017-02-13 05:05:02 +00001// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions
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 {
25template <typename... T>
26struct coroutine_traits; // expected-note {{declared here}}
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000027}} // namespace std::experimental
Richard Smith9f690bd2015-10-27 06:02:45 +000028
Richard Smith2af65c42015-11-24 02:34:39 +000029template<typename Promise> struct coro {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000030template <typename Promise, typename... Ps>
31struct std::experimental::coroutine_traits<coro<Promise>, Ps...> {
Richard Smith2af65c42015-11-24 02:34:39 +000032 using promise_type = Promise;
33};
34
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +000035struct awaitable {
36 bool await_ready();
37 template <typename F> void await_suspend(F);
38 void await_resume();
39} a;
40
41struct suspend_always {
42 bool await_ready() { return false; }
43 template <typename F> void await_suspend(F);
44 void await_resume() {}
45};
46
47struct suspend_never {
48 bool await_ready() { return true; }
49 template <typename F> void await_suspend(F);
50 void await_resume() {}
51};
52
Richard Smith9f690bd2015-10-27 06:02:45 +000053void no_specialization() {
Gor Nishanov3e048bb2016-10-04 00:31:16 +000054 co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits<void>'}}
Richard Smith9f690bd2015-10-27 06:02:45 +000055}
56
Gor Nishanov3e048bb2016-10-04 00:31:16 +000057template <typename... T>
58struct std::experimental::coroutine_traits<int, T...> {};
Richard Smith9f690bd2015-10-27 06:02:45 +000059
Eric Fiselier89bf0e72017-03-06 22:52:28 +000060int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits<int>' has no member named 'promise_type'}}
61 co_await a;
Richard Smith9b2f53e2015-11-19 02:36:35 +000062}
63
Gor Nishanov3e048bb2016-10-04 00:31:16 +000064template <>
65struct std::experimental::coroutine_traits<double, double> { typedef int promise_type; };
Eric Fiselier89bf0e72017-03-06 22:52:28 +000066double 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}}
67 co_await a;
Richard Smith9f690bd2015-10-27 06:02:45 +000068}
69
Gor Nishanov3e048bb2016-10-04 00:31:16 +000070template <>
71struct std::experimental::coroutine_traits<double, int> {
Richard Smith23da82c2015-11-20 22:40:06 +000072 struct promise_type {};
73};
Eric Fiselier20f25cb2017-03-06 23:38:15 +000074double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}}
Gor Nishanov3e048bb2016-10-04 00:31:16 +000075 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 +000076}
77
Eric Fiselier89bf0e72017-03-06 22:52:28 +000078struct promise; // expected-note {{forward declaration}}
Eric Fiselier98131312016-10-06 21:23:38 +000079struct promise_void;
80struct void_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +000081template <typename... T>
82struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; };
Eric Fiselier98131312016-10-06 21:23:38 +000083template <typename... T>
84struct std::experimental::coroutine_traits<void, void_tag, T...>
85{ using promise_type = promise_void; };
Richard Smith9f690bd2015-10-27 06:02:45 +000086
Eric Fiselier20f25cb2017-03-06 23:38:15 +000087// FIXME: This diagnostic is terrible.
Eric Fiselier89bf0e72017-03-06 22:52:28 +000088void 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 +000089 co_await a;
90}
91
Richard Smithae3d1472015-11-20 22:47:10 +000092struct yielded_thing { const char *p; short a, b; };
Richard Smith23da82c2015-11-20 22:40:06 +000093
Richard Smithd7bed4d2015-11-22 02:57:17 +000094struct not_awaitable {};
95
Richard Smith23da82c2015-11-20 22:40:06 +000096struct promise {
Richard Smith2af65c42015-11-24 02:34:39 +000097 void get_return_object();
98 suspend_always initial_suspend();
99 suspend_always final_suspend();
Richard Smith71d403e2015-11-22 07:33:28 +0000100 awaitable yield_value(int); // expected-note 2{{candidate}}
101 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
102 not_awaitable yield_value(void()); // expected-note 2{{candidate}}
Richard Smith71d403e2015-11-22 07:33:28 +0000103 void return_value(int); // expected-note 2{{here}}
Richard Smith23da82c2015-11-20 22:40:06 +0000104};
105
Eric Fiselier98131312016-10-06 21:23:38 +0000106struct promise_void {
107 void get_return_object();
108 suspend_always initial_suspend();
109 suspend_always final_suspend();
Eric Fiselier98131312016-10-06 21:23:38 +0000110 void return_void();
111};
112
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000113void no_coroutine_handle() { // expected-error {{std::experimental::coroutine_handle type was not found; include <experimental/coroutine> before defining a coroutine}}
114 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
115 co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}}
116}
117
118namespace std {
119namespace experimental {
120template <class PromiseType = void>
121struct coroutine_handle {
122 static coroutine_handle from_address(void *);
123};
124template <>
125struct coroutine_handle<void> {
126 template <class PromiseType>
127 coroutine_handle(coroutine_handle<PromiseType>);
128 static coroutine_handle from_address(void *);
129};
130}} // namespace std::experimental
131
Richard Smith23da82c2015-11-20 22:40:06 +0000132void yield() {
133 co_yield 0;
Richard Smithae3d1472015-11-20 22:47:10 +0000134 co_yield {"foo", 1, 2};
135 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}}
136 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
137 co_yield {"foo"};
Richard Smith23da82c2015-11-20 22:40:06 +0000138 co_yield "foo"; // expected-error {{no matching}}
Richard Smithd7bed4d2015-11-22 02:57:17 +0000139 co_yield 1.0;
140 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Richard Smith23da82c2015-11-20 22:40:06 +0000141}
Richard Smith9f690bd2015-10-27 06:02:45 +0000142
Richard Smith4ba66602015-11-22 07:05:16 +0000143void coreturn(int n) {
144 co_await a;
145 if (n == 0)
146 co_return 3;
147 if (n == 1)
Eric Fiselier98131312016-10-06 21:23:38 +0000148 co_return {4}; // expected-warning {{braces around scalar initializer}}
Richard Smith4ba66602015-11-22 07:05:16 +0000149 if (n == 2)
150 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 +0000151 co_return 42;
Richard Smith4ba66602015-11-22 07:05:16 +0000152}
153
Eric Fiselier8d409e82017-03-09 05:01:31 +0000154template <class T>
155void co_await_non_dependent_arg(T) {
156 co_await a;
157}
158template void co_await_non_dependent_arg(int);
159
Richard Smithcfd53b42015-10-22 06:13:50 +0000160void mixed_yield() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000161 co_yield 0; // expected-note {{use of 'co_yield'}}
162 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000163}
164
Eric Fiseliercac0a592017-03-11 02:35:37 +0000165void mixed_yield_invalid() {
166 co_yield blah; // expected-error {{use of undeclared identifier}}
167 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
168 return; // expected-error {{return statement not allowed in coroutine}}
169}
170
171template <class T>
172void mixed_yield_template(T) {
173 co_yield blah; // expected-error {{use of undeclared identifier}}
174 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
175 return; // expected-error {{return statement not allowed in coroutine}}
176}
177
178template <class T>
179void mixed_yield_template2(T) {
180 co_yield 42;
181 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
182 return; // expected-error {{return statement not allowed in coroutine}}
183}
184
185template <class T>
186void mixed_yield_template3(T v) {
187 co_yield blah(v);
188 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
189 return; // expected-error {{return statement not allowed in coroutine}}
190}
191
Richard Smithcfd53b42015-10-22 06:13:50 +0000192void mixed_await() {
Richard Smith9f690bd2015-10-27 06:02:45 +0000193 co_await a; // expected-note {{use of 'co_await'}}
194 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000195}
196
Eric Fiseliercac0a592017-03-11 02:35:37 +0000197void mixed_await_invalid() {
198 co_await 42; // expected-error {{'int' is not a structure or union}}
199 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
200 return; // expected-error {{not allowed in coroutine}}
201}
202
203template <class T>
204void mixed_await_template(T) {
205 co_await 42;
206 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
207 return; // expected-error {{not allowed in coroutine}}
208}
209
210template <class T>
211void mixed_await_template2(T v) {
212 co_await v; // expected-error {{'long' is not a structure or union}}
213 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
214 return; // expected-error {{not allowed in coroutine}}
215}
216template void mixed_await_template2(long); // expected-note {{requested here}}
217
Eric Fiselier98131312016-10-06 21:23:38 +0000218void only_coreturn(void_tag) {
Gor Nishanovd97f6bf2017-01-10 00:08:31 +0000219 co_return; // OK
Richard Smithcfd53b42015-10-22 06:13:50 +0000220}
221
Eric Fiselier98131312016-10-06 21:23:38 +0000222void mixed_coreturn(void_tag, bool b) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000223 if (b)
Richard Smith9f690bd2015-10-27 06:02:45 +0000224 co_return; // expected-note {{use of 'co_return'}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000225 else
Richard Smith9f690bd2015-10-27 06:02:45 +0000226 return; // expected-error {{not allowed in coroutine}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000227}
228
Eric Fiseliercac0a592017-03-11 02:35:37 +0000229void mixed_coreturn_invalid(bool b) {
230 if (b)
231 co_return; // expected-note {{use of 'co_return'}}
232 // expected-error@-1 {{no member named 'return_void' in 'promise'}}
233 else
234 return; // expected-error {{not allowed in coroutine}}
235}
236
237template <class T>
238void mixed_coreturn_template(void_tag, bool b, T v) {
239 if (b)
240 co_return v; // expected-note {{use of 'co_return'}}
241 // expected-error@-1 {{no member named 'return_value' in 'promise_void'}}
242 else
243 return; // expected-error {{not allowed in coroutine}}
244}
245template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}}
246
247template <class T>
248void mixed_coreturn_template2(bool b, T) {
249 if (b)
250 co_return v; // expected-note {{use of 'co_return'}}
251 // expected-error@-1 {{use of undeclared identifier 'v'}}
252 else
253 return; // expected-error {{not allowed in coroutine}}
254}
255
Richard Smithcfd53b42015-10-22 06:13:50 +0000256struct CtorDtor {
257 CtorDtor() {
258 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
259 }
Richard Smith9f690bd2015-10-27 06:02:45 +0000260 CtorDtor(awaitable a) {
Richard Smithcfd53b42015-10-22 06:13:50 +0000261 // The spec doesn't say this is ill-formed, but it must be.
Richard Smith9f690bd2015-10-27 06:02:45 +0000262 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000263 }
264 ~CtorDtor() {
265 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
266 }
267 // FIXME: The spec says this is ill-formed.
268 void operator=(CtorDtor&) {
Eric Fiselierc8efda72016-10-27 18:43:28 +0000269 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
270 }
271 void operator=(CtorDtor const &) {
272 co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}}
273 }
274 void operator=(CtorDtor &&) {
275 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
276 }
277 void operator=(CtorDtor const &&) {
278 co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}}
279 }
280 void operator=(int) {
281 co_await a; // OK. Not a special member
Richard Smithcfd53b42015-10-22 06:13:50 +0000282 }
283};
284
Richard Smith744b2242015-11-20 02:54:01 +0000285void unevaluated() {
286 decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}}
287 sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}}
288 typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}}
289 decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
290 sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
291 typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}}
292}
293
Eric Fiselierc8efda72016-10-27 18:43:28 +0000294constexpr auto constexpr_deduced_return_coroutine() {
Richard Smith744b2242015-11-20 02:54:01 +0000295 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
Eric Fiselierc8efda72016-10-27 18:43:28 +0000296 // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
Richard Smithcfd53b42015-10-22 06:13:50 +0000297}
298
299void varargs_coroutine(const char *, ...) {
Richard Smith9f690bd2015-10-27 06:02:45 +0000300 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
301}
302
Eric Fiselierc8efda72016-10-27 18:43:28 +0000303auto deduced_return_coroutine() {
304 co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
305}
306
Richard Smith9f690bd2015-10-27 06:02:45 +0000307struct outer {};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000308struct await_arg_1 {};
309struct await_arg_2 {};
310
311namespace adl_ns {
312struct coawait_arg_type {};
313awaitable operator co_await(coawait_arg_type);
314}
Richard Smith9f690bd2015-10-27 06:02:45 +0000315
316namespace dependent_operator_co_await_lookup {
317 template<typename T> void await_template(T t) {
318 // no unqualified lookup results
319 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
320 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
321 };
322 template void await_template(awaitable);
323
324 struct indirectly_awaitable { indirectly_awaitable(outer); };
325 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
326 template void await_template(indirectly_awaitable);
327
328 struct not_awaitable {};
329 template void await_template(not_awaitable); // expected-note {{instantiation}}
330
331 template<typename T> void await_template_2(T t) {
332 // one unqualified lookup result
333 co_await t;
334 };
335 template void await_template(outer); // expected-note {{instantiation}}
336 template void await_template_2(outer);
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000337
338 struct transform_awaitable {};
339 struct transformed {};
340
341 struct transform_promise {
342 typedef transform_awaitable await_arg;
343 coro<transform_promise> get_return_object();
344 transformed initial_suspend();
345 ::adl_ns::coawait_arg_type final_suspend();
346 transformed await_transform(transform_awaitable);
347 };
348 template <class AwaitArg>
349 struct basic_promise {
350 typedef AwaitArg await_arg;
351 coro<basic_promise> get_return_object();
352 awaitable initial_suspend();
353 awaitable final_suspend();
354 };
355
356 awaitable operator co_await(await_arg_1);
357
358 template <typename T, typename U>
359 coro<T> await_template_3(U t) {
360 co_await t;
361 }
362
363 template coro<basic_promise<await_arg_1>> await_template_3<basic_promise<await_arg_1>>(await_arg_1);
364
365 template <class T, int I = 0>
366 struct dependent_member {
367 coro<T> mem_fn() const {
368 co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}}
369 }
370 template <class U>
371 coro<T> dep_mem_fn(U t) {
372 co_await t;
373 }
374 };
375
376 template <>
377 struct dependent_member<long> {
378 // FIXME this diagnostic is terrible
379 coro<transform_promise> mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
380 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
381 // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
382 co_await transform_awaitable{};
383 // expected-error@-1 {{no member named 'await_ready'}}
384 }
385 template <class R, class U>
386 coro<R> dep_mem_fn(U u) { co_await u; }
387 };
388
389 awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}}
390
391 template struct dependent_member<basic_promise<await_arg_1>, 0>;
392 template struct dependent_member<basic_promise<await_arg_2>, 0>; // expected-note {{in instantiation}}
393
394 template <>
395 coro<transform_promise>
396 // FIXME this diagnostic is terrible
397 dependent_member<long>::dep_mem_fn<transform_promise>(int) { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
398 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
399 //expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
400 co_await transform_awaitable{};
401 // expected-error@-1 {{no member named 'await_ready'}}
402 }
403
404 void operator co_await(transform_awaitable) = delete;
405 awaitable operator co_await(transformed);
406
407 template coro<transform_promise>
408 dependent_member<long>::dep_mem_fn<transform_promise>(transform_awaitable);
409
410 template <>
411 coro<transform_promise> dependent_member<long>::dep_mem_fn<transform_promise>(long) {
412 co_await transform_awaitable{};
413 }
414
415 template <>
416 struct dependent_member<int> {
417 coro<transform_promise> mem_fn() const {
418 co_await transform_awaitable{};
419 }
420 };
421
422 template coro<transform_promise> await_template_3<transform_promise>(transform_awaitable);
423 template struct dependent_member<transform_promise>;
424 template coro<transform_promise> dependent_member<transform_promise>::dep_mem_fn(transform_awaitable);
Richard Smithcfd53b42015-10-22 06:13:50 +0000425}
Richard Smith10610f72015-11-20 22:57:24 +0000426
Richard Smith71d403e2015-11-22 07:33:28 +0000427struct yield_fn_tag {};
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000428template <>
429struct std::experimental::coroutine_traits<void, yield_fn_tag> {
Richard Smith71d403e2015-11-22 07:33:28 +0000430 struct promise_type {
431 // FIXME: add an await_transform overload for functions
432 awaitable yield_value(int());
433 void return_value(int());
Richard Smith2af65c42015-11-24 02:34:39 +0000434
435 suspend_never initial_suspend();
436 suspend_never final_suspend();
437 void get_return_object();
Richard Smith71d403e2015-11-22 07:33:28 +0000438 };
439};
440
Richard Smith10610f72015-11-20 22:57:24 +0000441namespace placeholder {
Richard Smith71d403e2015-11-22 07:33:28 +0000442 awaitable f(), f(int); // expected-note 4{{possible target}}
443 int g(), g(int); // expected-note 2{{candidate}}
Richard Smith10610f72015-11-20 22:57:24 +0000444 void x() {
445 co_await f; // expected-error {{reference to overloaded function}}
446 }
447 void y() {
Richard Smith71d403e2015-11-22 07:33:28 +0000448 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
Richard Smith10610f72015-11-20 22:57:24 +0000449 }
450 void z() {
451 co_await a;
Richard Smith71d403e2015-11-22 07:33:28 +0000452 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
453 }
454
455 void x(yield_fn_tag) {
456 co_await f; // expected-error {{reference to overloaded function}}
457 }
458 void y(yield_fn_tag) {
459 co_yield g;
460 }
461 void z(yield_fn_tag) {
462 co_await a;
463 co_return g;
Richard Smith10610f72015-11-20 22:57:24 +0000464 }
465}
Richard Smith2af65c42015-11-24 02:34:39 +0000466
467struct bad_promise_1 {
468 suspend_always initial_suspend();
469 suspend_always final_suspend();
470};
471coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
472 co_await a;
473}
474
475struct bad_promise_2 {
476 coro<bad_promise_2> get_return_object();
477 // FIXME: We shouldn't offer a typo-correction here!
478 suspend_always final_suspend(); // expected-note {{here}}
479};
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000480// FIXME: This shouldn't happen twice
Richard Smith2af65c42015-11-24 02:34:39 +0000481coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
482 co_await a;
483}
484
485struct bad_promise_3 {
486 coro<bad_promise_3> get_return_object();
487 // FIXME: We shouldn't offer a typo-correction here!
488 suspend_always initial_suspend(); // expected-note {{here}}
489};
490coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
491 co_await a;
492}
493
494struct bad_promise_4 {
495 coro<bad_promise_4> get_return_object();
496 not_awaitable initial_suspend();
497 suspend_always final_suspend();
498};
499// FIXME: This diagnostic is terrible.
500coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000501 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
502 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000503}
504
505struct bad_promise_5 {
506 coro<bad_promise_5> get_return_object();
507 suspend_always initial_suspend();
508 not_awaitable final_suspend();
509};
510// FIXME: This diagnostic is terrible.
511coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000512 // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}}
513 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
Richard Smith2af65c42015-11-24 02:34:39 +0000514}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000515
Eric Fiselier709d1b32016-10-27 07:30:31 +0000516struct bad_promise_6 {
517 coro<bad_promise_6> get_return_object();
518 suspend_always initial_suspend();
519 suspend_always final_suspend();
520 void return_void();
521 void return_value(int) const;
522 void return_value(int);
523};
524coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
525 co_await a;
526}
527
528struct bad_promise_7 {
529 coro<bad_promise_7> get_return_object();
530 suspend_always initial_suspend();
531 suspend_always final_suspend();
532 void return_void();
533 void set_exception(int *);
534};
535coro<bad_promise_7> no_std_current_exc() {
536 // expected-error@-1 {{you need to include <exception> before defining a coroutine that implicitly uses 'set_exception'}}
537 co_await a;
538}
539
540namespace std {
541int *current_exception();
542}
543
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000544struct bad_promise_base {
545private:
546 void return_void();
547};
548struct bad_promise_8 : bad_promise_base {
Eric Fiselier709d1b32016-10-27 07:30:31 +0000549 coro<bad_promise_8> get_return_object();
550 suspend_always initial_suspend();
551 suspend_always final_suspend();
Eric Fiselier709d1b32016-10-27 07:30:31 +0000552 void set_exception(); // expected-note {{function not viable}}
553 void set_exception(int *) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
554 void set_exception(void *); // expected-note {{candidate function}}
555};
556coro<bad_promise_8> calls_set_exception() {
557 // expected-error@-1 {{call to unavailable member function 'set_exception'}}
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000558 // FIXME: also warn about private 'return_void' here. Even though building
559 // the call to set_exception has already failed.
Eric Fiselier709d1b32016-10-27 07:30:31 +0000560 co_await a;
561}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000562
Eric Fiselier20f25cb2017-03-06 23:38:15 +0000563struct bad_promise_9 {
564 coro<bad_promise_9> get_return_object();
565 suspend_always initial_suspend();
566 suspend_always final_suspend();
567 void await_transform(void *); // expected-note {{candidate}}
568 awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
569 void return_void();
570};
571coro<bad_promise_9> calls_await_transform() {
572 co_await 42; // expected-error {{call to unavailable member function 'await_transform'}}
573 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
574}
575
576struct bad_promise_10 {
577 coro<bad_promise_10> get_return_object();
578 suspend_always initial_suspend();
579 suspend_always final_suspend();
580 int await_transform;
581 void return_void();
582};
583coro<bad_promise_10> bad_coawait() {
584 // FIXME this diagnostic is terrible
585 co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}}
586 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
587}
588
589struct call_operator {
590 template <class... Args>
591 awaitable operator()(Args...) const { return a; }
592};
593void ret_void();
594struct good_promise_1 {
595 coro<good_promise_1> get_return_object();
596 suspend_always initial_suspend();
597 suspend_always final_suspend();
598 static const call_operator await_transform;
599 using Fn = void (*)();
600 Fn return_void = ret_void;
601};
602const call_operator good_promise_1::await_transform;
603coro<good_promise_1> ok_static_coawait() {
604 // FIXME this diagnostic is terrible
605 co_await 42;
606}
607
Gor Nishanov3e048bb2016-10-04 00:31:16 +0000608template<> struct std::experimental::coroutine_traits<int, int, const char**>
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000609{ using promise_type = promise; };
610
Eric Fiselierc8efda72016-10-27 18:43:28 +0000611int main(int, const char**) {
612 co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
Eric Fiselier7d5773e2016-09-30 22:38:31 +0000613}
Gor Nishanov6dcb0eb2017-03-09 03:09:43 +0000614
615struct good_promise_2 {
616 float get_return_object();
617 suspend_always initial_suspend();
618 suspend_always final_suspend();
619 void return_void();
620};
621template<> struct std::experimental::coroutine_handle<good_promise_2> {};
622
623template<> struct std::experimental::coroutine_traits<float>
624{ using promise_type = good_promise_2; };
625
626float badly_specialized_coro_handle() { // expected-error {{std::experimental::coroutine_handle missing a member named 'from_address'}}
627 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
628 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
629}