Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaCXX / coroutines.cpp
blob2292932583fff620eaa73e915a7ce4b38e52838a
1 // This file contains references to sections of the Coroutines TS, which can be
2 // found at http://wg21.link/coroutines.
4 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s -fcxx-exceptions -fexceptions -Wunused-result
5 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -fcxx-exceptions -fexceptions -Wunused-result
7 void no_coroutine_traits_bad_arg_await() {
8 co_await a; // expected-error {{include <coroutine>}}
9 // expected-error@-1 {{use of undeclared identifier 'a'}}
12 void no_coroutine_traits_bad_arg_yield() {
13 co_yield a; // expected-error {{include <coroutine>}}
14 // expected-error@-1 {{use of undeclared identifier 'a'}}
18 void no_coroutine_traits_bad_arg_return() {
19 co_return a; // expected-error {{include <coroutine>}}
20 // expected-error@-1 {{use of undeclared identifier 'a'}}
23 void no_coroutine_traits() {
24 co_await 4; // expected-error {{std::coroutine_traits type was not found; include <coroutine>}}
27 namespace std {
29 template <class... Args>
30 struct void_t_imp {
31 using type = void;
33 template <class... Args>
34 using void_t = typename void_t_imp<Args...>::type;
36 template <class T, class = void>
37 struct traits_sfinae_base {};
39 template <class T>
40 struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
41 using promise_type = typename T::promise_type;
44 template <class Ret, class... Args>
45 struct coroutine_traits : public traits_sfinae_base<Ret> {};
46 } // end of namespace std
48 template<typename Promise> struct coro {};
49 template <typename Promise, typename... Ps>
50 struct std::coroutine_traits<coro<Promise>, Ps...> {
51 using promise_type = Promise;
54 struct awaitable {
55 bool await_ready() noexcept;
56 template <typename F>
57 void await_suspend(F) noexcept;
58 void await_resume() noexcept;
59 } a;
61 struct suspend_always {
62 bool await_ready() noexcept { return false; }
63 template <typename F>
64 void await_suspend(F) noexcept;
65 void await_resume() noexcept {}
68 struct suspend_never {
69 bool await_ready() noexcept { return true; }
70 template <typename F>
71 void await_suspend(F) noexcept;
72 void await_resume() noexcept {}
75 struct auto_await_suspend {
76 bool await_ready();
77 template <typename F> auto await_suspend(F) {}
78 void await_resume();
81 struct DummyVoidTag {};
82 DummyVoidTag no_specialization() { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<DummyVoidTag>' has no member named 'promise_type'}}
83 co_await a;
86 template <typename... T>
87 struct std::coroutine_traits<int, T...> {};
89 int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<int>' has no member named 'promise_type'}}
90 co_await a;
93 int no_promise_type_multiple_awaits(int) { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<int, int>' has no member named 'promise_type'}}
94 co_await a;
95 co_await a;
98 template <>
99 struct std::coroutine_traits<double, double> { typedef int promise_type; };
100 double bad_promise_type(double) { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<double, double>::promise_type' (aka 'int') is not a class}}
101 co_await a;
104 template <>
105 struct std::coroutine_traits<double, int> {
106 struct promise_type {};
108 double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}}
109 co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits<double, int>::promise_type'}}
112 struct promise; // expected-note {{forward declaration}}
113 struct promise_void;
114 struct void_tag {};
115 template <typename... T>
116 struct std::coroutine_traits<void, T...> { using promise_type = promise; };
117 template <typename... T>
118 struct std::coroutine_traits<void, void_tag, T...> { using promise_type = promise_void; };
120 // FIXME: This diagnostic is terrible.
121 void undefined_promise() { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<void>::promise_type' (aka 'promise') is an incomplete type}}
122 co_await a;
125 struct yielded_thing { const char *p; short a, b; };
127 struct not_awaitable {};
129 struct promise {
130 void get_return_object();
131 suspend_always initial_suspend();
132 suspend_always final_suspend() noexcept;
133 awaitable yield_value(int); // expected-note 2{{candidate}}
134 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}}
135 not_awaitable yield_value(void()); // expected-note 2{{candidate}}
136 void return_value(int); // expected-note 2{{here}}
137 void unhandled_exception();
140 struct promise_void {
141 void get_return_object();
142 suspend_always initial_suspend();
143 suspend_always final_suspend() noexcept;
144 void return_void();
145 void unhandled_exception();
148 void no_coroutine_handle() { // expected-error {{std::coroutine_handle type was not found; include <coroutine> before defining a coroutine}}
149 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
150 co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}}
153 namespace std {
154 template <class PromiseType = void>
155 struct coroutine_handle {
156 static coroutine_handle from_address(void *) noexcept;
158 template <>
159 struct coroutine_handle<void> {
160 template <class PromiseType>
161 coroutine_handle(coroutine_handle<PromiseType>) noexcept;
162 static coroutine_handle from_address(void *) noexcept;
164 } // namespace std
166 void yield() {
167 co_yield 0;
168 co_yield {"foo", 1, 2};
169 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{implicit conversion}} expected-warning {{braces around scalar}}
170 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}}
171 co_yield {"foo"};
172 co_yield "foo"; // expected-error {{no matching}}
173 co_yield 1.0;
174 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
177 void check_auto_await_suspend() {
178 co_await auto_await_suspend{}; // Should compile successfully.
181 void coreturn(int n) {
182 co_await a;
183 if (n == 0)
184 co_return 3;
185 if (n == 1)
186 co_return {4}; // expected-warning {{braces around scalar initializer}}
187 if (n == 2)
188 co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char[4]'}}
189 co_return 42;
192 template <class T>
193 void co_await_non_dependent_arg(T) {
194 co_await a;
196 template void co_await_non_dependent_arg(int);
198 void mixed_yield() {
199 co_yield 0; // expected-note {{use of 'co_yield'}}
200 return; // expected-error {{not allowed in coroutine}}
203 void mixed_yield_invalid() {
204 co_yield blah; // expected-error {{use of undeclared identifier}}
205 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
206 return; // expected-error {{return statement not allowed in coroutine}}
209 template <class T>
210 void mixed_yield_template(T) {
211 co_yield blah; // expected-error {{use of undeclared identifier}}
212 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
213 return; // expected-error {{return statement not allowed in coroutine}}
216 template <class T>
217 void mixed_yield_template2(T) {
218 co_yield 42;
219 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
220 return; // expected-error {{return statement not allowed in coroutine}}
223 template <class T>
224 void mixed_yield_template3(T v) {
225 co_yield blah(v);
226 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}}
227 return; // expected-error {{return statement not allowed in coroutine}}
230 void mixed_await() {
231 co_await a; // expected-note {{use of 'co_await'}}
232 return; // expected-error {{not allowed in coroutine}}
235 void mixed_await_invalid() {
236 co_await 42; // expected-error {{'int' is not a structure or union}}
237 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
238 return; // expected-error {{not allowed in coroutine}}
241 template <class T>
242 void mixed_await_template(T) {
243 co_await 42;
244 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
245 return; // expected-error {{not allowed in coroutine}}
248 template <class T>
249 void mixed_await_template2(T v) {
250 co_await v; // expected-error {{'long' is not a structure or union}}
251 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}}
252 return; // expected-error {{not allowed in coroutine}}
254 template void mixed_await_template2(long); // expected-note {{requested here}}
256 void only_coreturn(void_tag) {
257 co_return; // OK
260 void mixed_coreturn(void_tag, bool b) {
261 if (b)
262 co_return; // expected-note {{use of 'co_return'}}
263 else
264 return; // expected-error {{not allowed in coroutine}}
267 void mixed_coreturn_invalid(bool b) {
268 if (b)
269 co_return; // expected-note {{use of 'co_return'}}
270 // expected-error@-1 {{no member named 'return_void' in 'promise'}}
271 else
272 return; // expected-error {{not allowed in coroutine}}
275 template <class T>
276 void mixed_coreturn_template(void_tag, bool b, T v) {
277 if (b)
278 co_return v; // expected-note {{use of 'co_return'}}
279 // expected-error@-1 {{no member named 'return_value' in 'promise_void'}}
280 else
281 return; // expected-error {{not allowed in coroutine}}
283 template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}}
285 template <class T>
286 void mixed_coreturn_template2(bool b, T) {
287 if (b)
288 co_return v; // expected-note {{use of 'co_return'}}
289 // expected-error@-1 {{use of undeclared identifier 'v'}}
290 else
291 return; // expected-error {{not allowed in coroutine}}
294 struct CtorDtor {
295 CtorDtor() {
296 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
298 CtorDtor(awaitable a) {
299 // The spec doesn't say this is ill-formed, but it must be.
300 co_await a; // expected-error {{'co_await' cannot be used in a constructor}}
302 ~CtorDtor() {
303 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}}
305 void operator=(CtorDtor&) {
306 co_yield 0; // OK.
308 void operator=(CtorDtor const &) {
309 co_yield 0; // OK.
311 void operator=(CtorDtor &&) {
312 co_await a; // OK.
314 void operator=(CtorDtor const &&) {
315 co_await a; // OK.
317 void operator=(int) {
318 co_await a; // OK. Not a special member
322 namespace std { class type_info; }
324 void unevaluated() {
325 decltype(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}}
328 void unevaluated2() {
329 sizeof(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}}
332 void unevaluated3() {
333 typeid(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}}
336 void unevaluated4() {
337 decltype(co_yield 1); // expected-error {{'co_yield' cannot be used in an unevaluated context}}
340 void unevaluated5() {
341 sizeof(co_yield 2); // expected-error {{'co_yield' cannot be used in an unevaluated context}}
344 void unevaluated6() {
345 typeid(co_yield 3); // expected-error {{'co_yield' cannot be used in an unevaluated context}}
348 // [expr.await]p2: "An await-expression shall not appear in a default argument."
349 // FIXME: A better diagnostic would explicitly state that default arguments are
350 // not allowed. A user may not understand that this is "outside a function."
351 void default_argument(int arg = co_await 0) {} // expected-error {{'co_await' cannot be used outside a function}}
353 void await_in_catch_coroutine() {
354 try {
355 } catch (...) { // FIXME: Emit a note diagnostic pointing out the try handler on this line.
356 []() -> void { co_await a; }(); // OK
357 co_await a; // expected-error {{'co_await' cannot be used in the handler of a try block}}
361 void await_nested_in_catch_coroutine() {
362 try {
363 } catch (...) { // FIXME: Emit a note diagnostic pointing out the try handler on this line.
364 try {
365 co_await a; // expected-error {{'co_await' cannot be used in the handler of a try block}}
366 []() -> void { co_await a; }(); // OK
367 } catch (...) {
368 co_return 123;
373 void await_in_lambda_in_catch_coroutine() {
374 try {
375 } catch (...) {
376 []() -> void { co_await a; }(); // OK
380 void yield_in_catch_coroutine() {
381 try {
382 } catch (...) {
383 co_yield 1; // expected-error {{'co_yield' cannot be used in the handler of a try block}}
387 void return_in_catch_coroutine() {
388 try {
389 } catch (...) {
390 co_return 123; // OK
394 constexpr auto constexpr_deduced_return_coroutine() {
395 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}}
396 // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}}
399 void varargs_coroutine(const char *, ...) {
400 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}}
403 auto deduced_return_coroutine() {
404 co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}}
407 struct outer {};
408 struct await_arg_1 {};
409 struct await_arg_2 {};
411 namespace adl_ns {
412 struct coawait_arg_type {};
413 awaitable operator co_await(coawait_arg_type) noexcept;
416 namespace dependent_operator_co_await_lookup {
417 template<typename T> void await_template(T t) {
418 // no unqualified lookup results
419 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}}
420 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}}
422 template void await_template(awaitable);
424 struct indirectly_awaitable { indirectly_awaitable(outer); };
425 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}}
426 template void await_template(indirectly_awaitable);
428 struct not_awaitable {};
429 template void await_template(not_awaitable); // expected-note {{instantiation}}
431 template<typename T> void await_template_2(T t) {
432 // one unqualified lookup result
433 co_await t;
435 template void await_template(outer); // expected-note {{instantiation}}
436 template void await_template_2(outer);
438 struct transform_awaitable {};
439 struct transformed {};
441 struct transform_promise {
442 typedef transform_awaitable await_arg;
443 coro<transform_promise> get_return_object();
444 transformed initial_suspend();
445 ::adl_ns::coawait_arg_type final_suspend() noexcept;
446 transformed await_transform(transform_awaitable);
447 void unhandled_exception();
448 void return_void();
450 template <class AwaitArg>
451 struct basic_promise {
452 typedef AwaitArg await_arg;
453 coro<basic_promise> get_return_object();
454 awaitable initial_suspend();
455 awaitable final_suspend() noexcept;
456 void unhandled_exception();
457 void return_void();
460 awaitable operator co_await(await_arg_1);
462 template <typename T, typename U>
463 coro<T> await_template_3(U t) {
464 co_await t;
467 template coro<basic_promise<await_arg_1>> await_template_3<basic_promise<await_arg_1>>(await_arg_1);
469 template <class T, int I = 0>
470 struct dependent_member {
471 coro<T> mem_fn() const {
472 co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}}
474 template <class U>
475 coro<T> dep_mem_fn(U t) {
476 co_await t;
480 template <>
481 struct dependent_member<long> {
482 // FIXME this diagnostic is terrible
483 coro<transform_promise> mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
484 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
485 // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
486 co_await transform_awaitable{};
487 // expected-error@-1 {{no member named 'await_ready'}}
489 template <class R, class U>
490 coro<R> dep_mem_fn(U u) { co_await u; }
493 awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}}
495 template struct dependent_member<basic_promise<await_arg_1>, 0>;
496 template struct dependent_member<basic_promise<await_arg_2>, 0>; // expected-note {{in instantiation}}
498 template <>
499 coro<transform_promise>
500 // FIXME this diagnostic is terrible
501 dependent_member<long>::dep_mem_fn<transform_promise>(int) { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}}
502 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
503 //expected-note@+1 {{function is a coroutine due to use of 'co_await' here}}
504 co_await transform_awaitable{};
505 // expected-error@-1 {{no member named 'await_ready'}}
508 void operator co_await(transform_awaitable) = delete;
509 awaitable operator co_await(transformed);
511 template coro<transform_promise>
512 dependent_member<long>::dep_mem_fn<transform_promise>(transform_awaitable);
514 template <>
515 coro<transform_promise> dependent_member<long>::dep_mem_fn<transform_promise>(long) {
516 co_await transform_awaitable{};
519 template <>
520 struct dependent_member<int> {
521 coro<transform_promise> mem_fn() const {
522 co_await transform_awaitable{};
526 template coro<transform_promise> await_template_3<transform_promise>(transform_awaitable);
527 template struct dependent_member<transform_promise>;
528 template coro<transform_promise> dependent_member<transform_promise>::dep_mem_fn(transform_awaitable);
531 struct yield_fn_tag {};
532 template <>
533 struct std::coroutine_traits<void, yield_fn_tag> {
534 struct promise_type {
535 // FIXME: add an await_transform overload for functions
536 awaitable yield_value(int());
537 void return_value(int());
539 suspend_never initial_suspend();
540 suspend_never final_suspend() noexcept;
541 void get_return_object();
542 void unhandled_exception();
546 namespace placeholder {
547 awaitable f(), f(int); // expected-note 4{{possible target}}
548 int g(), g(int); // expected-note 2{{candidate}}
549 void x() {
550 co_await f; // expected-error {{reference to overloaded function}}
552 void y() {
553 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}}
555 void z() {
556 co_await a;
557 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}}
560 void x(yield_fn_tag) {
561 co_await f; // expected-error {{reference to overloaded function}}
563 void y(yield_fn_tag) {
564 co_yield g;
566 void z(yield_fn_tag) {
567 co_await a;
568 co_return g;
572 struct bad_promise_1 {
573 suspend_always initial_suspend();
574 suspend_always final_suspend() noexcept;
575 void unhandled_exception();
576 void return_void();
578 coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}}
579 co_await a;
582 struct bad_promise_2 {
583 coro<bad_promise_2> get_return_object();
584 suspend_always final_suspend() noexcept;
585 void unhandled_exception();
586 void return_void();
588 // FIXME: This shouldn't happen twice
589 coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}}
590 co_await a;
593 struct bad_promise_3 {
594 coro<bad_promise_3> get_return_object();
595 suspend_always initial_suspend();
596 void unhandled_exception();
597 void return_void();
599 coro<bad_promise_3> missing_final_suspend() noexcept { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}}
600 co_await a;
603 struct bad_promise_4 {
604 coro<bad_promise_4> get_return_object();
605 not_awaitable initial_suspend();
606 suspend_always final_suspend() noexcept;
607 void return_void();
609 // FIXME: This diagnostic is terrible.
610 coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
611 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
612 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
615 struct bad_promise_5 {
616 coro<bad_promise_5> get_return_object();
617 suspend_always initial_suspend();
618 not_awaitable final_suspend() noexcept;
619 void return_void();
621 // FIXME: This diagnostic is terrible.
622 coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}}
623 // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}}
624 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}}
627 struct bad_promise_6 {
628 coro<bad_promise_6> get_return_object();
629 suspend_always initial_suspend();
630 suspend_always final_suspend() noexcept;
631 void unhandled_exception();
632 void return_void(); // expected-note 2 {{member 'return_void' first declared here}}
633 void return_value(int) const; // expected-note 2 {{member 'return_value' first declared here}}
634 void return_value(int);
636 coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
637 co_await a;
640 template <class T>
641 coro<T> bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}}
642 co_await a;
644 template coro<bad_promise_6> bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}}
646 struct bad_promise_7 { // expected-note 2 {{defined here}}
647 coro<bad_promise_7> get_return_object();
648 suspend_always initial_suspend();
649 suspend_always final_suspend() noexcept;
650 void return_void();
652 coro<bad_promise_7> no_unhandled_exception() { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}}
653 co_await a;
656 template <class T>
657 coro<T> no_unhandled_exception_dependent(T) { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}}
658 co_await a;
660 template coro<bad_promise_7> no_unhandled_exception_dependent(bad_promise_7); // expected-note {{in instantiation}}
662 struct bad_promise_base {
663 private:
664 void return_void(); // expected-note 2 {{declared private here}}
666 struct bad_promise_8 : bad_promise_base {
667 coro<bad_promise_8> get_return_object();
668 suspend_always initial_suspend();
669 suspend_always final_suspend() noexcept;
670 void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{marked unavailable here}}
671 void unhandled_exception() const;
672 void unhandled_exception(void *) const;
674 coro<bad_promise_8> calls_unhandled_exception() {
675 // expected-error@-1 {{'unhandled_exception' is unavailable}}
676 // expected-error@-2 {{'return_void' is a private member}}
677 co_await a;
680 template <class T>
681 coro<T> calls_unhandled_exception_dependent(T) {
682 // expected-error@-1 {{'unhandled_exception' is unavailable}}
683 // expected-error@-2 {{'return_void' is a private member}}
684 co_await a;
686 template coro<bad_promise_8> calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}}
688 struct bad_promise_9 {
689 coro<bad_promise_9> get_return_object();
690 suspend_always initial_suspend();
691 suspend_always final_suspend() noexcept;
692 void await_transform(void *);
693 awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly marked unavailable}}
694 void return_void();
695 void unhandled_exception();
697 coro<bad_promise_9> calls_await_transform() {
698 co_await 42; // expected-error {{'await_transform' is unavailable}}
701 struct bad_promise_10 {
702 coro<bad_promise_10> get_return_object();
703 suspend_always initial_suspend();
704 suspend_always final_suspend() noexcept;
705 int await_transform;
706 void return_void();
707 void unhandled_exception();
709 coro<bad_promise_10> bad_coawait() {
710 // FIXME this diagnostic is terrible
711 co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}}
712 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}}
715 struct call_operator {
716 template <class... Args>
717 awaitable operator()(Args...) const { return a; }
719 void ret_void();
720 struct good_promise_1 {
721 coro<good_promise_1> get_return_object();
722 suspend_always initial_suspend();
723 suspend_always final_suspend() noexcept;
724 void unhandled_exception();
725 static const call_operator await_transform;
726 using Fn = void (*)();
727 Fn return_void = ret_void;
729 const call_operator good_promise_1::await_transform;
730 coro<good_promise_1> ok_static_coawait() {
731 // FIXME this diagnostic is terrible
732 co_await 42;
735 template<typename T> void ok_generic_lambda_coawait_PR41909() {
736 [](auto& arg) -> coro<good_promise_1> { // expected-warning {{expression result unused}}
737 co_await 12;
739 [](auto &arg) -> coro<good_promise_1> {
740 co_await 24;
741 }("argument");
742 [](auto &arg) ->coro<good_promise_1> { // expected-warning {{expression result unused}}
743 []() -> coro<good_promise_1> {
744 co_await 36;
746 co_await 48;
749 template void ok_generic_lambda_coawait_PR41909<int>(); // expected-note {{in instantiation of function template specialization 'ok_generic_lambda_coawait_PR41909<int>' requested here}}
751 template <> struct std::coroutine_traits<int, int, const char **> { using promise_type = promise; };
753 int main(int, const char**) {
754 co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}}
757 struct good_promise_2 {
758 float get_return_object();
759 suspend_always initial_suspend();
760 suspend_always final_suspend() noexcept;
761 void return_void();
762 void unhandled_exception();
764 template <> struct std::coroutine_handle<good_promise_2> {};
766 template <> struct std::coroutine_traits<float> { using promise_type = good_promise_2; };
768 float badly_specialized_coro_handle() { // expected-error {{std::coroutine_handle must have a member named 'from_address'}}
769 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}}
770 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
773 namespace std {
774 struct nothrow_t {};
775 constexpr nothrow_t nothrow = {};
778 using SizeT = decltype(sizeof(int));
780 void* operator new(SizeT __sz, const std::nothrow_t&) noexcept;
781 void operator delete(void* __p, const std::nothrow_t&) noexcept;
785 struct promise_on_alloc_failure_tag {};
787 template <>
788 struct std::coroutine_traits<int, promise_on_alloc_failure_tag> {
789 struct promise_type {
790 int get_return_object() {}
791 suspend_always initial_suspend() { return {}; }
792 suspend_always final_suspend() noexcept { return {}; }
793 void return_void() {}
794 int get_return_object_on_allocation_failure(); // expected-error{{'promise_type': 'get_return_object_on_allocation_failure()' must be a static member function}}
795 void unhandled_exception();
799 extern "C" int f(promise_on_alloc_failure_tag) {
800 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
803 struct bad_promise_11 {
804 coro<bad_promise_11> get_return_object();
805 suspend_always initial_suspend();
806 suspend_always final_suspend() noexcept;
807 void unhandled_exception();
808 void return_void();
810 private:
811 static coro<bad_promise_11> get_return_object_on_allocation_failure(); // expected-note 2 {{declared private here}}
813 coro<bad_promise_11> private_alloc_failure_handler() {
814 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
815 co_return; // FIXME: Add a "declared coroutine here" note.
818 template <class T>
819 coro<T> dependent_private_alloc_failure_handler(T) {
820 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}}
821 co_return; // FIXME: Add a "declared coroutine here" note.
823 template coro<bad_promise_11> dependent_private_alloc_failure_handler(bad_promise_11);
824 // expected-note@-1 {{requested here}}
826 struct bad_promise_12 {
827 coro<bad_promise_12> get_return_object();
828 suspend_always initial_suspend();
829 suspend_always final_suspend() noexcept;
830 void unhandled_exception();
831 void return_void();
832 static coro<bad_promise_12> get_return_object_on_allocation_failure();
834 static void* operator new(SizeT);
835 // 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()'}}
837 coro<bad_promise_12> throwing_in_class_new() { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
838 co_return;
841 template <class T>
842 coro<T> dependent_throwing_in_class_new(T) { // expected-note {{call to 'operator new' implicitly required by coroutine function here}}
843 co_return;
845 template coro<bad_promise_12> dependent_throwing_in_class_new(bad_promise_12); // expected-note {{requested here}}
848 struct good_promise_13 {
849 coro<good_promise_13> get_return_object();
850 suspend_always initial_suspend();
851 suspend_always final_suspend() noexcept;
852 void unhandled_exception();
853 void return_void();
854 static coro<good_promise_13> get_return_object_on_allocation_failure();
856 coro<good_promise_13> uses_nothrow_new() {
857 co_return;
860 template <class T>
861 coro<T> dependent_uses_nothrow_new(T) {
862 co_return;
864 template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13);
866 struct good_promise_custom_new_operator {
867 coro<good_promise_custom_new_operator> get_return_object();
868 suspend_always initial_suspend();
869 suspend_always final_suspend() noexcept;
870 void return_void();
871 void unhandled_exception();
872 void *operator new(SizeT, double, float, int);
875 coro<good_promise_custom_new_operator>
876 good_coroutine_calls_custom_new_operator(double, float, int) {
877 co_return;
880 struct coroutine_nonstatic_member_struct;
882 struct good_promise_nonstatic_member_custom_new_operator {
883 coro<good_promise_nonstatic_member_custom_new_operator> get_return_object();
884 suspend_always initial_suspend();
885 suspend_always final_suspend() noexcept;
886 void return_void();
887 void unhandled_exception();
888 void *operator new(SizeT, coroutine_nonstatic_member_struct &, double);
891 struct good_promise_noexcept_custom_new_operator {
892 static coro<good_promise_noexcept_custom_new_operator> get_return_object_on_allocation_failure();
893 coro<good_promise_noexcept_custom_new_operator> get_return_object();
894 suspend_always initial_suspend();
895 suspend_always final_suspend() noexcept;
896 void return_void();
897 void unhandled_exception();
898 void *operator new(SizeT, double, float, int) noexcept;
901 coro<good_promise_noexcept_custom_new_operator>
902 good_coroutine_calls_noexcept_custom_new_operator(double, float, int) {
903 co_return;
906 struct mismatch_gro_type_tag1 {};
907 template <>
908 struct std::coroutine_traits<int, mismatch_gro_type_tag1> {
909 struct promise_type {
910 void get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
911 suspend_always initial_suspend() { return {}; }
912 suspend_always final_suspend() noexcept { return {}; }
913 void return_void() {}
914 void unhandled_exception();
918 extern "C" int f(mismatch_gro_type_tag1) {
919 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
920 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
923 struct mismatch_gro_type_tag2 {};
924 template <>
925 struct std::coroutine_traits<int, mismatch_gro_type_tag2> {
926 struct promise_type {
927 void *get_return_object() {} //expected-note {{member 'get_return_object' declared here}}
928 suspend_always initial_suspend() { return {}; }
929 suspend_always final_suspend() noexcept { return {}; }
930 void return_void() {}
931 void unhandled_exception();
935 extern "C" int f(mismatch_gro_type_tag2) {
936 // cxx23-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void *'}}
937 // cxx14_20-error@-2 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}}
938 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
941 struct mismatch_gro_type_tag3 {};
942 template <>
943 struct std::coroutine_traits<int, mismatch_gro_type_tag3> {
944 struct promise_type {
945 int get_return_object() {}
946 static void get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared here}}
947 suspend_always initial_suspend() { return {}; }
948 suspend_always final_suspend() noexcept { return {}; }
949 void return_void() {}
950 void unhandled_exception();
954 extern "C" int f(mismatch_gro_type_tag3) {
955 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}}
956 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
960 struct mismatch_gro_type_tag4 {};
961 template <>
962 struct std::coroutine_traits<int, mismatch_gro_type_tag4> {
963 struct promise_type {
964 int get_return_object() {}
965 static char *get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared}}
966 suspend_always initial_suspend() { return {}; }
967 suspend_always final_suspend() noexcept { return {}; }
968 void return_void() {}
969 void unhandled_exception();
973 extern "C" int f(mismatch_gro_type_tag4) {
974 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}}
975 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}}
978 struct promise_no_return_func {
979 coro<promise_no_return_func> get_return_object();
980 suspend_always initial_suspend();
981 suspend_always final_suspend() noexcept;
982 void unhandled_exception();
984 // [dcl.fct.def.coroutine]/p6
985 // If searches for the names return_­void and return_­value in the scope of
986 // the promise type each find any declarations, the program is ill-formed.
987 // [Note 1: If return_­void is found, flowing off the end of a coroutine is
988 // equivalent to a co_­return with no operand. Otherwise, flowing off the end
989 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). —
990 // end note]
992 // So it isn't ill-formed if the promise doesn't define return_value and return_void.
993 // It is just a potential UB.
994 coro<promise_no_return_func> no_return_value_or_return_void() {
995 co_await a;
998 // The following two tests that it would emit correct diagnostic message
999 // if we co_return in `promise_no_return_func`.
1000 coro<promise_no_return_func> no_return_value_or_return_void_2() {
1001 co_return; // expected-error {{no member named 'return_void'}}
1004 coro<promise_no_return_func> no_return_value_or_return_void_3() {
1005 co_return 43; // expected-error {{no member named 'return_value'}}
1008 struct bad_await_suspend_return {
1009 bool await_ready();
1010 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}}
1011 char await_suspend(std::coroutine_handle<>);
1012 void await_resume();
1014 struct bad_await_ready_return {
1015 // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}}
1016 void await_ready();
1017 bool await_suspend(std::coroutine_handle<>);
1018 void await_resume();
1020 struct await_ready_explicit_bool {
1021 struct BoolT {
1022 explicit operator bool() const;
1024 BoolT await_ready();
1025 void await_suspend(std::coroutine_handle<>);
1026 void await_resume();
1028 template <class SuspendTy>
1029 struct await_suspend_type_test {
1030 bool await_ready();
1031 // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}}
1032 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}}
1033 SuspendTy await_suspend(std::coroutine_handle<>);
1034 // cxx20_23-warning@-1 {{volatile-qualified return type 'const volatile bool' is deprecated}}
1035 void await_resume();
1037 void test_bad_suspend() {
1039 // FIXME: The actual error emitted here is terrible, and no number of notes can save it.
1040 bad_await_ready_return a;
1041 // expected-error@+1 {{value of type 'void' is not contextually convertible to 'bool'}}
1042 co_await a; // expected-note {{call to 'await_ready' implicitly required by coroutine function here}}
1045 bad_await_suspend_return b;
1046 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
1049 await_ready_explicit_bool c;
1050 co_await c; // OK
1053 await_suspend_type_test<bool &&> a;
1054 await_suspend_type_test<bool &> b;
1055 await_suspend_type_test<const void> c;
1056 await_suspend_type_test<const volatile bool> d; // cxx20_23-note {{in instantiation of template class}}
1057 co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
1058 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}}
1059 co_await c; // OK
1060 co_await d; // OK
1064 template <int ID = 0>
1065 struct NoCopy {
1066 NoCopy(NoCopy const&) = delete; // expected-note 2 {{deleted here}}
1068 template <class T, class U>
1069 void test_dependent_param(T t, U) {
1070 // expected-error@-1 {{call to deleted constructor of 'NoCopy<>'}}
1071 // expected-error@-2 {{call to deleted constructor of 'NoCopy<1>'}}
1072 ((void)t);
1073 co_return 42;
1075 template void test_dependent_param(NoCopy<0>, NoCopy<1>); // expected-note {{requested here}}
1077 namespace CoroHandleMemberFunctionTest {
1078 struct CoroMemberTag {};
1079 struct BadCoroMemberTag {};
1081 template <class T, class U>
1082 constexpr bool IsSameV = false;
1083 template <class T>
1084 constexpr bool IsSameV<T, T> = true;
1086 template <class T>
1087 struct TypeTest {
1088 template <class U>
1089 static constexpr bool IsSame = IsSameV<T, U>;
1091 template <class... Args>
1092 static constexpr bool MatchesArgs = IsSameV<T,
1093 std::coroutine_traits<CoroMemberTag, Args...>>;
1096 template <class T>
1097 struct AwaitReturnsType {
1098 bool await_ready() const;
1099 void await_suspend(...) const;
1100 T await_resume() const;
1103 template <class... CoroTraitsArgs>
1104 struct CoroMemberPromise {
1105 using TraitsT = std::coroutine_traits<CoroTraitsArgs...>;
1106 using TypeTestT = TypeTest<TraitsT>;
1107 using AwaitTestT = AwaitReturnsType<TypeTestT>;
1109 CoroMemberTag get_return_object();
1110 suspend_always initial_suspend();
1111 suspend_always final_suspend() noexcept;
1113 AwaitTestT yield_value(int);
1115 void return_void();
1116 void unhandled_exception();
1119 } // namespace CoroHandleMemberFunctionTest
1121 template <class... Args>
1122 struct ::std::coroutine_traits<CoroHandleMemberFunctionTest::CoroMemberTag, Args...> {
1123 using promise_type = CoroHandleMemberFunctionTest::CoroMemberPromise<CoroHandleMemberFunctionTest::CoroMemberTag, Args...>;
1126 namespace CoroHandleMemberFunctionTest {
1127 struct TestType {
1129 CoroMemberTag test_qual() {
1130 auto TC = co_yield 0;
1131 static_assert(TC.MatchesArgs<TestType &>, "");
1132 static_assert(!TC.MatchesArgs<TestType>, "");
1133 static_assert(!TC.MatchesArgs<TestType *>, "");
1136 CoroMemberTag test_asserts(int *) const {
1137 auto TC = co_yield 0;
1138 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static assertion failed}}
1139 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static assertion failed}}
1140 static_assert(TC.MatchesArgs<const TestType &, int *>, "");
1143 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1144 // cxx20_23-warning@-1 {{volatile-qualified parameter type}}
1145 auto TC = co_yield 0;
1146 static_assert(TC.MatchesArgs<const TestType &, int *, const float &&, volatile void *volatile>, "");
1149 CoroMemberTag test_qual() const volatile {
1150 auto TC = co_yield 0;
1151 static_assert(TC.MatchesArgs<const volatile TestType &>, "");
1154 CoroMemberTag test_ref_qual() & {
1155 auto TC = co_yield 0;
1156 static_assert(TC.MatchesArgs<TestType &>, "");
1158 CoroMemberTag test_ref_qual() const & {
1159 auto TC = co_yield 0;
1160 static_assert(TC.MatchesArgs<TestType const &>, "");
1162 CoroMemberTag test_ref_qual() && {
1163 auto TC = co_yield 0;
1164 static_assert(TC.MatchesArgs<TestType &&>, "");
1166 CoroMemberTag test_ref_qual(const char *&) const volatile && {
1167 auto TC = co_yield 0;
1168 static_assert(TC.MatchesArgs<TestType const volatile &&, const char *&>, "");
1171 CoroMemberTag test_args(int) {
1172 auto TC = co_yield 0;
1173 static_assert(TC.MatchesArgs<TestType &, int>, "");
1175 CoroMemberTag test_args(int, long &, void *) const {
1176 auto TC = co_yield 0;
1177 static_assert(TC.MatchesArgs<TestType const &, int, long &, void *>, "");
1180 template <class... Args>
1181 CoroMemberTag test_member_template(Args...) const && {
1182 auto TC = co_yield 0;
1183 static_assert(TC.template MatchesArgs<TestType const &&, Args...>, "");
1186 static CoroMemberTag test_static() {
1187 auto TC = co_yield 0;
1188 static_assert(TC.MatchesArgs<>, "");
1189 static_assert(!TC.MatchesArgs<TestType>, "");
1190 static_assert(!TC.MatchesArgs<TestType &>, "");
1191 static_assert(!TC.MatchesArgs<TestType *>, "");
1194 static CoroMemberTag test_static(volatile void *const, char &&) {
1195 auto TC = co_yield 0;
1196 static_assert(TC.MatchesArgs<volatile void *const, char &&>, "");
1199 template <class Dummy>
1200 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1201 auto TC = co_yield 0;
1202 using TCT = decltype(TC);
1203 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1204 static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, "");
1207 BadCoroMemberTag test_diagnostics() {
1208 // expected-error@-1 {{this function cannot be a coroutine: 'std::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, CoroHandleMemberFunctionTest::TestType &>' has no member named 'promise_type'}}
1209 co_return;
1211 BadCoroMemberTag test_diagnostics(int) const && {
1212 // expected-error@-1 {{this function cannot be a coroutine: 'std::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, const CoroHandleMemberFunctionTest::TestType &&, int>' has no member named 'promise_type'}}
1213 co_return;
1216 static BadCoroMemberTag test_static_diagnostics(long *) {
1217 // expected-error@-1 {{this function cannot be a coroutine: 'std::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, long *>' has no member named 'promise_type'}}
1218 co_return;
1222 template CoroMemberTag TestType::test_member_template(long, const char *) const &&;
1223 template CoroMemberTag TestType::test_static_template<void>(const char *volatile &, unsigned);
1225 template <class... Args>
1226 struct DepTestType {
1228 CoroMemberTag test_asserts(int *) const {
1229 auto TC = co_yield 0;
1230 static_assert(TC.template MatchesArgs<const DepTestType &>, ""); // expected-error {{static assertion failed}}
1231 static_assert(TC.template MatchesArgs<>, ""); // expected-error {{static assertion failed}}
1232 static_assert(TC.template MatchesArgs<const DepTestType &, int *>, "");
1235 CoroMemberTag test_qual() {
1236 auto TC = co_yield 0;
1237 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1238 static_assert(!TC.template MatchesArgs<DepTestType>, "");
1239 static_assert(!TC.template MatchesArgs<DepTestType *>, "");
1242 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const {
1243 // cxx20_23-warning@-1 {{volatile-qualified parameter type}}
1244 auto TC = co_yield 0;
1245 static_assert(TC.template MatchesArgs<const DepTestType &, int *, const float &&, volatile void *volatile>, "");
1248 CoroMemberTag test_qual() const volatile {
1249 auto TC = co_yield 0;
1250 static_assert(TC.template MatchesArgs<const volatile DepTestType &>, "");
1253 CoroMemberTag test_ref_qual() & {
1254 auto TC = co_yield 0;
1255 static_assert(TC.template MatchesArgs<DepTestType &>, "");
1257 CoroMemberTag test_ref_qual() const & {
1258 auto TC = co_yield 0;
1259 static_assert(TC.template MatchesArgs<DepTestType const &>, "");
1261 CoroMemberTag test_ref_qual() && {
1262 auto TC = co_yield 0;
1263 static_assert(TC.template MatchesArgs<DepTestType &&>, "");
1265 CoroMemberTag test_ref_qual(const char *&) const volatile && {
1266 auto TC = co_yield 0;
1267 static_assert(TC.template MatchesArgs<DepTestType const volatile &&, const char *&>, "");
1270 CoroMemberTag test_args(int) {
1271 auto TC = co_yield 0;
1272 static_assert(TC.template MatchesArgs<DepTestType &, int>, "");
1274 CoroMemberTag test_args(int, long &, void *) const {
1275 auto TC = co_yield 0;
1276 static_assert(TC.template MatchesArgs<DepTestType const &, int, long &, void *>, "");
1279 template <class... UArgs>
1280 CoroMemberTag test_member_template(UArgs...) const && {
1281 auto TC = co_yield 0;
1282 static_assert(TC.template MatchesArgs<DepTestType const &&, UArgs...>, "");
1285 static CoroMemberTag test_static() {
1286 auto TC = co_yield 0;
1287 using TCT = decltype(TC);
1288 static_assert(TCT::MatchesArgs<>, "");
1289 static_assert(!TCT::MatchesArgs<DepTestType>, "");
1290 static_assert(!TCT::MatchesArgs<DepTestType &>, "");
1291 static_assert(!TCT::MatchesArgs<DepTestType *>, "");
1293 // Ensure diagnostics are actually being generated here
1294 static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static assertion failed}}
1297 static CoroMemberTag test_static(volatile void *const, char &&) {
1298 auto TC = co_yield 0;
1299 using TCT = decltype(TC);
1300 static_assert(TCT::MatchesArgs<volatile void *const, char &&>, "");
1303 template <class Dummy>
1304 static CoroMemberTag test_static_template(const char *volatile &, unsigned) {
1305 auto TC = co_yield 0;
1306 using TCT = decltype(TC);
1307 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, "");
1308 static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, "");
1312 template struct DepTestType<int>; // expected-note 2{{requested here}}
1313 template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&;
1315 template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned);
1317 struct bad_promise_deleted_constructor {
1318 // expected-note@+1 {{'bad_promise_deleted_constructor' has been explicitly marked deleted here}}
1319 bad_promise_deleted_constructor() = delete;
1320 coro<bad_promise_deleted_constructor> get_return_object();
1321 suspend_always initial_suspend();
1322 suspend_always final_suspend() noexcept;
1323 void return_void();
1324 void unhandled_exception();
1327 coro<bad_promise_deleted_constructor>
1328 bad_coroutine_calls_deleted_promise_constructor() {
1329 // expected-error@-1 {{call to deleted constructor of 'std::coroutine_traits<coro<CoroHandleMemberFunctionTest::bad_promise_deleted_constructor>>::promise_type' (aka 'CoroHandleMemberFunctionTest::bad_promise_deleted_constructor')}}
1330 co_return;
1333 // Test that, when the promise type has a constructor whose signature matches
1334 // that of the coroutine function, that constructor is used. If no matching
1335 // constructor exists, the default constructor is used as a fallback. If no
1336 // matching constructors exist at all, an error is emitted. This is an
1337 // experimental feature that will be proposed for the Coroutines TS.
1339 struct good_promise_default_constructor {
1340 good_promise_default_constructor(double, float, int);
1341 good_promise_default_constructor() = default;
1342 coro<good_promise_default_constructor> get_return_object();
1343 suspend_always initial_suspend();
1344 suspend_always final_suspend() noexcept;
1345 void return_void();
1346 void unhandled_exception();
1349 coro<good_promise_default_constructor>
1350 good_coroutine_calls_default_constructor() {
1351 co_return;
1354 struct some_class;
1356 struct good_promise_custom_constructor {
1357 good_promise_custom_constructor(some_class&, float, int);
1358 good_promise_custom_constructor(double, float, int);
1359 good_promise_custom_constructor() = delete;
1360 coro<good_promise_custom_constructor> get_return_object();
1361 suspend_always initial_suspend();
1362 suspend_always final_suspend() noexcept;
1363 void return_void();
1364 void unhandled_exception();
1367 coro<good_promise_custom_constructor>
1368 good_coroutine_calls_custom_constructor(double, float, int) {
1369 co_return;
1372 struct some_class {
1373 coro<good_promise_custom_constructor>
1374 good_coroutine_calls_custom_constructor(float, int) {
1375 co_return;
1377 coro<good_promise_custom_constructor>
1378 static good_coroutine_calls_custom_constructor(double, float, int) {
1379 co_return;
1383 struct bad_promise_no_matching_constructor {
1384 bad_promise_no_matching_constructor(int, int, int);
1385 // expected-note@+1 2 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}}
1386 bad_promise_no_matching_constructor() = delete;
1387 coro<bad_promise_no_matching_constructor> get_return_object();
1388 suspend_always initial_suspend();
1389 suspend_always final_suspend() noexcept;
1390 void return_void();
1391 void unhandled_exception();
1394 coro<bad_promise_no_matching_constructor>
1395 bad_coroutine_calls_with_no_matching_constructor(int, int) {
1396 // expected-error@-1 {{call to deleted constructor of 'std::coroutine_traits<coro<CoroHandleMemberFunctionTest::bad_promise_no_matching_constructor>, int, int>::promise_type' (aka 'CoroHandleMemberFunctionTest::bad_promise_no_matching_constructor')}}
1397 co_return;
1400 struct some_class2 {
1401 coro<bad_promise_no_matching_constructor>
1402 bad_coroutine_calls_with_no_matching_constructor(int, int, int) {
1403 // expected-error@-1 {{call to deleted constructor}}
1404 co_return;
1408 } // namespace CoroHandleMemberFunctionTest
1410 class awaitable_no_unused_warn {
1411 public:
1412 using handle_type = std::coroutine_handle<>;
1413 constexpr bool await_ready() noexcept { return false; }
1414 void await_suspend(handle_type) noexcept {}
1415 int await_resume() noexcept { return 1; }
1419 class awaitable_unused_warn {
1420 public:
1421 using handle_type = std::coroutine_handle<>;
1422 constexpr bool await_ready() noexcept { return false; }
1423 void await_suspend(handle_type) noexcept {}
1424 [[nodiscard]] int await_resume() noexcept { return 1; }
1427 template <class Await>
1428 struct check_warning_promise {
1429 coro<check_warning_promise> get_return_object();
1430 Await initial_suspend();
1431 Await final_suspend() noexcept;
1432 Await yield_value(int);
1433 void return_void();
1434 void unhandled_exception();
1438 coro<check_warning_promise<awaitable_no_unused_warn>>
1439 test_no_unused_warning() {
1440 co_await awaitable_no_unused_warn();
1441 co_yield 42;
1444 coro<check_warning_promise<awaitable_unused_warn>>
1445 test_unused_warning() {
1446 co_await awaitable_unused_warn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
1447 co_yield 42; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
1450 struct missing_await_ready {
1451 void await_suspend(std::coroutine_handle<>);
1452 void await_resume();
1454 struct missing_await_suspend {
1455 bool await_ready();
1456 void await_resume();
1458 struct missing_await_resume {
1459 bool await_ready();
1460 void await_suspend(std::coroutine_handle<>);
1463 void test_missing_awaitable_members() {
1464 co_await missing_await_ready{}; // expected-error {{no member named 'await_ready' in 'missing_await_ready'}}
1465 co_await missing_await_suspend{}; // expected-error {{no member named 'await_suspend' in 'missing_await_suspend'}}
1466 co_await missing_await_resume{}; // expected-error {{no member named 'await_resume' in 'missing_await_resume'}}
1469 __attribute__((__always_inline__))
1470 void warn_always_inline() { // expected-warning {{this coroutine may be split into pieces; not every piece is guaranteed to be inlined}}
1471 co_await suspend_always{};
1474 [[gnu::always_inline]]
1475 void warn_gnu_always_inline() { // expected-warning {{this coroutine may be split into pieces; not every piece is guaranteed to be inlined}}
1476 co_await suspend_always{};