1 // RUN: %clang_cc1 -verify -std=c++17 -fcoroutines-ts -fsyntax-only %s 2 3 namespace std::experimental { 4 template <class Promise = void> struct coroutine_handle { 5 coroutine_handle() = default; 6 static coroutine_handle from_address(void *) noexcept; 7 }; 8 9 template <> 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 16 template <class... Args> 17 struct void_t_imp { 18 using type = void; 19 }; 20 template <class... Args> 21 using void_t = typename void_t_imp<Args...>::type; 22 23 template <class T, class = void> 24 struct traits_sfinae_base {}; 25 26 template <class T> 27 struct traits_sfinae_base<T, void_t<typename T::promise_type>> { 28 using promise_type = typename T::promise_type; 29 }; 30 31 template <class Ret, class... Args> 32 struct coroutine_traits : public traits_sfinae_base<Ret> {}; 33 } 34 35 struct suspend_never { 36 bool await_ready() noexcept; 37 void await_suspend(std::experimental::coroutine_handle<>) noexcept; 38 void await_resume() noexcept; 39 }; 40 41 struct MoveOnly { 42 MoveOnly() = default; 43 MoveOnly(const MoveOnly&) = delete; 44 MoveOnly(MoveOnly &&) = default; 45 }; 46 47 struct NoCopyNoMove { 48 NoCopyNoMove() = default; 49 NoCopyNoMove(const NoCopyNoMove &) = delete; 50 }; 51 52 template <typename T> 53 struct task { 54 struct promise_type { initial_suspendtask::promise_type55 auto initial_suspend() { return suspend_never{}; } final_suspendtask::promise_type56 auto final_suspend() noexcept { return suspend_never{}; } get_return_objecttask::promise_type57 auto get_return_object() { return task{}; } unhandled_exceptiontask::promise_type58 static void unhandled_exception() {} return_valuetask::promise_type59 void return_value(T &&value) {} // expected-note 4{{passing argument}} 60 }; 61 }; 62 local2val()63task<NoCopyNoMove> local2val() { 64 NoCopyNoMove value; 65 co_return value; 66 } 67 local2ref()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. param2val(MoveOnly value)74task<MoveOnly> param2val(MoveOnly value) { 75 co_return value; 76 } 77 lvalue2val(NoCopyNoMove & value)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 rvalue2val(NoCopyNoMove && value)82task<NoCopyNoMove> rvalue2val(NoCopyNoMove &&value) { 83 co_return value; 84 } 85 lvalue2ref(NoCopyNoMove & value)86task<NoCopyNoMove &> lvalue2ref(NoCopyNoMove &value) { 87 co_return value; 88 } 89 rvalue2ref(NoCopyNoMove && value)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 94 struct To { 95 operator MoveOnly() &&; 96 }; conversion_operator()97task<MoveOnly> conversion_operator() { 98 To t; 99 co_return t; 100 } 101 102 struct Construct { 103 Construct(MoveOnly); 104 }; converting_constructor()105task<Construct> converting_constructor() { 106 MoveOnly w; 107 co_return w; 108 } 109 110 struct Derived : MoveOnly {}; derived2base()111task<MoveOnly> derived2base() { 112 Derived result; 113 co_return result; 114 } 115 116 struct RetThis { fooRetThis117 task<RetThis> foo() && { 118 co_return *this; // expected-error {{rvalue reference to type 'RetThis' cannot bind to lvalue of type 'RetThis'}} 119 } 120 }; 121 122 template <typename, typename> 123 struct is_same { static constexpr bool value = false; }; 124 125 template <typename T> 126 struct is_same<T, T> { static constexpr bool value = true; }; 127 128 template <typename T> 129 struct generic_task { 130 struct promise_type { initial_suspendgeneric_task::promise_type131 auto initial_suspend() { return suspend_never{}; } final_suspendgeneric_task::promise_type132 auto final_suspend() noexcept { return suspend_never{}; } get_return_objectgeneric_task::promise_type133 auto get_return_object() { return generic_task{}; } 134 static void unhandled_exception(); 135 template <typename U> return_valuegeneric_task::promise_type136 void return_value(U &&value) { 137 static_assert(is_same<T, U>::value); 138 } 139 }; 140 }; 141 param2template(MoveOnly value)142generic_task<MoveOnly> param2template(MoveOnly value) { 143 co_return value; // We should deduce U = MoveOnly. 144 } 145 lvalue2template(NoCopyNoMove & value)146generic_task<NoCopyNoMove &> lvalue2template(NoCopyNoMove &value) { 147 co_return value; // We should deduce U = NoCopyNoMove&. 148 } 149