Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / utilities / optional / optional.object / optional.object.assign / optional_U.pass.cpp
blobcc1b17157f2b46cab1708a27a107f9d5ee16a8a5
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
10 // <optional>
12 // From LWG2451:
13 // template <class U>
14 // optional<T>& operator=(optional<U>&& rhs);
16 #include <optional>
18 #include <array>
19 #include <cassert>
20 #include <memory>
21 #include <type_traits>
23 #include "test_macros.h"
24 #include "archetypes.h"
26 using std::optional;
28 struct X
30 static bool throw_now;
32 X() = default;
33 X(int &&)
35 if (throw_now)
36 TEST_THROW(6);
40 bool X::throw_now = false;
42 struct Y1
44 Y1() = default;
45 Y1(const int&) {}
46 Y1& operator=(const Y1&) = delete;
49 struct Y2
51 Y2() = default;
52 Y2(const int&) = delete;
53 Y2& operator=(const int&) { return *this; }
56 struct B { virtual ~B() = default; };
57 class D : public B {};
60 template <class T>
61 struct AssignableFrom {
62 static int type_constructed;
63 static int type_assigned;
64 static int int_constructed;
65 static int int_assigned;
67 static void reset() {
68 type_constructed = int_constructed = 0;
69 type_assigned = int_assigned = 0;
72 AssignableFrom() = default;
74 explicit AssignableFrom(T) { ++type_constructed; }
75 AssignableFrom& operator=(T) { ++type_assigned; return *this; }
77 AssignableFrom(int) { ++int_constructed; }
78 AssignableFrom& operator=(int) { ++int_assigned; return *this; }
79 private:
80 AssignableFrom(AssignableFrom const&) = delete;
81 AssignableFrom& operator=(AssignableFrom const&) = delete;
84 template <class T> int AssignableFrom<T>::type_constructed = 0;
85 template <class T> int AssignableFrom<T>::type_assigned = 0;
86 template <class T> int AssignableFrom<T>::int_constructed = 0;
87 template <class T> int AssignableFrom<T>::int_assigned = 0;
89 void test_with_test_type() {
90 using T = TestTypes::TestType;
91 T::reset();
92 { // non-empty to empty
93 T::reset_constructors();
94 optional<T> opt;
95 optional<int> other(42);
96 opt = std::move(other);
97 assert(T::alive == 1);
98 assert(T::constructed == 1);
99 assert(T::value_constructed == 1);
100 assert(T::assigned == 0);
101 assert(T::destroyed == 0);
102 assert(static_cast<bool>(other) == true);
103 assert(*other == 42);
104 assert(static_cast<bool>(opt) == true);
105 assert(*opt == T(42));
107 assert(T::alive == 0);
108 { // non-empty to non-empty
109 optional<T> opt(101);
110 optional<int> other(42);
111 T::reset_constructors();
112 opt = std::move(other);
113 assert(T::alive == 1);
114 assert(T::constructed == 0);
115 assert(T::assigned == 1);
116 assert(T::value_assigned == 1);
117 assert(T::destroyed == 0);
118 assert(static_cast<bool>(other) == true);
119 assert(*other == 42);
120 assert(static_cast<bool>(opt) == true);
121 assert(*opt == T(42));
123 assert(T::alive == 0);
124 { // empty to non-empty
125 optional<T> opt(101);
126 optional<int> other;
127 T::reset_constructors();
128 opt = std::move(other);
129 assert(T::alive == 0);
130 assert(T::constructed == 0);
131 assert(T::assigned == 0);
132 assert(T::destroyed == 1);
133 assert(static_cast<bool>(other) == false);
134 assert(static_cast<bool>(opt) == false);
136 assert(T::alive == 0);
137 { // empty to empty
138 optional<T> opt;
139 optional<int> other;
140 T::reset_constructors();
141 opt = std::move(other);
142 assert(T::alive == 0);
143 assert(T::constructed == 0);
144 assert(T::assigned == 0);
145 assert(T::destroyed == 0);
146 assert(static_cast<bool>(other) == false);
147 assert(static_cast<bool>(opt) == false);
149 assert(T::alive == 0);
153 void test_ambiguous_assign() {
154 using OptInt = std::optional<int>;
156 using T = AssignableFrom<OptInt&&>;
157 T::reset();
159 OptInt a(42);
160 std::optional<T> t;
161 t = std::move(a);
162 assert(T::type_constructed == 1);
163 assert(T::type_assigned == 0);
164 assert(T::int_constructed == 0);
165 assert(T::int_assigned == 0);
168 using Opt = std::optional<T>;
169 static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, "");
170 static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
171 static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
175 using T = AssignableFrom<OptInt const&&>;
176 T::reset();
178 const OptInt a(42);
179 std::optional<T> t;
180 t = std::move(a);
181 assert(T::type_constructed == 1);
182 assert(T::type_assigned == 0);
183 assert(T::int_constructed == 0);
184 assert(T::int_assigned == 0);
186 T::reset();
188 OptInt a(42);
189 std::optional<T> t;
190 t = std::move(a);
191 assert(T::type_constructed == 1);
192 assert(T::type_assigned == 0);
193 assert(T::int_constructed == 0);
194 assert(T::int_assigned == 0);
197 using Opt = std::optional<T>;
198 static_assert(std::is_assignable<Opt&, OptInt&&>::value, "");
199 static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
200 static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
206 TEST_CONSTEXPR_CXX20 bool test()
209 optional<int> opt;
210 optional<short> opt2;
211 opt = std::move(opt2);
212 assert(static_cast<bool>(opt2) == false);
213 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
216 optional<int> opt;
217 optional<short> opt2(short{2});
218 opt = std::move(opt2);
219 assert(static_cast<bool>(opt2) == true);
220 assert(*opt2 == 2);
221 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
222 assert(*opt == *opt2);
225 optional<int> opt(3);
226 optional<short> opt2;
227 opt = std::move(opt2);
228 assert(static_cast<bool>(opt2) == false);
229 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
232 optional<int> opt(3);
233 optional<short> opt2(short{2});
234 opt = std::move(opt2);
235 assert(static_cast<bool>(opt2) == true);
236 assert(*opt2 == 2);
237 assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
238 assert(*opt == *opt2);
241 enum class state_t { inactive, constructed, copy_assigned, move_assigned };
242 class StateTracker {
243 public:
244 constexpr StateTracker(state_t& s)
245 : state_(&s)
247 *state_ = state_t::constructed;
250 StateTracker(StateTracker&&) = default;
251 StateTracker(StateTracker const&) = default;
253 constexpr StateTracker& operator=(StateTracker&& other) noexcept
255 *state_ = state_t::inactive;
256 state_ = other.state_;
257 *state_ = state_t::move_assigned;
258 other.state_ = nullptr;
259 return *this;
262 constexpr StateTracker& operator=(StateTracker const& other) noexcept
264 *state_ = state_t::inactive;
265 state_ = other.state_;
266 *state_ = state_t::copy_assigned;
267 return *this;
269 private:
270 state_t* state_;
273 auto state = std::array{state_t::inactive, state_t::inactive};
274 auto opt1 = std::optional<StateTracker>(state[0]);
275 assert(state[0] == state_t::constructed);
277 auto opt2 = std::optional<StateTracker>(state[1]);
278 assert(state[1] == state_t::constructed);
280 opt1 = std::move(opt2);
281 assert(state[0] == state_t::inactive);
282 assert(state[1] == state_t::move_assigned);
285 auto state = std::array{state_t::inactive, state_t::inactive};
286 auto opt1 = std::optional<StateTracker>(state[0]);
287 assert(state[0] == state_t::constructed);
289 auto opt2 = std::optional<StateTracker>(state[1]);
290 assert(state[1] == state_t::constructed);
292 opt1 = opt2;
293 assert(state[0] == state_t::inactive);
294 assert(state[1] == state_t::copy_assigned);
297 return true;
301 int main(int, char**)
303 #if TEST_STD_VER > 17
304 static_assert(test());
305 #endif
306 test_with_test_type();
307 test_ambiguous_assign();
308 test();
310 optional<std::unique_ptr<B>> opt;
311 optional<std::unique_ptr<D>> other(new D());
312 opt = std::move(other);
313 assert(static_cast<bool>(opt) == true);
314 assert(static_cast<bool>(other) == true);
315 assert(opt->get() != nullptr);
316 assert(other->get() == nullptr);
318 #ifndef TEST_HAS_NO_EXCEPTIONS
320 optional<X> opt;
321 optional<int> opt2(42);
322 assert(static_cast<bool>(opt2) == true);
325 X::throw_now = true;
326 opt = std::move(opt2);
327 assert(false);
329 catch (int i)
331 assert(i == 6);
332 assert(static_cast<bool>(opt) == false);
335 #endif
337 return 0;