|
4 | 4 | // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,cxx20_23,cxx23 %s -fcxx-exceptions -fexceptions -Wunused-result
|
5 | 5 | // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx14_20,cxx20_23 %s -fcxx-exceptions -fexceptions -Wunused-result
|
6 | 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 | + |
7 | 10 | void no_coroutine_traits_bad_arg_await() {
|
8 | 11 | co_await a; // expected-error {{include <coroutine>}}
|
9 | 12 | // expected-error@-1 {{use of undeclared identifier 'a'}}
|
@@ -154,12 +157,15 @@ namespace std {
|
154 | 157 | template <class PromiseType = void>
|
155 | 158 | struct coroutine_handle {
|
156 | 159 | static coroutine_handle from_address(void *) noexcept;
|
| 160 | + static coroutine_handle from_promise(PromiseType &promise); |
157 | 161 | };
|
158 | 162 | template <>
|
159 | 163 | struct coroutine_handle<void> {
|
160 | 164 | template <class PromiseType>
|
161 | 165 | coroutine_handle(coroutine_handle<PromiseType>) noexcept;
|
162 | 166 | static coroutine_handle from_address(void *) noexcept;
|
| 167 | + template <class PromiseType> |
| 168 | + static coroutine_handle from_promise(PromiseType &promise); |
163 | 169 | };
|
164 | 170 | } // namespace std
|
165 | 171 |
|
@@ -206,6 +212,22 @@ void mixed_yield_invalid() {
|
206 | 212 | return; // expected-error {{return statement not allowed in coroutine}}
|
207 | 213 | }
|
208 | 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 | + |
209 | 231 | template <class T>
|
210 | 232 | void mixed_yield_template(T) {
|
211 | 233 | co_yield blah; // expected-error {{use of undeclared identifier}}
|
@@ -264,6 +286,13 @@ void mixed_coreturn(void_tag, bool b) {
|
264 | 286 | return; // expected-error {{not allowed in coroutine}}
|
265 | 287 | }
|
266 | 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 | + |
267 | 296 | void mixed_coreturn_invalid(bool b) {
|
268 | 297 | if (b)
|
269 | 298 | co_return; // expected-note {{use of 'co_return'}}
|
@@ -291,6 +320,53 @@ void mixed_coreturn_template2(bool b, T) {
|
291 | 320 | return; // expected-error {{not allowed in coroutine}}
|
292 | 321 | }
|
293 | 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 | + |
294 | 370 | struct CtorDtor {
|
295 | 371 | CtorDtor() {
|
296 | 372 | co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}}
|
|
0 commit comments