149 lines · cpp
1// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s2 3namespace std {4template <class Promise = void> struct coroutine_handle {5 coroutine_handle() = default;6 static coroutine_handle from_address(void *) noexcept;7};8 9template <> struct coroutine_handle<void> {10 static coroutine_handle from_address(void *) noexcept;11 coroutine_handle() = default;12 template <class PromiseType>13 coroutine_handle(coroutine_handle<PromiseType>) noexcept;14};15 16template <class... Args>17struct void_t_imp {18 using type = void;19};20template <class... Args>21using void_t = typename void_t_imp<Args...>::type;22 23template <class T, class = void>24struct traits_sfinae_base {};25 26template <class T>27struct traits_sfinae_base<T, void_t<typename T::promise_type>> {28 using promise_type = typename T::promise_type;29};30 31template <class Ret, class... Args>32struct coroutine_traits : public traits_sfinae_base<Ret> {};33} // namespace std34 35struct suspend_never {36 bool await_ready() noexcept;37 void await_suspend(std::coroutine_handle<>) noexcept;38 void await_resume() noexcept;39};40 41struct MoveOnly {42 MoveOnly() = default;43 MoveOnly(const MoveOnly&) = delete;44 MoveOnly(MoveOnly &&) = default;45};46 47struct NoCopyNoMove {48 NoCopyNoMove() = default;49 NoCopyNoMove(const NoCopyNoMove &) = delete;50};51 52template <typename T>53struct task {54 struct promise_type {55 auto initial_suspend() { return suspend_never{}; }56 auto final_suspend() noexcept { return suspend_never{}; }57 auto get_return_object() { return task{}; }58 static void unhandled_exception() {}59 void return_value(T &&value) {} // expected-note 4{{passing argument}}60 };61};62 63task<NoCopyNoMove> local2val() {64 NoCopyNoMove value;65 co_return value;66}67 68task<NoCopyNoMove &> local2ref() {69 NoCopyNoMove value;70 co_return value; // expected-error {{non-const lvalue reference to type 'NoCopyNoMove' cannot bind to a temporary of type 'NoCopyNoMove'}}71}72 73// We need the move constructor for construction of the coroutine.74task<MoveOnly> param2val(MoveOnly value) {75 co_return value;76}77 78task<NoCopyNoMove> lvalue2val(NoCopyNoMove &value) {79 co_return value; // expected-error {{rvalue reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}}80}81 82task<NoCopyNoMove> rvalue2val(NoCopyNoMove &&value) {83 co_return value;84}85 86task<NoCopyNoMove &> lvalue2ref(NoCopyNoMove &value) {87 co_return value;88}89 90task<NoCopyNoMove &> rvalue2ref(NoCopyNoMove &&value) {91 co_return value; // expected-error {{non-const lvalue reference to type 'NoCopyNoMove' cannot bind to a temporary of type 'NoCopyNoMove'}}92}93 94struct To {95 operator MoveOnly() &&;96};97task<MoveOnly> conversion_operator() {98 To t;99 co_return t;100}101 102struct Construct {103 Construct(MoveOnly);104};105task<Construct> converting_constructor() {106 MoveOnly w;107 co_return w;108}109 110struct Derived : MoveOnly {};111task<MoveOnly> derived2base() {112 Derived result;113 co_return result;114}115 116struct RetThis {117 task<RetThis> foo() && {118 co_return *this; // expected-error {{rvalue reference to type 'RetThis' cannot bind to lvalue of type 'RetThis'}}119 }120};121 122template <typename, typename>123struct is_same { static constexpr bool value = false; };124 125template <typename T>126struct is_same<T, T> { static constexpr bool value = true; };127 128template <typename T>129struct generic_task {130 struct promise_type {131 auto initial_suspend() { return suspend_never{}; }132 auto final_suspend() noexcept { return suspend_never{}; }133 auto get_return_object() { return generic_task{}; }134 static void unhandled_exception();135 template <typename U>136 void return_value(U &&value) {137 static_assert(is_same<T, U>::value);138 }139 };140};141 142generic_task<MoveOnly> param2template(MoveOnly value) {143 co_return value; // We should deduce U = MoveOnly.144}145 146generic_task<NoCopyNoMove &> lvalue2template(NoCopyNoMove &value) {147 co_return value; // We should deduce U = NoCopyNoMove&.148}149