// RUN: %clang_cc1 -std=c++14 -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions void no_coroutine_traits_bad_arg_await() { co_await a; // expected-error {{include }} // expected-error@-1 {{use of undeclared identifier 'a'}} } void no_coroutine_traits_bad_arg_yield() { co_yield a; // expected-error {{include }} // expected-error@-1 {{use of undeclared identifier 'a'}} } void no_coroutine_traits_bad_arg_return() { co_return a; // expected-error {{include }} // expected-error@-1 {{use of undeclared identifier 'a'}} } void no_coroutine_traits() { co_await 4; // expected-error {{std::experimental::coroutine_traits type was not found; include }} } namespace std { namespace experimental { template struct coroutine_traits; // expected-note {{declared here}} }} // namespace std::experimental template struct coro {}; template struct std::experimental::coroutine_traits, Ps...> { using promise_type = Promise; }; struct awaitable { bool await_ready(); template void await_suspend(F); void await_resume(); } a; struct suspend_always { bool await_ready() { return false; } template void await_suspend(F); void await_resume() {} }; struct suspend_never { bool await_ready() { return true; } template void await_suspend(F); void await_resume() {} }; void no_specialization() { co_await a; // expected-error {{implicit instantiation of undefined template 'std::experimental::coroutine_traits'}} } template struct std::experimental::coroutine_traits {}; int no_promise_type() { // expected-error {{this function cannot be a coroutine: 'std::experimental::coroutine_traits' has no member named 'promise_type'}} co_await a; } template <> struct std::experimental::coroutine_traits { typedef int promise_type; }; double bad_promise_type(double) { // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits::promise_type' (aka 'int') is not a class}} co_await a; } template <> struct std::experimental::coroutine_traits { struct promise_type {}; }; double bad_promise_type_2(int) { // expected-error {{no member named 'initial_suspend'}} co_yield 0; // expected-error {{no member named 'yield_value' in 'std::experimental::coroutine_traits::promise_type'}} } struct promise; // expected-note {{forward declaration}} struct promise_void; struct void_tag {}; template struct std::experimental::coroutine_traits { using promise_type = promise; }; template struct std::experimental::coroutine_traits { using promise_type = promise_void; }; // FIXME: This diagnostic is terrible. void undefined_promise() { // expected-error {{this function cannot be a coroutine: 'experimental::coroutine_traits::promise_type' (aka 'promise') is an incomplete type}} co_await a; } struct yielded_thing { const char *p; short a, b; }; struct not_awaitable {}; struct promise { void get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); awaitable yield_value(int); // expected-note 2{{candidate}} awaitable yield_value(yielded_thing); // expected-note 2{{candidate}} not_awaitable yield_value(void()); // expected-note 2{{candidate}} void return_value(int); // expected-note 2{{here}} void unhandled_exception(); }; struct promise_void { void get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void return_void(); void unhandled_exception(); }; void no_coroutine_handle() { // expected-error {{std::experimental::coroutine_handle type was not found; include before defining a coroutine}} //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} co_return 5; //expected-note {{function is a coroutine due to use of 'co_return' here}} } namespace std { namespace experimental { template struct coroutine_handle { static coroutine_handle from_address(void *); }; template <> struct coroutine_handle { template coroutine_handle(coroutine_handle); static coroutine_handle from_address(void *); }; }} // namespace std::experimental void yield() { co_yield 0; co_yield {"foo", 1, 2}; co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}} co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} co_yield {"foo"}; co_yield "foo"; // expected-error {{no matching}} co_yield 1.0; co_yield yield; // expected-error {{no member named 'await_ready' in 'not_awaitable'}} } void coreturn(int n) { co_await a; if (n == 0) co_return 3; if (n == 1) co_return {4}; // expected-warning {{braces around scalar initializer}} if (n == 2) co_return "foo"; // expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char [4]'}} co_return 42; } template void co_await_non_dependent_arg(T) { co_await a; } template void co_await_non_dependent_arg(int); void mixed_yield() { co_yield 0; // expected-note {{use of 'co_yield'}} return; // expected-error {{not allowed in coroutine}} } void mixed_yield_invalid() { co_yield blah; // expected-error {{use of undeclared identifier}} // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} return; // expected-error {{return statement not allowed in coroutine}} } template void mixed_yield_template(T) { co_yield blah; // expected-error {{use of undeclared identifier}} // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} return; // expected-error {{return statement not allowed in coroutine}} } template void mixed_yield_template2(T) { co_yield 42; // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} return; // expected-error {{return statement not allowed in coroutine}} } template void mixed_yield_template3(T v) { co_yield blah(v); // expected-note@-1 {{function is a coroutine due to use of 'co_yield'}} return; // expected-error {{return statement not allowed in coroutine}} } void mixed_await() { co_await a; // expected-note {{use of 'co_await'}} return; // expected-error {{not allowed in coroutine}} } void mixed_await_invalid() { co_await 42; // expected-error {{'int' is not a structure or union}} // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} return; // expected-error {{not allowed in coroutine}} } template void mixed_await_template(T) { co_await 42; // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} return; // expected-error {{not allowed in coroutine}} } template void mixed_await_template2(T v) { co_await v; // expected-error {{'long' is not a structure or union}} // expected-note@-1 {{function is a coroutine due to use of 'co_await'}} return; // expected-error {{not allowed in coroutine}} } template void mixed_await_template2(long); // expected-note {{requested here}} void only_coreturn(void_tag) { co_return; // OK } void mixed_coreturn(void_tag, bool b) { if (b) co_return; // expected-note {{use of 'co_return'}} else return; // expected-error {{not allowed in coroutine}} } void mixed_coreturn_invalid(bool b) { if (b) co_return; // expected-note {{use of 'co_return'}} // expected-error@-1 {{no member named 'return_void' in 'promise'}} else return; // expected-error {{not allowed in coroutine}} } template void mixed_coreturn_template(void_tag, bool b, T v) { if (b) co_return v; // expected-note {{use of 'co_return'}} // expected-error@-1 {{no member named 'return_value' in 'promise_void'}} else return; // expected-error {{not allowed in coroutine}} } template void mixed_coreturn_template(void_tag, bool, int); // expected-note {{requested here}} template void mixed_coreturn_template2(bool b, T) { if (b) co_return v; // expected-note {{use of 'co_return'}} // expected-error@-1 {{use of undeclared identifier 'v'}} else return; // expected-error {{not allowed in coroutine}} } struct CtorDtor { CtorDtor() { co_yield 0; // expected-error {{'co_yield' cannot be used in a constructor}} } CtorDtor(awaitable a) { // The spec doesn't say this is ill-formed, but it must be. co_await a; // expected-error {{'co_await' cannot be used in a constructor}} } ~CtorDtor() { co_return 0; // expected-error {{'co_return' cannot be used in a destructor}} } // FIXME: The spec says this is ill-formed. void operator=(CtorDtor&) { co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}} } void operator=(CtorDtor const &) { co_yield 0; // expected-error {{'co_yield' cannot be used in a copy assignment operator}} } void operator=(CtorDtor &&) { co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}} } void operator=(CtorDtor const &&) { co_await a; // expected-error {{'co_await' cannot be used in a move assignment operator}} } void operator=(int) { co_await a; // OK. Not a special member } }; void unevaluated() { decltype(co_await a); // expected-error {{cannot be used in an unevaluated context}} sizeof(co_await a); // expected-error {{cannot be used in an unevaluated context}} typeid(co_await a); // expected-error {{cannot be used in an unevaluated context}} decltype(co_yield a); // expected-error {{cannot be used in an unevaluated context}} sizeof(co_yield a); // expected-error {{cannot be used in an unevaluated context}} typeid(co_yield a); // expected-error {{cannot be used in an unevaluated context}} } constexpr auto constexpr_deduced_return_coroutine() { co_yield 0; // expected-error {{'co_yield' cannot be used in a constexpr function}} // expected-error@-1 {{'co_yield' cannot be used in a function with a deduced return type}} } void varargs_coroutine(const char *, ...) { co_await a; // expected-error {{'co_await' cannot be used in a varargs function}} } auto deduced_return_coroutine() { co_await a; // expected-error {{'co_await' cannot be used in a function with a deduced return type}} } struct outer {}; struct await_arg_1 {}; struct await_arg_2 {}; namespace adl_ns { struct coawait_arg_type {}; awaitable operator co_await(coawait_arg_type); } namespace dependent_operator_co_await_lookup { template void await_template(T t) { // no unqualified lookup results co_await t; // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::not_awaitable'}} // expected-error@-1 {{call to function 'operator co_await' that is neither visible in the template definition nor found by argument-dependent lookup}} }; template void await_template(awaitable); struct indirectly_awaitable { indirectly_awaitable(outer); }; awaitable operator co_await(indirectly_awaitable); // expected-note {{should be declared prior to}} template void await_template(indirectly_awaitable); struct not_awaitable {}; template void await_template(not_awaitable); // expected-note {{instantiation}} template void await_template_2(T t) { // one unqualified lookup result co_await t; }; template void await_template(outer); // expected-note {{instantiation}} template void await_template_2(outer); struct transform_awaitable {}; struct transformed {}; struct transform_promise { typedef transform_awaitable await_arg; coro get_return_object(); transformed initial_suspend(); ::adl_ns::coawait_arg_type final_suspend(); transformed await_transform(transform_awaitable); void unhandled_exception(); }; template struct basic_promise { typedef AwaitArg await_arg; coro get_return_object(); awaitable initial_suspend(); awaitable final_suspend(); void unhandled_exception(); }; awaitable operator co_await(await_arg_1); template coro await_template_3(U t) { co_await t; } template coro> await_template_3>(await_arg_1); template struct dependent_member { coro mem_fn() const { co_await typename T::await_arg{}; // expected-error {{call to function 'operator co_await'}}} } template coro dep_mem_fn(U t) { co_await t; } }; template <> struct dependent_member { // FIXME this diagnostic is terrible coro mem_fn() const { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}} // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} // expected-note@+1 {{function is a coroutine due to use of 'co_await' here}} co_await transform_awaitable{}; // expected-error@-1 {{no member named 'await_ready'}} } template coro dep_mem_fn(U u) { co_await u; } }; awaitable operator co_await(await_arg_2); // expected-note {{'operator co_await' should be declared prior to the call site}} template struct dependent_member, 0>; template struct dependent_member, 0>; // expected-note {{in instantiation}} template <> coro // FIXME this diagnostic is terrible dependent_member::dep_mem_fn(int) { // expected-error {{no member named 'await_ready' in 'dependent_operator_co_await_lookup::transformed'}} //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} //expected-note@+1 {{function is a coroutine due to use of 'co_await' here}} co_await transform_awaitable{}; // expected-error@-1 {{no member named 'await_ready'}} } void operator co_await(transform_awaitable) = delete; awaitable operator co_await(transformed); template coro dependent_member::dep_mem_fn(transform_awaitable); template <> coro dependent_member::dep_mem_fn(long) { co_await transform_awaitable{}; } template <> struct dependent_member { coro mem_fn() const { co_await transform_awaitable{}; } }; template coro await_template_3(transform_awaitable); template struct dependent_member; template coro dependent_member::dep_mem_fn(transform_awaitable); } struct yield_fn_tag {}; template <> struct std::experimental::coroutine_traits { struct promise_type { // FIXME: add an await_transform overload for functions awaitable yield_value(int()); void return_value(int()); suspend_never initial_suspend(); suspend_never final_suspend(); void get_return_object(); void unhandled_exception(); }; }; namespace placeholder { awaitable f(), f(int); // expected-note 4{{possible target}} int g(), g(int); // expected-note 2{{candidate}} void x() { co_await f; // expected-error {{reference to overloaded function}} } void y() { co_yield g; // expected-error {{no matching member function for call to 'yield_value'}} } void z() { co_await a; co_return g; // expected-error {{address of overloaded function 'g' does not match required type 'int'}} } void x(yield_fn_tag) { co_await f; // expected-error {{reference to overloaded function}} } void y(yield_fn_tag) { co_yield g; } void z(yield_fn_tag) { co_await a; co_return g; } } struct bad_promise_1 { suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception(); }; coro missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}} co_await a; } struct bad_promise_2 { coro get_return_object(); // FIXME: We shouldn't offer a typo-correction here! suspend_always final_suspend(); // expected-note {{here}} void unhandled_exception(); }; // FIXME: This shouldn't happen twice coro missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}} co_await a; } struct bad_promise_3 { coro get_return_object(); // FIXME: We shouldn't offer a typo-correction here! suspend_always initial_suspend(); // expected-note {{here}} void unhandled_exception(); }; coro missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}} co_await a; } struct bad_promise_4 { coro get_return_object(); not_awaitable initial_suspend(); suspend_always final_suspend(); }; // FIXME: This diagnostic is terrible. coro bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} // expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} } struct bad_promise_5 { coro get_return_object(); suspend_always initial_suspend(); not_awaitable final_suspend(); }; // FIXME: This diagnostic is terrible. coro bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} // expected-note@-1 {{call to 'final_suspend' implicitly required by the final suspend point}} co_await a; // expected-note {{function is a coroutine due to use of 'co_await' here}} } struct bad_promise_6 { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception(); void return_void(); void return_value(int) const; void return_value(int); }; coro bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} co_await a; } template coro bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} co_await a; } template coro bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}} struct bad_promise_7 { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void return_void(); }; coro no_unhandled_exception() { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}} co_await a; } template coro no_unhandled_exception_dependent(T) { // expected-error {{'bad_promise_7' is required to declare the member 'unhandled_exception()'}} co_await a; } template coro no_unhandled_exception_dependent(bad_promise_7); // expected-note {{in instantiation}} struct bad_promise_base { private: void return_void(); }; struct bad_promise_8 : bad_promise_base { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception() __attribute__((unavailable)); // expected-note 2 {{made unavailable}} void unhandled_exception() const; // expected-note 2 {{candidate}} void unhandled_exception(void *) const; // expected-note 2 {{requires 1 argument, but 0 were provided}} }; coro calls_unhandled_exception() { // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}} // FIXME: also warn about private 'return_void' here. Even though building // the call to unhandled_exception has already failed. co_await a; } template coro calls_unhandled_exception_dependent(T) { // expected-error@-1 {{call to unavailable member function 'unhandled_exception'}} co_await a; } template coro calls_unhandled_exception_dependent(bad_promise_8); // expected-note {{in instantiation}} struct bad_promise_9 { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void await_transform(void *); // expected-note {{candidate}} awaitable await_transform(int) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}} void return_void(); void unhandled_exception(); }; coro calls_await_transform() { co_await 42; // expected-error {{call to unavailable member function 'await_transform'}} // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}} } struct bad_promise_10 { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); int await_transform; void return_void(); void unhandled_exception(); }; coro bad_coawait() { // FIXME this diagnostic is terrible co_await 42; // expected-error {{called object type 'int' is not a function or function pointer}} // expected-note@-1 {{call to 'await_transform' implicitly required by 'co_await' here}} } struct call_operator { template awaitable operator()(Args...) const { return a; } }; void ret_void(); struct good_promise_1 { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception(); static const call_operator await_transform; using Fn = void (*)(); Fn return_void = ret_void; }; const call_operator good_promise_1::await_transform; coro ok_static_coawait() { // FIXME this diagnostic is terrible co_await 42; } template<> struct std::experimental::coroutine_traits { using promise_type = promise; }; int main(int, const char**) { co_await a; // expected-error {{'co_await' cannot be used in the 'main' function}} } struct good_promise_2 { float get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void return_void(); void unhandled_exception(); }; template<> struct std::experimental::coroutine_handle {}; template<> struct std::experimental::coroutine_traits { using promise_type = good_promise_2; }; float badly_specialized_coro_handle() { // expected-error {{std::experimental::coroutine_handle missing a member named 'from_address'}} //expected-note@-1 {{call to 'initial_suspend' implicitly required by the initial suspend point}} co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} } struct promise_on_alloc_failure_tag {}; template<> struct std::experimental::coroutine_traits { struct promise_type { int get_return_object() {} suspend_always initial_suspend() { return {}; } suspend_always final_suspend() { return {}; } void return_void() {} int get_return_object_on_allocation_failure(); // expected-error{{'promise_type': 'get_return_object_on_allocation_failure()' must be a static member function}} void unhandled_exception(); }; }; extern "C" int f(promise_on_alloc_failure_tag) { co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} } struct bad_promise_11 { coro get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception(); void return_void(); private: static coro get_return_object_on_allocation_failure(); // expected-note 2 {{declared private here}} }; coro private_alloc_failure_handler() { // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}} co_return; // FIXME: Add a "declared coroutine here" note. } template coro dependent_private_alloc_failure_handler(T) { // expected-error@-1 {{'get_return_object_on_allocation_failure' is a private member of 'bad_promise_11'}} co_return; // FIXME: Add a "declared coroutine here" note. } template coro dependent_private_alloc_failure_handler(bad_promise_11); // expected-note@-1 {{requested here}}