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() {}; 43 MoveOnly(const MoveOnly&) = delete; 44 MoveOnly(MoveOnly&&) noexcept {}; 45 ~MoveOnly() {}; 46 }; 47 48 struct NoCopyNoMove { 49 NoCopyNoMove() = default; 50 NoCopyNoMove(const NoCopyNoMove &) = delete; // expected-note 4{{'NoCopyNoMove' has been explicitly marked deleted here}} 51 }; 52 53 template <typename T> 54 struct task { 55 struct promise_type { 56 auto initial_suspend() { return suspend_never{}; } 57 auto final_suspend() noexcept { return suspend_never{}; } 58 auto get_return_object() { return task{}; } 59 static void unhandled_exception() {} 60 void return_value(T &&value) {} // expected-note 4{{passing argument}} 61 }; 62 }; 63 64 task<NoCopyNoMove> local2val() { 65 NoCopyNoMove value; 66 co_return value; // expected-error {{call to deleted constructor of 'NoCopyNoMove'}} 67 // expected-error@-1 {{value reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}} 68 } 69 70 task<NoCopyNoMove &> local2ref() { 71 NoCopyNoMove value; 72 co_return value; // expected-error {{call to deleted constructor of 'NoCopyNoMove'}} 73 } 74 75 // We need the move constructor for construction of the coroutine. 76 task<MoveOnly> param2val(MoveOnly value) { 77 co_return value; 78 } 79 80 task<NoCopyNoMove> lvalue2val(NoCopyNoMove &value) { 81 co_return value; // expected-error {{rvalue reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}} 82 } 83 84 task<NoCopyNoMove> rvalue2val(NoCopyNoMove &&value) { 85 co_return value; // expected-error {{rvalue reference to type 'NoCopyNoMove' cannot bind to lvalue of type 'NoCopyNoMove'}} 86 // expected-error@-1 {{call to deleted constructor of 'NoCopyNoMove'}} 87 } 88 89 task<NoCopyNoMove &> lvalue2ref(NoCopyNoMove &value) { 90 co_return value; 91 } 92 93 task<NoCopyNoMove &> rvalue2ref(NoCopyNoMove &&value) { 94 co_return value; // expected-error {{call to deleted constructor of 'NoCopyNoMove'}} 95 } 96 97 struct To { 98 operator MoveOnly() &&; 99 }; 100 task<MoveOnly> conversion_operator() { 101 To t; 102 co_return t; 103 } 104 105 struct Construct { 106 Construct(MoveOnly); 107 }; 108 task<Construct> converting_constructor() { 109 MoveOnly w; 110 co_return w; 111 } 112 113 struct Derived : MoveOnly {}; 114 task<MoveOnly> derived2base() { 115 Derived result; 116 co_return result; 117 } 118 119 struct RetThis { 120 task<RetThis> foo() && { 121 co_return *this; // expected-error {{rvalue reference to type 'RetThis' cannot bind to lvalue of type 'RetThis'}} 122 } 123 }; 124 125 template <typename, typename> 126 struct is_same { static constexpr bool value = false; }; 127 128 template <typename T> 129 struct is_same<T, T> { static constexpr bool value = true; }; 130 131 template <typename T> 132 struct generic_task { 133 struct promise_type { 134 auto initial_suspend() { return suspend_never{}; } 135 auto final_suspend() noexcept { return suspend_never{}; } 136 auto get_return_object() { return generic_task{}; } 137 static void unhandled_exception(); 138 template <typename U> 139 void return_value(U &&value) { 140 static_assert(is_same<T, U>::value); 141 } 142 }; 143 }; 144 145 generic_task<MoveOnly> param2template(MoveOnly value) { 146 co_return value; // We should deduce U = MoveOnly. 147 } 148 149 generic_task<NoCopyNoMove &> lvalue2template(NoCopyNoMove &value) { 150 co_return value; // We should deduce U = NoCopyNoMove&. 151 } 152