1 // This file contains references to sections of the Coroutines TS, which can be 2 // found at http://wg21.link/coroutines. 3 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 6 7 // Run without -verify to check the order of errors we show. 8 // RUN: not %clang_cc1 -std=c++20 -fsyntax-only %s -fcxx-exceptions -fexceptions -Wunused-result 2>&1 | FileCheck %s 9 10 void no_coroutine_traits_bad_arg_await() { 11 co_await a; // expected-error {{include <coroutine>}} 12 // expected-error@-1 {{use of undeclared identifier 'a'}} 13 } 14 15 void no_coroutine_traits_bad_arg_yield() { 16 co_yield a; // expected-error {{include <coroutine>}} 17 // expected-error@-1 {{use of undeclared identifier 'a'}} 18 } 19 20 21 void no_coroutine_traits_bad_arg_return() { 22 co_return a; // expected-error {{include <coroutine>}} 23 // expected-error@-1 {{use of undeclared identifier 'a'}} 24 } 25 26 void no_coroutine_traits() { 27 co_await 4; // expected-error {{std::coroutine_traits type was not found; include <coroutine>}} 28 } 29 30 namespace std { 31 32 template <class... Args> 33 struct void_t_imp { 34 using type = void; 35 }; 36 template <class... Args> 37 using void_t = typename void_t_imp<Args...>::type; 38 39 template <class T, class = void> 40 struct traits_sfinae_base {}; 41 42 template <class T> 43 struct traits_sfinae_base<T, void_t<typename T::promise_type>> { 44 using promise_type = typename T::promise_type; 45 }; 46 47 template <class Ret, class... Args> 48 struct coroutine_traits : public traits_sfinae_base<Ret> {}; 49 } // end of namespace std 50 51 template<typename Promise> struct coro {}; 52 template <typename Promise, typename... Ps> 53 struct std::coroutine_traits<coro<Promise>, Ps...> { 54 using promise_type = Promise; 55 }; 56 57 struct awaitable { 58 bool await_ready() noexcept; 59 template <typename F> 60 void await_suspend(F) noexcept; 61 void await_resume() noexcept; 62 } a; 63 64 struct suspend_always { 65 bool await_ready() noexcept { return false; } 66 template <typename F> 67 void await_suspend(F) noexcept; 68 void await_resume() noexcept {} 69 }; 70 71 struct suspend_never { 72 bool await_ready() noexcept { return true; } 73 template <typename F> 74 void await_suspend(F) noexcept; 75 void await_resume() noexcept {} 76 }; 77 78 struct auto_await_suspend { 79 bool await_ready(); 80 template <typename F> auto await_suspend(F) {} 81 void await_resume(); 82 }; 83 84 struct DummyVoidTag {}; 85 DummyVoidTag no_specialization() { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<DummyVoidTag>' has no member named 'promise_type'}} 86 co_await a; 87 } 88 89 template <typename... T> 90 struct std::coroutine_traits<int, T...> {}; 91 92 int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<int>' has no member named 'promise_type'}} 93 co_await a; 94 } 95 96 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'}} 97 co_await a; 98 co_await a; 99 } 100 101 template <> 102 struct std::coroutine_traits<double, double> { typedef int promise_type; }; 103 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}} 104 co_await a; 105 } 106 107 template <> 108 struct std::coroutine_traits<double, int> { 109 struct promise_type {}; 110 }; 111 double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}} 112 co_yield 0; // expected-error {{no member named 'yield_value' in 'std::coroutine_traits<double, int>::promise_type'}} 113 } 114 115 struct promise; // expected-note {{forward declaration}} 116 struct promise_void; 117 struct void_tag {}; 118 template <typename... T> 119 struct std::coroutine_traits<void, T...> { using promise_type = promise; }; 120 template <typename... T> 121 struct std::coroutine_traits<void, void_tag, T...> { using promise_type = promise_void; }; 122 123 // FIXME: This diagnostic is terrible. 124 void undefined_promise() { // expected-error {{this function cannot be a coroutine: 'std::coroutine_traits<void>::promise_type' (aka 'promise') is an incomplete type}} 125 co_await a; 126 } 127 128 struct yielded_thing { const char *p; short a, b; }; 129 130 struct not_awaitable {}; 131 132 struct promise { 133 void get_return_object(); 134 suspend_always initial_suspend(); 135 suspend_always final_suspend() noexcept; 136 awaitable yield_value(int); // expected-note 2{{candidate}} 137 awaitable yield_value(yielded_thing); // expected-note 2{{candidate}} 138 not_awaitable yield_value(void()); // expected-note 2{{candidate}} 139 void return_value(int); // expected-note 2{{here}} 140 void unhandled_exception(); 141 }; 142 143 struct promise_void { 144 void get_return_object(); 145 suspend_always initial_suspend(); 146 suspend_always final_suspend() noexcept; 147 void return_void(); 148 void unhandled_exception(); 149 }; 150 151 void no_coroutine_handle() { // expected-error {{std::coroutine_handle type was not found; include <coroutine> before defining a coroutine}} 152 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} 153 co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}} 154 } 155 156 namespace std { 157 template <class PromiseType = void> 158 struct coroutine_handle { 159 static coroutine_handle from_address(void *) noexcept; 160 static coroutine_handle from_promise(PromiseType &promise); 161 }; 162 template <> 163 struct coroutine_handle<void> { 164 template <class PromiseType> 165 coroutine_handle(coroutine_handle<PromiseType>) noexcept; 166 static coroutine_handle from_address(void *) noexcept; 167 template <class PromiseType> 168 static coroutine_handle from_promise(PromiseType &promise); 169 }; 170 } // namespace std 171 172 void yield() { 173 co_yield 0; 174 co_yield {"foo", 1, 2}; 175 co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{implicit conversion}} expected-warning {{braces around scalar}} 176 co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} 177 co_yield {"foo"}; 178 co_yield "foo"; // expected-error {{no matching}} 179 co_yield 1.0; 180 co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}} 181 } 182 183 void check_auto_await_suspend() { 184 co_await auto_await_suspend{}; // Should compile successfully. 185 } 186 187 void coreturn(int n) { 188 co_await a; 189 if (n == 0) 190 co_return 3; 191 if (n == 1) 192 co_return {4}; // expected-warning {{braces around scalar initializer}} 193 if (n == 2) 194 co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char[4]'}} 195 co_return 42; 196 } 197 198 template <class T> 199 void co_await_non_dependent_arg(T) { 200 co_await a; 201 } 202 template void co_await_non_dependent_arg(int); 203 204 void mixed_yield() { 205 co_yield 0; // expected-note {{use of 'co_yield'}} 206 return; // expected-error {{not allowed in coroutine}} 207 } 208 209 void mixed_yield_invalid() { 210 co_yield blah; // expected-error {{use of undeclared identifier}} 211 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} 212 return; // expected-error {{return statement not allowed in coroutine}} 213 } 214 215 void mixed_yield_return_first(bool b) { 216 if (b) { 217 return; // expected-error {{return statement not allowed in coroutine}} 218 } 219 co_yield 0; // expected-note {{function is a coroutine due to use of 'co_yield'}} 220 } 221 222 template<typename T> 223 void mixed_return_for_range(bool b, T t) { 224 if (b) { 225 return; // expected-error {{return statement not allowed in coroutine}} 226 } 227 for co_await (auto i : t){}; // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}} 228 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} 229 } 230 231 template <class T> 232 void mixed_yield_template(T) { 233 co_yield blah; // expected-error {{use of undeclared identifier}} 234 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} 235 return; // expected-error {{return statement not allowed in coroutine}} 236 } 237 238 template <class T> 239 void mixed_yield_template2(T) { 240 co_yield 42; 241 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} 242 return; // expected-error {{return statement not allowed in coroutine}} 243 } 244 245 template <class T> 246 void mixed_yield_template3(T v) { 247 co_yield blah(v); 248 // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} 249 return; // expected-error {{return statement not allowed in coroutine}} 250 } 251 252 void mixed_await() { 253 co_await a; // expected-note {{use of 'co_await'}} 254 return; // expected-error {{not allowed in coroutine}} 255 } 256 257 void mixed_await_invalid() { 258 co_await 42; // expected-error {{'int' is not a structure or union}} 259 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} 260 return; // expected-error {{not allowed in coroutine}} 261 } 262 263 template <class T> 264 void mixed_await_template(T) { 265 co_await 42; 266 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} 267 return; // expected-error {{not allowed in coroutine}} 268 } 269 270 template <class T> 271 void mixed_await_template2(T v) { 272 co_await v; // expected-error {{'long' is not a structure or union}} 273 // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} 274 return; // expected-error {{not allowed in coroutine}} 275 } 276 template void mixed_await_template2(long); // expected-note {{requested here}} 277 278 void only_coreturn(void_tag) { 279 co_return; // OK 280 } 281 282 void mixed_coreturn(void_tag, bool b) { 283 if (b) 284 co_return; // expected-note {{use of 'co_return'}} 285 else 286 return; // expected-error {{not allowed in coroutine}} 287 } 288 289 void mixed_coreturn_return_first(void_tag, bool b) { 290 if (b) 291 return; // expected-error {{not allowed in coroutine}} 292 else 293 co_return; // expected-note {{use of 'co_return'}} 294 } 295 296 void mixed_coreturn_invalid(bool b) { 297 if (b) 298 co_return; // expected-note {{use of 'co_return'}} 299 // expected-error@-1 {{no member named 'return_void' in 'promise'}} 300 else 301 return; // expected-error {{not allowed in coroutine}} 302 } 303 304 template <class T> 305 void mixed_coreturn_template(void_tag, bool b, T v) { 306 if (b) 307 co_return v; // expected-note {{use of 'co_return'}} 308 // expected-error@-1 {{no member named 'return_value' in 'promise_void'}} 309 else 310 return; // expected-error {{not allowed in coroutine}} 311 } 312 template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}} 313 314 template <class T> 315 void mixed_coreturn_template2(bool b, T) { 316 if (b) 317 co_return v; // expected-note {{use of 'co_return'}} 318 // expected-error@-1 {{use of undeclared identifier 'v'}} 319 else 320 return; // expected-error {{not allowed in coroutine}} 321 } 322 323 struct promise_handle; 324 325 struct Handle : std::coroutine_handle<promise_handle> { // expected-note 4{{not viable}} 326 // expected-note@-1 4{{not viable}} 327 using promise_type = promise_handle; 328 }; 329 330 struct promise_handle { 331 Handle get_return_object() noexcept { 332 { return Handle(std::coroutine_handle<Handle::promise_type>::from_promise(*this)); } 333 } 334 suspend_never initial_suspend() const noexcept { return {}; } 335 suspend_never final_suspend() const noexcept { return {}; } 336 void return_void() const noexcept {} 337 void unhandled_exception() const noexcept {} 338 }; 339 340 Handle mixed_return_value() { 341 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} 342 return 0; // expected-error {{return statement not allowed in coroutine}} 343 // expected-error@-1 {{no viable conversion from returned value of type}} 344 // Check that we first show that return is not allowed in coroutine. 345 // The error about bad conversion is most likely spurious so we prefer to have it afterwards. 346 // CHECK-NOT: error: no viable conversion from returned value of type 347 // CHECK: error: return statement not allowed in coroutine 348 // CHECK: error: no viable conversion from returned value of type 349 } 350 351 Handle mixed_return_value_return_first(bool b) { 352 if (b) { 353 return 0; // expected-error {{no viable conversion from returned value of type}} 354 // expected-error@-1 {{return statement not allowed in coroutine}} 355 } 356 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} 357 co_return 0; // expected-error {{no member named 'return_value' in 'promise_handle'}} 358 } 359 360 Handle mixed_multiple_returns(bool b) { 361 if (b) { 362 return 0; // expected-error {{no viable conversion from returned value of type}} 363 // expected-error@-1 {{return statement not allowed in coroutine}} 364 } 365 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} 366 // The error 'return statement not allowed in coroutine' should appear only once. 367 return 0; // expected-error {{no viable conversion from returned value of type}} 368 } 369 370 struct CtorDtor { 371 CtorDtor() { 372 co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}} 373 } 374 CtorDtor(awaitable a) { 375 // The spec doesn't say this is ill-formed, but it must be. 376 co_await a; // expected-error {{'co_await' cannot be used in a constructor}} 377 } 378 ~CtorDtor() { 379 co_return 0; // expected-error {{'co_return' cannot be used in a destructor}} 380 } 381 void operator=(CtorDtor&) { 382 co_yield 0; // OK. 383 } 384 void operator=(CtorDtor const &) { 385 co_yield 0; // OK. 386 } 387 void operator=(CtorDtor &&) { 388 co_await a; // OK. 389 } 390 void operator=(CtorDtor const &&) { 391 co_await a; // OK. 392 } 393 void operator=(int) { 394 co_await a; // OK. Not a special member 395 } 396 }; 397 398 namespace std { class type_info; } 399 400 void unevaluated() { 401 decltype(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}} 402 } 403 404 void unevaluated2() { 405 sizeof(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}} 406 } 407 408 void unevaluated3() { 409 typeid(co_await a); // expected-error {{'co_await' cannot be used in an unevaluated context}} 410 } 411 412 void unevaluated4() { 413 decltype(co_yield 1); // expected-error {{'co_yield' cannot be used in an unevaluated context}} 414 } 415 416 void unevaluated5() { 417 sizeof(co_yield 2); // expected-error {{'co_yield' cannot be used in an unevaluated context}} 418 } 419 420 void unevaluated6() { 421 typeid(co_yield 3); // expected-error {{'co_yield' cannot be used in an unevaluated context}} 422 } 423 424 // [expr.await]p2: "An await-expression shall not appear in a default argument." 425 // FIXME: A better diagnostic would explicitly state that default arguments are 426 // not allowed. A user may not understand that this is "outside a function." 427 void default_argument(int arg = co_await 0) {} // expected-error {{'co_await' cannot be used outside a function}} 428 429 void await_in_catch_coroutine() { 430 try { 431 } catch (...) { // FIXME: Emit a note diagnostic pointing out the try handler on this line. 432 []() -> void { co_await a; }(); // OK 433 co_await a; // expected-error {{'co_await' cannot be used in the handler of a try block}} 434 } 435 } 436 437 void await_nested_in_catch_coroutine() { 438 try { 439 } catch (...) { // FIXME: Emit a note diagnostic pointing out the try handler on this line. 440 try { 441 co_await a; // expected-error {{'co_await' cannot be used in the handler of a try block}} 442 []() -> void { co_await a; }(); // OK 443 } catch (...) { 444 co_return 123; 445 } 446 } 447 } 448 449 void await_in_lambda_in_catch_coroutine() { 450 try { 451 } catch (...) { 452 []() -> void { co_await a; }(); // OK 453 } 454 } 455 456 void yield_in_catch_coroutine() { 457 try { 458 } catch (...) { 459 co_yield 1; // expected-error {{'co_yield' cannot be used in the handler of a try block}} 460 } 461 } 462 463 void return_in_catch_coroutine() { 464 try { 465 } catch (...) { 466 co_return 123; // OK 467 } 468 } 469 470 constexpr auto constexpr_deduced_return_coroutine() { 471 co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}} 472 // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}} 473 } 474 475 void varargs_coroutine(const char *, ...) { 476 co_await a; // expected-error {{'co_await' cannot be used in a varargs function}} 477 } 478 479 auto deduced_return_coroutine() { 480 co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}} 481 } 482 483 struct outer {}; 484 struct await_arg_1 {}; 485 struct await_arg_2 {}; 486 487 namespace adl_ns { 488 struct coawait_arg_type {}; 489 awaitable operator co_await(coawait_arg_type) noexcept; 490 } 491 492 namespace dependent_operator_co_await_lookup { 493 template<typename T> void await_template(T t) { 494 // no unqualified lookup results 495 co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}} 496 // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}} 497 }; 498 template void await_template(awaitable); 499 500 struct indirectly_awaitable { indirectly_awaitable(outer); }; 501 awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}} 502 template void await_template(indirectly_awaitable); 503 504 struct not_awaitable {}; 505 template void await_template(not_awaitable); // expected-note {{instantiation}} 506 507 template<typename T> void await_template_2(T t) { 508 // one unqualified lookup result 509 co_await t; 510 }; 511 template void await_template(outer); // expected-note {{instantiation}} 512 template void await_template_2(outer); 513 514 struct transform_awaitable {}; 515 struct transformed {}; 516 517 struct transform_promise { 518 typedef transform_awaitable await_arg; 519 coro<transform_promise> get_return_object(); 520 transformed initial_suspend(); 521 ::adl_ns::coawait_arg_type final_suspend() noexcept; 522 transformed await_transform(transform_awaitable); 523 void unhandled_exception(); 524 void return_void(); 525 }; 526 template <class AwaitArg> 527 struct basic_promise { 528 typedef AwaitArg await_arg; 529 coro<basic_promise> get_return_object(); 530 awaitable initial_suspend(); 531 awaitable final_suspend() noexcept; 532 void unhandled_exception(); 533 void return_void(); 534 }; 535 536 awaitable operator co_await(await_arg_1); 537 538 template <typename T, typename U> 539 coro<T> await_template_3(U t) { 540 co_await t; 541 } 542 543 template coro<basic_promise<await_arg_1>> await_template_3<basic_promise<await_arg_1>>(await_arg_1); 544 545 template <class T, int I = 0> 546 struct dependent_member { 547 coro<T> mem_fn() const { 548 co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}} 549 } 550 template <class U> 551 coro<T> dep_mem_fn(U t) { 552 co_await t; 553 } 554 }; 555 556 template <> 557 struct dependent_member<long> { 558 // FIXME this diagnostic is terrible 559 coro<transform_promise> mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}} 560 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} 561 // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}} 562 co_await transform_awaitable{}; 563 // expected-error@-1 {{no member named 'await_ready'}} 564 } 565 template <class R, class U> 566 coro<R> dep_mem_fn(U u) { co_await u; } 567 }; 568 569 awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}} 570 571 template struct dependent_member<basic_promise<await_arg_1>, 0>; 572 template struct dependent_member<basic_promise<await_arg_2>, 0>; // expected-note {{in instantiation}} 573 574 template <> 575 coro<transform_promise> 576 // FIXME this diagnostic is terrible 577 dependent_member<long>::dep_mem_fn<transform_promise>(int) { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}} 578 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} 579 //expected-note@+1 {{function is a coroutine due to use of 'co_await' here}} 580 co_await transform_awaitable{}; 581 // expected-error@-1 {{no member named 'await_ready'}} 582 } 583 584 void operator co_await(transform_awaitable) = delete; 585 awaitable operator co_await(transformed); 586 587 template coro<transform_promise> 588 dependent_member<long>::dep_mem_fn<transform_promise>(transform_awaitable); 589 590 template <> 591 coro<transform_promise> dependent_member<long>::dep_mem_fn<transform_promise>(long) { 592 co_await transform_awaitable{}; 593 } 594 595 template <> 596 struct dependent_member<int> { 597 coro<transform_promise> mem_fn() const { 598 co_await transform_awaitable{}; 599 } 600 }; 601 602 template coro<transform_promise> await_template_3<transform_promise>(transform_awaitable); 603 template struct dependent_member<transform_promise>; 604 template coro<transform_promise> dependent_member<transform_promise>::dep_mem_fn(transform_awaitable); 605 } 606 607 struct yield_fn_tag {}; 608 template <> 609 struct std::coroutine_traits<void, yield_fn_tag> { 610 struct promise_type { 611 // FIXME: add an await_transform overload for functions 612 awaitable yield_value(int()); 613 void return_value(int()); 614 615 suspend_never initial_suspend(); 616 suspend_never final_suspend() noexcept; 617 void get_return_object(); 618 void unhandled_exception(); 619 }; 620 }; 621 622 namespace placeholder { 623 awaitable f(), f(int); // expected-note 4{{possible target}} 624 int g(), g(int); // expected-note 2{{candidate}} 625 void x() { 626 co_await f; // expected-error {{reference to overloaded function}} 627 } 628 void y() { 629 co_yield g; // expected-error {{no matching member function for call to 'yield_value'}} 630 } 631 void z() { 632 co_await a; 633 co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}} 634 } 635 636 void x(yield_fn_tag) { 637 co_await f; // expected-error {{reference to overloaded function}} 638 } 639 void y(yield_fn_tag) { 640 co_yield g; 641 } 642 void z(yield_fn_tag) { 643 co_await a; 644 co_return g; 645 } 646 } 647 648 struct bad_promise_1 { 649 suspend_always initial_suspend(); 650 suspend_always final_suspend() noexcept; 651 void unhandled_exception(); 652 void return_void(); 653 }; 654 coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}} 655 co_await a; 656 } 657 658 struct bad_promise_2 { 659 coro<bad_promise_2> get_return_object(); 660 suspend_always final_suspend() noexcept; 661 void unhandled_exception(); 662 void return_void(); 663 }; 664 // FIXME: This shouldn't happen twice 665 coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}} 666 co_await a; 667 } 668 669 struct bad_promise_3 { 670 coro<bad_promise_3> get_return_object(); 671 suspend_always initial_suspend(); 672 void unhandled_exception(); 673 void return_void(); 674 }; 675 coro<bad_promise_3> missing_final_suspend() noexcept { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}} 676 co_await a; 677 } 678 679 struct bad_promise_4 { 680 coro<bad_promise_4> get_return_object(); 681 not_awaitable initial_suspend(); 682 suspend_always final_suspend() noexcept; 683 void return_void(); 684 }; 685 // FIXME: This diagnostic is terrible. 686 coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} 687 // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} 688 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} 689 } 690 691 struct bad_promise_5 { 692 coro<bad_promise_5> get_return_object(); 693 suspend_always initial_suspend(); 694 not_awaitable final_suspend() noexcept; 695 void return_void(); 696 }; 697 // FIXME: This diagnostic is terrible. 698 coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} 699 // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}} 700 co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} 701 } 702 703 struct bad_promise_6 { 704 coro<bad_promise_6> get_return_object(); 705 suspend_always initial_suspend(); 706 suspend_always final_suspend() noexcept; 707 void unhandled_exception(); 708 void return_void(); // expected-note 2 {{member 'return_void' first declared here}} 709 void return_value(int) const; // expected-note 2 {{member 'return_value' first declared here}} 710 void return_value(int); 711 }; 712 coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} 713 co_await a; 714 } 715 716 template <class T> 717 coro<T> bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} 718 co_await a; 719 } 720 template coro<bad_promise_6> bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}} 721 722 struct bad_promise_7 { // expected-note 2 {{defined here}} 723 coro<bad_promise_7> get_return_object(); 724 suspend_always initial_suspend(); 725 suspend_always final_suspend() noexcept; 726 void return_void(); 727 }; 728 coro<bad_promise_7> no_unhandled_exception() { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}} 729 co_await a; 730 } 731 732 template <class T> 733 coro<T> no_unhandled_exception_dependent(T) { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}} 734 co_await a; 735 } 736 template coro<bad_promise_7> no_unhandled_exception_dependent(bad_promise_7); // expected-note {{in instantiation}} 737 738 struct bad_promise_base { 739 private: 740 void return_void(); // expected-note 2 {{declared private here}} 741 }; 742 struct bad_promise_8 : bad_promise_base { 743 coro<bad_promise_8> get_return_object(); 744 suspend_always initial_suspend(); 745 suspend_always final_suspend() noexcept; 746 void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{marked unavailable here}} 747 void unhandled_exception() const; 748 void unhandled_exception(void *) const; 749 }; 750 coro<bad_promise_8> calls_unhandled_exception() { 751 // expected-error@-1 {{'unhandled_exception' is unavailable}} 752 // expected-error@-2 {{'return_void' is a private member}} 753 co_await a; 754 } 755 756 template <class T> 757 coro<T> calls_unhandled_exception_dependent(T) { 758 // expected-error@-1 {{'unhandled_exception' is unavailable}} 759 // expected-error@-2 {{'return_void' is a private member}} 760 co_await a; 761 } 762 template coro<bad_promise_8> calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}} 763 764 struct bad_promise_9 { 765 coro<bad_promise_9> get_return_object(); 766 suspend_always initial_suspend(); 767 suspend_always final_suspend() noexcept; 768 void await_transform(void *); 769 awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly marked unavailable}} 770 void return_void(); 771 void unhandled_exception(); 772 }; 773 coro<bad_promise_9> calls_await_transform() { 774 co_await 42; // expected-error {{'await_transform' is unavailable}} 775 } 776 777 struct bad_promise_10 { 778 coro<bad_promise_10> get_return_object(); 779 suspend_always initial_suspend(); 780 suspend_always final_suspend() noexcept; 781 int await_transform; 782 void return_void(); 783 void unhandled_exception(); 784 }; 785 coro<bad_promise_10> bad_coawait() { 786 // FIXME this diagnostic is terrible 787 co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}} 788 // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}} 789 } 790 791 struct call_operator { 792 template <class... Args> 793 awaitable operator()(Args...) const { return a; } 794 }; 795 void ret_void(); 796 struct good_promise_1 { 797 coro<good_promise_1> get_return_object(); 798 suspend_always initial_suspend(); 799 suspend_always final_suspend() noexcept; 800 void unhandled_exception(); 801 static const call_operator await_transform; 802 using Fn = void (*)(); 803 Fn return_void = ret_void; 804 }; 805 const call_operator good_promise_1::await_transform; 806 coro<good_promise_1> ok_static_coawait() { 807 // FIXME this diagnostic is terrible 808 co_await 42; 809 } 810 811 template<typename T> void ok_generic_lambda_coawait_PR41909() { 812 [](auto& arg) -> coro<good_promise_1> { // expected-warning {{expression result unused}} 813 co_await 12; 814 }; 815 [](auto &arg) -> coro<good_promise_1> { 816 co_await 24; 817 }("argument"); 818 [](auto &arg) ->coro<good_promise_1> { // expected-warning {{expression result unused}} 819 []() -> coro<good_promise_1> { 820 co_await 36; 821 }; 822 co_await 48; 823 }; 824 } 825 template void ok_generic_lambda_coawait_PR41909<int>(); // expected-note {{in instantiation of function template specialization 'ok_generic_lambda_coawait_PR41909<int>' requested here}} 826 827 template <> struct std::coroutine_traits<int, int, const char **> { using promise_type = promise; }; 828 829 int main(int, const char**) { 830 co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}} 831 } 832 833 struct good_promise_2 { 834 float get_return_object(); 835 suspend_always initial_suspend(); 836 suspend_always final_suspend() noexcept; 837 void return_void(); 838 void unhandled_exception(); 839 }; 840 template <> struct std::coroutine_handle<good_promise_2> {}; 841 842 template <> struct std::coroutine_traits<float> { using promise_type = good_promise_2; }; 843 844 float badly_specialized_coro_handle() { // expected-error {{std::coroutine_handle must have a member named 'from_address'}} 845 //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} 846 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} 847 } 848 849 namespace std { 850 struct nothrow_t {}; 851 constexpr nothrow_t nothrow = {}; 852 } 853 854 using SizeT = decltype(sizeof(int)); 855 856 void* operator new(SizeT __sz, const std::nothrow_t&) noexcept; 857 void operator delete(void* __p, const std::nothrow_t&) noexcept; 858 859 860 861 struct promise_on_alloc_failure_tag {}; 862 863 template <> 864 struct std::coroutine_traits<int, promise_on_alloc_failure_tag> { 865 struct promise_type { 866 int get_return_object() {} 867 suspend_always initial_suspend() { return {}; } 868 suspend_always final_suspend() noexcept { return {}; } 869 void return_void() {} 870 int get_return_object_on_allocation_failure(); // expected-error{{'promise_type': 'get_return_object_on_allocation_failure()' must be a static member function}} 871 void unhandled_exception(); 872 }; 873 }; 874 875 extern "C" int f(promise_on_alloc_failure_tag) { 876 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} 877 } 878 879 struct bad_promise_11 { 880 coro<bad_promise_11> get_return_object(); 881 suspend_always initial_suspend(); 882 suspend_always final_suspend() noexcept; 883 void unhandled_exception(); 884 void return_void(); 885 886 private: 887 static coro<bad_promise_11> get_return_object_on_allocation_failure(); // expected-note 2 {{declared private here}} 888 }; 889 coro<bad_promise_11> private_alloc_failure_handler() { 890 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}} 891 co_return; // FIXME: Add a "declared coroutine here" note. 892 } 893 894 template <class T> 895 coro<T> dependent_private_alloc_failure_handler(T) { 896 // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}} 897 co_return; // FIXME: Add a "declared coroutine here" note. 898 } 899 template coro<bad_promise_11> dependent_private_alloc_failure_handler(bad_promise_11); 900 // expected-note@-1 {{requested here}} 901 902 struct bad_promise_12 { 903 coro<bad_promise_12> get_return_object(); 904 suspend_always initial_suspend(); 905 suspend_always final_suspend() noexcept; 906 void unhandled_exception(); 907 void return_void(); 908 static coro<bad_promise_12> get_return_object_on_allocation_failure(); 909 910 static void* operator new(SizeT); 911 // 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()'}} 912 }; 913 coro<bad_promise_12> throwing_in_class_new() { // expected-note {{call to 'operator new' implicitly required by coroutine function here}} 914 co_return; 915 } 916 917 template <class T> 918 coro<T> dependent_throwing_in_class_new(T) { // expected-note {{call to 'operator new' implicitly required by coroutine function here}} 919 co_return; 920 } 921 template coro<bad_promise_12> dependent_throwing_in_class_new(bad_promise_12); // expected-note {{requested here}} 922 923 924 struct good_promise_13 { 925 coro<good_promise_13> get_return_object(); 926 suspend_always initial_suspend(); 927 suspend_always final_suspend() noexcept; 928 void unhandled_exception(); 929 void return_void(); 930 static coro<good_promise_13> get_return_object_on_allocation_failure(); 931 }; 932 coro<good_promise_13> uses_nothrow_new() { 933 co_return; 934 } 935 936 template <class T> 937 coro<T> dependent_uses_nothrow_new(T) { 938 co_return; 939 } 940 template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13); 941 942 struct good_promise_custom_new_operator { 943 coro<good_promise_custom_new_operator> get_return_object(); 944 suspend_always initial_suspend(); 945 suspend_always final_suspend() noexcept; 946 void return_void(); 947 void unhandled_exception(); 948 void *operator new(SizeT, double, float, int); 949 }; 950 951 coro<good_promise_custom_new_operator> 952 good_coroutine_calls_custom_new_operator(double, float, int) { 953 co_return; 954 } 955 956 struct coroutine_nonstatic_member_struct; 957 958 struct good_promise_nonstatic_member_custom_new_operator { 959 coro<good_promise_nonstatic_member_custom_new_operator> get_return_object(); 960 suspend_always initial_suspend(); 961 suspend_always final_suspend() noexcept; 962 void return_void(); 963 void unhandled_exception(); 964 void *operator new(SizeT, coroutine_nonstatic_member_struct &, double); 965 }; 966 967 struct good_promise_noexcept_custom_new_operator { 968 static coro<good_promise_noexcept_custom_new_operator> get_return_object_on_allocation_failure(); 969 coro<good_promise_noexcept_custom_new_operator> get_return_object(); 970 suspend_always initial_suspend(); 971 suspend_always final_suspend() noexcept; 972 void return_void(); 973 void unhandled_exception(); 974 void *operator new(SizeT, double, float, int) noexcept; 975 }; 976 977 coro<good_promise_noexcept_custom_new_operator> 978 good_coroutine_calls_noexcept_custom_new_operator(double, float, int) { 979 co_return; 980 } 981 982 struct mismatch_gro_type_tag1 {}; 983 template <> 984 struct std::coroutine_traits<int, mismatch_gro_type_tag1> { 985 struct promise_type { 986 void get_return_object() {} //expected-note {{member 'get_return_object' declared here}} 987 suspend_always initial_suspend() { return {}; } 988 suspend_always final_suspend() noexcept { return {}; } 989 void return_void() {} 990 void unhandled_exception(); 991 }; 992 }; 993 994 extern "C" int f(mismatch_gro_type_tag1) { 995 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}} 996 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} 997 } 998 999 struct mismatch_gro_type_tag2 {}; 1000 template <> 1001 struct std::coroutine_traits<int, mismatch_gro_type_tag2> { 1002 struct promise_type { 1003 void *get_return_object() {} //expected-note {{member 'get_return_object' declared here}} 1004 suspend_always initial_suspend() { return {}; } 1005 suspend_always final_suspend() noexcept { return {}; } 1006 void return_void() {} 1007 void unhandled_exception(); 1008 }; 1009 }; 1010 1011 extern "C" int f(mismatch_gro_type_tag2) { 1012 // cxx23-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void *'}} 1013 // cxx14_20-error@-2 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}} 1014 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} 1015 } 1016 1017 struct mismatch_gro_type_tag3 {}; 1018 template <> 1019 struct std::coroutine_traits<int, mismatch_gro_type_tag3> { 1020 struct promise_type { 1021 int get_return_object() {} 1022 static void get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared here}} 1023 suspend_always initial_suspend() { return {}; } 1024 suspend_always final_suspend() noexcept { return {}; } 1025 void return_void() {} 1026 void unhandled_exception(); 1027 }; 1028 }; 1029 1030 extern "C" int f(mismatch_gro_type_tag3) { 1031 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}} 1032 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} 1033 } 1034 1035 1036 struct mismatch_gro_type_tag4 {}; 1037 template <> 1038 struct std::coroutine_traits<int, mismatch_gro_type_tag4> { 1039 struct promise_type { 1040 int get_return_object() {} 1041 static char *get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared}} 1042 suspend_always initial_suspend() { return {}; } 1043 suspend_always final_suspend() noexcept { return {}; } 1044 void return_void() {} 1045 void unhandled_exception(); 1046 }; 1047 }; 1048 1049 extern "C" int f(mismatch_gro_type_tag4) { 1050 // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}} 1051 co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} 1052 } 1053 1054 struct promise_no_return_func { 1055 coro<promise_no_return_func> get_return_object(); 1056 suspend_always initial_suspend(); 1057 suspend_always final_suspend() noexcept; 1058 void unhandled_exception(); 1059 }; 1060 // [dcl.fct.def.coroutine]/p6 1061 // If searches for the names return_void and return_value in the scope of 1062 // the promise type each find any declarations, the program is ill-formed. 1063 // [Note 1: If return_void is found, flowing off the end of a coroutine is 1064 // equivalent to a co_return with no operand. Otherwise, flowing off the end 1065 // of a coroutine results in undefined behavior ([stmt.return.coroutine]). — 1066 // end note] 1067 // 1068 // So it isn't ill-formed if the promise doesn't define return_value and return_void. 1069 // It is just a potential UB. 1070 coro<promise_no_return_func> no_return_value_or_return_void() { 1071 co_await a; 1072 } 1073 1074 // The following two tests that it would emit correct diagnostic message 1075 // if we co_return in `promise_no_return_func`. 1076 coro<promise_no_return_func> no_return_value_or_return_void_2() { 1077 co_return; // expected-error {{no member named 'return_void'}} 1078 } 1079 1080 coro<promise_no_return_func> no_return_value_or_return_void_3() { 1081 co_return 43; // expected-error {{no member named 'return_value'}} 1082 } 1083 1084 struct bad_await_suspend_return { 1085 bool await_ready(); 1086 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}} 1087 char await_suspend(std::coroutine_handle<>); 1088 void await_resume(); 1089 }; 1090 struct bad_await_ready_return { 1091 // expected-note@+1 {{return type of 'await_ready' is required to be contextually convertible to 'bool'}} 1092 void await_ready(); 1093 bool await_suspend(std::coroutine_handle<>); 1094 void await_resume(); 1095 }; 1096 struct await_ready_explicit_bool { 1097 struct BoolT { 1098 explicit operator bool() const; 1099 }; 1100 BoolT await_ready(); 1101 void await_suspend(std::coroutine_handle<>); 1102 void await_resume(); 1103 }; 1104 template <class SuspendTy> 1105 struct await_suspend_type_test { 1106 bool await_ready(); 1107 // expected-error@+2 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &')}} 1108 // expected-error@+1 {{return type of 'await_suspend' is required to be 'void' or 'bool' (have 'bool &&')}} 1109 SuspendTy await_suspend(std::coroutine_handle<>); 1110 // cxx20_23-warning@-1 {{volatile-qualified return type 'const volatile bool' is deprecated}} 1111 void await_resume(); 1112 }; 1113 void test_bad_suspend() { 1114 { 1115 // FIXME: The actual error emitted here is terrible, and no number of notes can save it. 1116 bad_await_ready_return a; 1117 // expected-error@+1 {{value of type 'void' is not contextually convertible to 'bool'}} 1118 co_await a; // expected-note {{call to 'await_ready' implicitly required by coroutine function here}} 1119 } 1120 { 1121 bad_await_suspend_return b; 1122 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}} 1123 } 1124 { 1125 await_ready_explicit_bool c; 1126 co_await c; // OK 1127 } 1128 { 1129 await_suspend_type_test<bool &&> a; 1130 await_suspend_type_test<bool &> b; 1131 await_suspend_type_test<const void> c; 1132 await_suspend_type_test<const volatile bool> d; // cxx20_23-note {{in instantiation of template class}} 1133 co_await a; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}} 1134 co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}} 1135 co_await c; // OK 1136 co_await d; // OK 1137 } 1138 } 1139 1140 template <int ID = 0> 1141 struct NoCopy { 1142 NoCopy(NoCopy const&) = delete; // expected-note 2 {{deleted here}} 1143 }; 1144 template <class T, class U> 1145 void test_dependent_param(T t, U) { 1146 // expected-error@-1 {{call to deleted constructor of 'NoCopy<>'}} 1147 // expected-error@-2 {{call to deleted constructor of 'NoCopy<1>'}} 1148 ((void)t); 1149 co_return 42; 1150 } 1151 template void test_dependent_param(NoCopy<0>, NoCopy<1>); // expected-note {{requested here}} 1152 1153 namespace CoroHandleMemberFunctionTest { 1154 struct CoroMemberTag {}; 1155 struct BadCoroMemberTag {}; 1156 1157 template <class T, class U> 1158 constexpr bool IsSameV = false; 1159 template <class T> 1160 constexpr bool IsSameV<T, T> = true; 1161 1162 template <class T> 1163 struct TypeTest { 1164 template <class U> 1165 static constexpr bool IsSame = IsSameV<T, U>; 1166 1167 template <class... Args> 1168 static constexpr bool MatchesArgs = IsSameV<T, 1169 std::coroutine_traits<CoroMemberTag, Args...>>; 1170 }; 1171 1172 template <class T> 1173 struct AwaitReturnsType { 1174 bool await_ready() const; 1175 void await_suspend(...) const; 1176 T await_resume() const; 1177 }; 1178 1179 template <class... CoroTraitsArgs> 1180 struct CoroMemberPromise { 1181 using TraitsT = std::coroutine_traits<CoroTraitsArgs...>; 1182 using TypeTestT = TypeTest<TraitsT>; 1183 using AwaitTestT = AwaitReturnsType<TypeTestT>; 1184 1185 CoroMemberTag get_return_object(); 1186 suspend_always initial_suspend(); 1187 suspend_always final_suspend() noexcept; 1188 1189 AwaitTestT yield_value(int); 1190 1191 void return_void(); 1192 void unhandled_exception(); 1193 }; 1194 1195 } // namespace CoroHandleMemberFunctionTest 1196 1197 template <class... Args> 1198 struct ::std::coroutine_traits<CoroHandleMemberFunctionTest::CoroMemberTag, Args...> { 1199 using promise_type = CoroHandleMemberFunctionTest::CoroMemberPromise<CoroHandleMemberFunctionTest::CoroMemberTag, Args...>; 1200 }; 1201 1202 namespace CoroHandleMemberFunctionTest { 1203 struct TestType { 1204 1205 CoroMemberTag test_qual() { 1206 auto TC = co_yield 0; 1207 static_assert(TC.MatchesArgs<TestType &>, ""); 1208 static_assert(!TC.MatchesArgs<TestType>, ""); 1209 static_assert(!TC.MatchesArgs<TestType *>, ""); 1210 } 1211 1212 CoroMemberTag test_asserts(int *) const { 1213 auto TC = co_yield 0; 1214 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static assertion failed}} 1215 static_assert(TC.MatchesArgs<const TestType &>, ""); // expected-error {{static assertion failed}} 1216 static_assert(TC.MatchesArgs<const TestType &, int *>, ""); 1217 } 1218 1219 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const { 1220 // cxx20_23-warning@-1 {{volatile-qualified parameter type}} 1221 auto TC = co_yield 0; 1222 static_assert(TC.MatchesArgs<const TestType &, int *, const float &&, volatile void *volatile>, ""); 1223 } 1224 1225 CoroMemberTag test_qual() const volatile { 1226 auto TC = co_yield 0; 1227 static_assert(TC.MatchesArgs<const volatile TestType &>, ""); 1228 } 1229 1230 CoroMemberTag test_ref_qual() & { 1231 auto TC = co_yield 0; 1232 static_assert(TC.MatchesArgs<TestType &>, ""); 1233 } 1234 CoroMemberTag test_ref_qual() const & { 1235 auto TC = co_yield 0; 1236 static_assert(TC.MatchesArgs<TestType const &>, ""); 1237 } 1238 CoroMemberTag test_ref_qual() && { 1239 auto TC = co_yield 0; 1240 static_assert(TC.MatchesArgs<TestType &&>, ""); 1241 } 1242 CoroMemberTag test_ref_qual(const char *&) const volatile && { 1243 auto TC = co_yield 0; 1244 static_assert(TC.MatchesArgs<TestType const volatile &&, const char *&>, ""); 1245 } 1246 1247 CoroMemberTag test_args(int) { 1248 auto TC = co_yield 0; 1249 static_assert(TC.MatchesArgs<TestType &, int>, ""); 1250 } 1251 CoroMemberTag test_args(int, long &, void *) const { 1252 auto TC = co_yield 0; 1253 static_assert(TC.MatchesArgs<TestType const &, int, long &, void *>, ""); 1254 } 1255 1256 template <class... Args> 1257 CoroMemberTag test_member_template(Args...) const && { 1258 auto TC = co_yield 0; 1259 static_assert(TC.template MatchesArgs<TestType const &&, Args...>, ""); 1260 } 1261 1262 static CoroMemberTag test_static() { 1263 auto TC = co_yield 0; 1264 static_assert(TC.MatchesArgs<>, ""); 1265 static_assert(!TC.MatchesArgs<TestType>, ""); 1266 static_assert(!TC.MatchesArgs<TestType &>, ""); 1267 static_assert(!TC.MatchesArgs<TestType *>, ""); 1268 } 1269 1270 static CoroMemberTag test_static(volatile void *const, char &&) { 1271 auto TC = co_yield 0; 1272 static_assert(TC.MatchesArgs<volatile void *const, char &&>, ""); 1273 } 1274 1275 template <class Dummy> 1276 static CoroMemberTag test_static_template(const char *volatile &, unsigned) { 1277 auto TC = co_yield 0; 1278 using TCT = decltype(TC); 1279 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, ""); 1280 static_assert(!TCT::MatchesArgs<TestType &, const char *volatile &, unsigned>, ""); 1281 } 1282 1283 BadCoroMemberTag test_diagnostics() { 1284 // expected-error@-1 {{this function cannot be a coroutine: 'std::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, CoroHandleMemberFunctionTest::TestType &>' has no member named 'promise_type'}} 1285 co_return; 1286 } 1287 BadCoroMemberTag test_diagnostics(int) const && { 1288 // expected-error@-1 {{this function cannot be a coroutine: 'std::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, const CoroHandleMemberFunctionTest::TestType &&, int>' has no member named 'promise_type'}} 1289 co_return; 1290 } 1291 1292 static BadCoroMemberTag test_static_diagnostics(long *) { 1293 // expected-error@-1 {{this function cannot be a coroutine: 'std::coroutine_traits<CoroHandleMemberFunctionTest::BadCoroMemberTag, long *>' has no member named 'promise_type'}} 1294 co_return; 1295 } 1296 }; 1297 1298 template CoroMemberTag TestType::test_member_template(long, const char *) const &&; 1299 template CoroMemberTag TestType::test_static_template<void>(const char *volatile &, unsigned); 1300 1301 template <class... Args> 1302 struct DepTestType { 1303 1304 CoroMemberTag test_asserts(int *) const { 1305 auto TC = co_yield 0; 1306 static_assert(TC.template MatchesArgs<const DepTestType &>, ""); // expected-error {{static assertion failed}} 1307 static_assert(TC.template MatchesArgs<>, ""); // expected-error {{static assertion failed}} 1308 static_assert(TC.template MatchesArgs<const DepTestType &, int *>, ""); 1309 } 1310 1311 CoroMemberTag test_qual() { 1312 auto TC = co_yield 0; 1313 static_assert(TC.template MatchesArgs<DepTestType &>, ""); 1314 static_assert(!TC.template MatchesArgs<DepTestType>, ""); 1315 static_assert(!TC.template MatchesArgs<DepTestType *>, ""); 1316 } 1317 1318 CoroMemberTag test_qual(int *, const float &&, volatile void *volatile) const { 1319 // cxx20_23-warning@-1 {{volatile-qualified parameter type}} 1320 auto TC = co_yield 0; 1321 static_assert(TC.template MatchesArgs<const DepTestType &, int *, const float &&, volatile void *volatile>, ""); 1322 } 1323 1324 CoroMemberTag test_qual() const volatile { 1325 auto TC = co_yield 0; 1326 static_assert(TC.template MatchesArgs<const volatile DepTestType &>, ""); 1327 } 1328 1329 CoroMemberTag test_ref_qual() & { 1330 auto TC = co_yield 0; 1331 static_assert(TC.template MatchesArgs<DepTestType &>, ""); 1332 } 1333 CoroMemberTag test_ref_qual() const & { 1334 auto TC = co_yield 0; 1335 static_assert(TC.template MatchesArgs<DepTestType const &>, ""); 1336 } 1337 CoroMemberTag test_ref_qual() && { 1338 auto TC = co_yield 0; 1339 static_assert(TC.template MatchesArgs<DepTestType &&>, ""); 1340 } 1341 CoroMemberTag test_ref_qual(const char *&) const volatile && { 1342 auto TC = co_yield 0; 1343 static_assert(TC.template MatchesArgs<DepTestType const volatile &&, const char *&>, ""); 1344 } 1345 1346 CoroMemberTag test_args(int) { 1347 auto TC = co_yield 0; 1348 static_assert(TC.template MatchesArgs<DepTestType &, int>, ""); 1349 } 1350 CoroMemberTag test_args(int, long &, void *) const { 1351 auto TC = co_yield 0; 1352 static_assert(TC.template MatchesArgs<DepTestType const &, int, long &, void *>, ""); 1353 } 1354 1355 template <class... UArgs> 1356 CoroMemberTag test_member_template(UArgs...) const && { 1357 auto TC = co_yield 0; 1358 static_assert(TC.template MatchesArgs<DepTestType const &&, UArgs...>, ""); 1359 } 1360 1361 static CoroMemberTag test_static() { 1362 auto TC = co_yield 0; 1363 using TCT = decltype(TC); 1364 static_assert(TCT::MatchesArgs<>, ""); 1365 static_assert(!TCT::MatchesArgs<DepTestType>, ""); 1366 static_assert(!TCT::MatchesArgs<DepTestType &>, ""); 1367 static_assert(!TCT::MatchesArgs<DepTestType *>, ""); 1368 1369 // Ensure diagnostics are actually being generated here 1370 static_assert(TCT::MatchesArgs<int>, ""); // expected-error {{static assertion failed}} 1371 } 1372 1373 static CoroMemberTag test_static(volatile void *const, char &&) { 1374 auto TC = co_yield 0; 1375 using TCT = decltype(TC); 1376 static_assert(TCT::MatchesArgs<volatile void *const, char &&>, ""); 1377 } 1378 1379 template <class Dummy> 1380 static CoroMemberTag test_static_template(const char *volatile &, unsigned) { 1381 auto TC = co_yield 0; 1382 using TCT = decltype(TC); 1383 static_assert(TCT::MatchesArgs<const char *volatile &, unsigned>, ""); 1384 static_assert(!TCT::MatchesArgs<DepTestType &, const char *volatile &, unsigned>, ""); 1385 } 1386 }; 1387 1388 template struct DepTestType<int>; // expected-note 2{{requested here}} 1389 template CoroMemberTag DepTestType<int>::test_member_template(long, const char *) const &&; 1390 1391 template CoroMemberTag DepTestType<int>::test_static_template<void>(const char *volatile &, unsigned); 1392 1393 struct bad_promise_deleted_constructor { 1394 // expected-note@+1 {{'bad_promise_deleted_constructor' has been explicitly marked deleted here}} 1395 bad_promise_deleted_constructor() = delete; 1396 coro<bad_promise_deleted_constructor> get_return_object(); 1397 suspend_always initial_suspend(); 1398 suspend_always final_suspend() noexcept; 1399 void return_void(); 1400 void unhandled_exception(); 1401 }; 1402 1403 coro<bad_promise_deleted_constructor> 1404 bad_coroutine_calls_deleted_promise_constructor() { 1405 // 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')}} 1406 co_return; 1407 } 1408 1409 // Test that, when the promise type has a constructor whose signature matches 1410 // that of the coroutine function, that constructor is used. If no matching 1411 // constructor exists, the default constructor is used as a fallback. If no 1412 // matching constructors exist at all, an error is emitted. This is an 1413 // experimental feature that will be proposed for the Coroutines TS. 1414 1415 struct good_promise_default_constructor { 1416 good_promise_default_constructor(double, float, int); 1417 good_promise_default_constructor() = default; 1418 coro<good_promise_default_constructor> get_return_object(); 1419 suspend_always initial_suspend(); 1420 suspend_always final_suspend() noexcept; 1421 void return_void(); 1422 void unhandled_exception(); 1423 }; 1424 1425 coro<good_promise_default_constructor> 1426 good_coroutine_calls_default_constructor() { 1427 co_return; 1428 } 1429 1430 struct some_class; 1431 1432 struct good_promise_custom_constructor { 1433 good_promise_custom_constructor(some_class&, float, int); 1434 good_promise_custom_constructor(double, float, int); 1435 good_promise_custom_constructor() = delete; 1436 coro<good_promise_custom_constructor> get_return_object(); 1437 suspend_always initial_suspend(); 1438 suspend_always final_suspend() noexcept; 1439 void return_void(); 1440 void unhandled_exception(); 1441 }; 1442 1443 coro<good_promise_custom_constructor> 1444 good_coroutine_calls_custom_constructor(double, float, int) { 1445 co_return; 1446 } 1447 1448 struct some_class { 1449 coro<good_promise_custom_constructor> 1450 good_coroutine_calls_custom_constructor(float, int) { 1451 co_return; 1452 } 1453 coro<good_promise_custom_constructor> 1454 static good_coroutine_calls_custom_constructor(double, float, int) { 1455 co_return; 1456 } 1457 }; 1458 1459 struct bad_promise_no_matching_constructor { 1460 bad_promise_no_matching_constructor(int, int, int); 1461 // expected-note@+1 2 {{'bad_promise_no_matching_constructor' has been explicitly marked deleted here}} 1462 bad_promise_no_matching_constructor() = delete; 1463 coro<bad_promise_no_matching_constructor> get_return_object(); 1464 suspend_always initial_suspend(); 1465 suspend_always final_suspend() noexcept; 1466 void return_void(); 1467 void unhandled_exception(); 1468 }; 1469 1470 coro<bad_promise_no_matching_constructor> 1471 bad_coroutine_calls_with_no_matching_constructor(int, int) { 1472 // 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')}} 1473 co_return; 1474 } 1475 1476 struct some_class2 { 1477 coro<bad_promise_no_matching_constructor> 1478 bad_coroutine_calls_with_no_matching_constructor(int, int, int) { 1479 // expected-error@-1 {{call to deleted constructor}} 1480 co_return; 1481 } 1482 }; 1483 1484 } // namespace CoroHandleMemberFunctionTest 1485 1486 class awaitable_no_unused_warn { 1487 public: 1488 using handle_type = std::coroutine_handle<>; 1489 constexpr bool await_ready() noexcept { return false; } 1490 void await_suspend(handle_type) noexcept {} 1491 int await_resume() noexcept { return 1; } 1492 }; 1493 1494 1495 class awaitable_unused_warn { 1496 public: 1497 using handle_type = std::coroutine_handle<>; 1498 constexpr bool await_ready() noexcept { return false; } 1499 void await_suspend(handle_type) noexcept {} 1500 [[nodiscard]] int await_resume() noexcept { return 1; } 1501 }; 1502 1503 template <class Await> 1504 struct check_warning_promise { 1505 coro<check_warning_promise> get_return_object(); 1506 Await initial_suspend(); 1507 Await final_suspend() noexcept; 1508 Await yield_value(int); 1509 void return_void(); 1510 void unhandled_exception(); 1511 }; 1512 1513 1514 coro<check_warning_promise<awaitable_no_unused_warn>> 1515 test_no_unused_warning() { 1516 co_await awaitable_no_unused_warn(); 1517 co_yield 42; 1518 } 1519 1520 coro<check_warning_promise<awaitable_unused_warn>> 1521 test_unused_warning() { 1522 co_await awaitable_unused_warn(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} 1523 co_yield 42; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} 1524 } 1525 1526 struct missing_await_ready { 1527 void await_suspend(std::coroutine_handle<>); 1528 void await_resume(); 1529 }; 1530 struct missing_await_suspend { 1531 bool await_ready(); 1532 void await_resume(); 1533 }; 1534 struct missing_await_resume { 1535 bool await_ready(); 1536 void await_suspend(std::coroutine_handle<>); 1537 }; 1538 1539 void test_missing_awaitable_members() { 1540 co_await missing_await_ready{}; // expected-error {{no member named 'await_ready' in 'missing_await_ready'}} 1541 co_await missing_await_suspend{}; // expected-error {{no member named 'await_suspend' in 'missing_await_suspend'}} 1542 co_await missing_await_resume{}; // expected-error {{no member named 'await_resume' in 'missing_await_resume'}} 1543 } 1544 1545 __attribute__((__always_inline__)) 1546 void warn_always_inline() { // expected-warning {{this coroutine may be split into pieces; not every piece is guaranteed to be inlined}} 1547 co_await suspend_always{}; 1548 } 1549 1550 [[gnu::always_inline]] 1551 void warn_gnu_always_inline() { // expected-warning {{this coroutine may be split into pieces; not every piece is guaranteed to be inlined}} 1552 co_await suspend_always{}; 1553 } 1554