// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s namespace std { template struct coroutine_handle { coroutine_handle() = default; static coroutine_handle from_address(void *) noexcept; }; template <> struct coroutine_handle { static coroutine_handle from_address(void *) noexcept; coroutine_handle() = default; template coroutine_handle(coroutine_handle) noexcept; }; template struct void_t_imp { using type = void; }; template using void_t = typename void_t_imp::type; template struct traits_sfinae_base {}; template struct traits_sfinae_base> { using promise_type = typename T::promise_type; }; template struct coroutine_traits : public traits_sfinae_base {}; } // namespace std struct suspend_never { bool await_ready() noexcept; void await_suspend(std::coroutine_handle<>) noexcept; void await_resume() noexcept; }; struct MoveOnly { MoveOnly() = default; MoveOnly(const MoveOnly&) = delete; MoveOnly(MoveOnly &&) = default; }; struct NoCopyNoMove { NoCopyNoMove() = default; NoCopyNoMove(const NoCopyNoMove &) = delete; }; template struct task { struct promise_type { auto initial_suspend() { return suspend_never{}; } auto final_suspend() noexcept { return suspend_never{}; } auto get_return_object() { return task{}; } static void unhandled_exception() {} void return_value(T &&value) {} // expected-note 4{{passing argument}} }; }; task local2val() { NoCopyNoMove value; co_return value; } task local2ref() { NoCopyNoMove value; co_return value; // expected-error {{non-const lvalue reference to type 'NoCopyNoMove' cannot bind to a temporary of type 'NoCopyNoMove'}} } // We need the move constructor for construction of the coroutine. task param2val(MoveOnly value) { co_return value; } task lvalue2val(NoCopyNoMove &value) { co_return value; // expected-error {{rvalue reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}} } task rvalue2val(NoCopyNoMove &&value) { co_return value; } task lvalue2ref(NoCopyNoMove &value) { co_return value; } task rvalue2ref(NoCopyNoMove &&value) { co_return value; // expected-error {{non-const lvalue reference to type 'NoCopyNoMove' cannot bind to a temporary of type 'NoCopyNoMove'}} } struct To { operator MoveOnly() &&; }; task conversion_operator() { To t; co_return t; } struct Construct { Construct(MoveOnly); }; task converting_constructor() { MoveOnly w; co_return w; } struct Derived : MoveOnly {}; task derived2base() { Derived result; co_return result; } struct RetThis { task foo() && { co_return *this; // expected-error {{rvalue reference to type 'RetThis' cannot bind to lvalue of type 'RetThis'}} } }; template struct is_same { static constexpr bool value = false; }; template struct is_same { static constexpr bool value = true; }; template struct generic_task { struct promise_type { auto initial_suspend() { return suspend_never{}; } auto final_suspend() noexcept { return suspend_never{}; } auto get_return_object() { return generic_task{}; } static void unhandled_exception(); template void return_value(U &&value) { static_assert(is_same::value); } }; }; generic_task param2template(MoveOnly value) { co_return value; // We should deduce U = MoveOnly. } generic_task lvalue2template(NoCopyNoMove &value) { co_return value; // We should deduce U = NoCopyNoMove&. }