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