1a9e65961SEric Fiselier //===----------------------------------------------------------------------===//
2a9e65961SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a9e65961SEric Fiselier //
7a9e65961SEric Fiselier //===----------------------------------------------------------------------===//
8a9e65961SEric Fiselier 
9*31cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10a9e65961SEric Fiselier // <optional>
11a9e65961SEric Fiselier 
12a9e65961SEric Fiselier // From LWG2451:
13a9e65961SEric Fiselier // template<class U>
14a9e65961SEric Fiselier //   optional<T>& operator=(const optional<U>& rhs);
15a9e65961SEric Fiselier 
16a9e65961SEric Fiselier #include <optional>
17a9e65961SEric Fiselier #include <type_traits>
18a9e65961SEric Fiselier #include <cassert>
19a9e65961SEric Fiselier 
20a9e65961SEric Fiselier #include "test_macros.h"
21cc89063bSNico Weber #include "archetypes.h"
22a9e65961SEric Fiselier 
23a9e65961SEric Fiselier using std::optional;
24a9e65961SEric Fiselier 
25a9e65961SEric Fiselier struct X
26a9e65961SEric Fiselier {
27a9e65961SEric Fiselier     static bool throw_now;
28a9e65961SEric Fiselier 
29a9e65961SEric Fiselier     X() = default;
XX30a9e65961SEric Fiselier     X(int)
31a9e65961SEric Fiselier     {
32a9e65961SEric Fiselier         if (throw_now)
33a9e65961SEric Fiselier             TEST_THROW(6);
34a9e65961SEric Fiselier     }
35a9e65961SEric Fiselier };
36a9e65961SEric Fiselier 
37a9e65961SEric Fiselier bool X::throw_now = false;
38a9e65961SEric Fiselier 
39a9e65961SEric Fiselier struct Y1
40a9e65961SEric Fiselier {
41a9e65961SEric Fiselier     Y1() = default;
Y1Y142a9e65961SEric Fiselier     Y1(const int&) {}
43a9e65961SEric Fiselier     Y1& operator=(const Y1&) = delete;
44a9e65961SEric Fiselier };
45a9e65961SEric Fiselier 
46a9e65961SEric Fiselier struct Y2
47a9e65961SEric Fiselier {
48a9e65961SEric Fiselier     Y2() = default;
49a9e65961SEric Fiselier     Y2(const int&) = delete;
operator =Y250a9e65961SEric Fiselier     Y2& operator=(const int&) { return *this; }
51a9e65961SEric Fiselier };
52a9e65961SEric Fiselier 
53a9e65961SEric Fiselier template <class T>
54a9e65961SEric Fiselier struct AssignableFrom {
55a9e65961SEric Fiselier   static int type_constructed;
56a9e65961SEric Fiselier   static int type_assigned;
57a9e65961SEric Fiselier static int int_constructed;
58a9e65961SEric Fiselier   static int int_assigned;
59a9e65961SEric Fiselier 
resetAssignableFrom60a9e65961SEric Fiselier   static void reset() {
61a9e65961SEric Fiselier       type_constructed = int_constructed = 0;
62a9e65961SEric Fiselier       type_assigned = int_assigned = 0;
63a9e65961SEric Fiselier   }
64a9e65961SEric Fiselier 
65a9e65961SEric Fiselier   AssignableFrom() = default;
66a9e65961SEric Fiselier 
AssignableFromAssignableFrom67a9e65961SEric Fiselier   explicit AssignableFrom(T) { ++type_constructed; }
operator =AssignableFrom68a9e65961SEric Fiselier   AssignableFrom& operator=(T) { ++type_assigned; return *this; }
69a9e65961SEric Fiselier 
AssignableFromAssignableFrom70a9e65961SEric Fiselier   AssignableFrom(int) { ++int_constructed; }
operator =AssignableFrom71a9e65961SEric Fiselier   AssignableFrom& operator=(int) { ++int_assigned; return *this; }
72a9e65961SEric Fiselier private:
73a9e65961SEric Fiselier   AssignableFrom(AssignableFrom const&) = delete;
74a9e65961SEric Fiselier   AssignableFrom& operator=(AssignableFrom const&) = delete;
75a9e65961SEric Fiselier };
76a9e65961SEric Fiselier 
77a9e65961SEric Fiselier template <class T> int AssignableFrom<T>::type_constructed = 0;
78a9e65961SEric Fiselier template <class T> int AssignableFrom<T>::type_assigned = 0;
79a9e65961SEric Fiselier template <class T> int AssignableFrom<T>::int_constructed = 0;
80a9e65961SEric Fiselier template <class T> int AssignableFrom<T>::int_assigned = 0;
81a9e65961SEric Fiselier 
82a9e65961SEric Fiselier 
test_with_test_type()83a9e65961SEric Fiselier void test_with_test_type() {
84a9e65961SEric Fiselier     using T = TestTypes::TestType;
85a9e65961SEric Fiselier     T::reset();
86a9e65961SEric Fiselier     { // non-empty to empty
87a9e65961SEric Fiselier         T::reset_constructors();
88a9e65961SEric Fiselier         optional<T> opt;
89a9e65961SEric Fiselier         const optional<int> other(42);
90a9e65961SEric Fiselier         opt = other;
91a9e65961SEric Fiselier         assert(T::alive == 1);
92a9e65961SEric Fiselier         assert(T::constructed == 1);
93a9e65961SEric Fiselier         assert(T::value_constructed == 1);
94a9e65961SEric Fiselier         assert(T::assigned == 0);
95a9e65961SEric Fiselier         assert(T::destroyed == 0);
96a9e65961SEric Fiselier         assert(static_cast<bool>(other) == true);
97a9e65961SEric Fiselier         assert(*other == 42);
98a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == true);
99a9e65961SEric Fiselier         assert(*opt == T(42));
100a9e65961SEric Fiselier     }
101a9e65961SEric Fiselier     assert(T::alive == 0);
102a9e65961SEric Fiselier     { // non-empty to non-empty
103a9e65961SEric Fiselier         optional<T> opt(101);
104a9e65961SEric Fiselier         const optional<int> other(42);
105a9e65961SEric Fiselier         T::reset_constructors();
106a9e65961SEric Fiselier         opt = other;
107a9e65961SEric Fiselier         assert(T::alive == 1);
108a9e65961SEric Fiselier         assert(T::constructed == 0);
109a9e65961SEric Fiselier         assert(T::assigned == 1);
110a9e65961SEric Fiselier         assert(T::value_assigned == 1);
111a9e65961SEric Fiselier         assert(T::destroyed == 0);
112a9e65961SEric Fiselier         assert(static_cast<bool>(other) == true);
113a9e65961SEric Fiselier         assert(*other == 42);
114a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == true);
115a9e65961SEric Fiselier         assert(*opt == T(42));
116a9e65961SEric Fiselier     }
117a9e65961SEric Fiselier     assert(T::alive == 0);
118a9e65961SEric Fiselier     { // empty to non-empty
119a9e65961SEric Fiselier         optional<T> opt(101);
120a9e65961SEric Fiselier         const optional<int> other;
121a9e65961SEric Fiselier         T::reset_constructors();
122a9e65961SEric Fiselier         opt = other;
123a9e65961SEric Fiselier         assert(T::alive == 0);
124a9e65961SEric Fiselier         assert(T::constructed == 0);
125a9e65961SEric Fiselier         assert(T::assigned == 0);
126a9e65961SEric Fiselier         assert(T::destroyed == 1);
127a9e65961SEric Fiselier         assert(static_cast<bool>(other) == false);
128a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == false);
129a9e65961SEric Fiselier     }
130a9e65961SEric Fiselier     assert(T::alive == 0);
131a9e65961SEric Fiselier     { // empty to empty
132a9e65961SEric Fiselier         optional<T> opt;
133a9e65961SEric Fiselier         const optional<int> other;
134a9e65961SEric Fiselier         T::reset_constructors();
135a9e65961SEric Fiselier         opt = other;
136a9e65961SEric Fiselier         assert(T::alive == 0);
137a9e65961SEric Fiselier         assert(T::constructed == 0);
138a9e65961SEric Fiselier         assert(T::assigned == 0);
139a9e65961SEric Fiselier         assert(T::destroyed == 0);
140a9e65961SEric Fiselier         assert(static_cast<bool>(other) == false);
141a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == false);
142a9e65961SEric Fiselier     }
143a9e65961SEric Fiselier     assert(T::alive == 0);
144a9e65961SEric Fiselier }
145a9e65961SEric Fiselier 
test_ambiguous_assign()14668b30bc0SCasey Carter void test_ambiguous_assign() {
147a9e65961SEric Fiselier     using OptInt = std::optional<int>;
148a9e65961SEric Fiselier     {
149a9e65961SEric Fiselier         using T = AssignableFrom<OptInt const&>;
150a9e65961SEric Fiselier         const OptInt a(42);
151a9e65961SEric Fiselier         T::reset();
152a9e65961SEric Fiselier         {
153a9e65961SEric Fiselier             std::optional<T> t;
154a9e65961SEric Fiselier             t = a;
155a9e65961SEric Fiselier             assert(T::type_constructed == 1);
156a9e65961SEric Fiselier             assert(T::type_assigned == 0);
157a9e65961SEric Fiselier             assert(T::int_constructed == 0);
158a9e65961SEric Fiselier             assert(T::int_assigned == 0);
159a9e65961SEric Fiselier         }
160a9e65961SEric Fiselier         T::reset();
161a9e65961SEric Fiselier         {
162a9e65961SEric Fiselier             std::optional<T> t(42);
163a9e65961SEric Fiselier             t = a;
164a9e65961SEric Fiselier             assert(T::type_constructed == 0);
165a9e65961SEric Fiselier             assert(T::type_assigned == 1);
166a9e65961SEric Fiselier             assert(T::int_constructed == 1);
167a9e65961SEric Fiselier             assert(T::int_assigned == 0);
168a9e65961SEric Fiselier         }
169a9e65961SEric Fiselier         T::reset();
170a9e65961SEric Fiselier         {
171a9e65961SEric Fiselier             std::optional<T> t(42);
172a9e65961SEric Fiselier             t = std::move(a);
173a9e65961SEric Fiselier             assert(T::type_constructed == 0);
174a9e65961SEric Fiselier             assert(T::type_assigned == 1);
175a9e65961SEric Fiselier             assert(T::int_constructed == 1);
176a9e65961SEric Fiselier             assert(T::int_assigned == 0);
177a9e65961SEric Fiselier         }
178a9e65961SEric Fiselier     }
179a9e65961SEric Fiselier     {
180a9e65961SEric Fiselier         using T = AssignableFrom<OptInt&>;
181a9e65961SEric Fiselier         OptInt a(42);
182a9e65961SEric Fiselier         T::reset();
183a9e65961SEric Fiselier         {
184a9e65961SEric Fiselier             std::optional<T> t;
185a9e65961SEric Fiselier             t = a;
186a9e65961SEric Fiselier             assert(T::type_constructed == 1);
187a9e65961SEric Fiselier             assert(T::type_assigned == 0);
188a9e65961SEric Fiselier             assert(T::int_constructed == 0);
189a9e65961SEric Fiselier             assert(T::int_assigned == 0);
190a9e65961SEric Fiselier         }
191a9e65961SEric Fiselier         {
192a9e65961SEric Fiselier             using Opt = std::optional<T>;
193a9e65961SEric Fiselier             static_assert(!std::is_assignable_v<Opt&, OptInt const&>, "");
194a9e65961SEric Fiselier         }
195a9e65961SEric Fiselier     }
196a9e65961SEric Fiselier }
197a9e65961SEric Fiselier 
198a9e65961SEric Fiselier 
main(int,char **)1992df59c50SJF Bastien int main(int, char**)
200a9e65961SEric Fiselier {
201a9e65961SEric Fiselier     test_with_test_type();
20268b30bc0SCasey Carter     test_ambiguous_assign();
203a9e65961SEric Fiselier     {
204a9e65961SEric Fiselier         optional<int> opt;
205a9e65961SEric Fiselier         constexpr optional<short> opt2;
206a9e65961SEric Fiselier         opt = opt2;
207a9e65961SEric Fiselier         static_assert(static_cast<bool>(opt2) == false, "");
208a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
209a9e65961SEric Fiselier     }
210a9e65961SEric Fiselier     {
211a9e65961SEric Fiselier         optional<int> opt;
212a9e65961SEric Fiselier         constexpr optional<short> opt2(short{2});
213a9e65961SEric Fiselier         opt = opt2;
214a9e65961SEric Fiselier         static_assert(static_cast<bool>(opt2) == true, "");
215a9e65961SEric Fiselier         static_assert(*opt2 == 2, "");
216a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
217a9e65961SEric Fiselier         assert(*opt == *opt2);
218a9e65961SEric Fiselier     }
219a9e65961SEric Fiselier     {
220a9e65961SEric Fiselier         optional<int> opt(3);
221a9e65961SEric Fiselier         constexpr optional<short> opt2;
222a9e65961SEric Fiselier         opt = opt2;
223a9e65961SEric Fiselier         static_assert(static_cast<bool>(opt2) == false, "");
224a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
225a9e65961SEric Fiselier     }
226a9e65961SEric Fiselier     {
227a9e65961SEric Fiselier         optional<int> opt(3);
228a9e65961SEric Fiselier         constexpr optional<short> opt2(short{2});
229a9e65961SEric Fiselier         opt = opt2;
230a9e65961SEric Fiselier         static_assert(static_cast<bool>(opt2) == true, "");
231a9e65961SEric Fiselier         static_assert(*opt2 == 2, "");
232a9e65961SEric Fiselier         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
233a9e65961SEric Fiselier         assert(*opt == *opt2);
234a9e65961SEric Fiselier     }
235a9e65961SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
236a9e65961SEric Fiselier     {
237a9e65961SEric Fiselier         optional<X> opt;
238a9e65961SEric Fiselier         optional<int> opt2(42);
239a9e65961SEric Fiselier         assert(static_cast<bool>(opt2) == true);
240a9e65961SEric Fiselier         try
241a9e65961SEric Fiselier         {
242a9e65961SEric Fiselier             X::throw_now = true;
243a9e65961SEric Fiselier             opt = opt2;
244a9e65961SEric Fiselier             assert(false);
245a9e65961SEric Fiselier         }
246a9e65961SEric Fiselier         catch (int i)
247a9e65961SEric Fiselier         {
248a9e65961SEric Fiselier             assert(i == 6);
249a9e65961SEric Fiselier             assert(static_cast<bool>(opt) == false);
250a9e65961SEric Fiselier         }
251a9e65961SEric Fiselier     }
252a9e65961SEric Fiselier #endif
2532df59c50SJF Bastien 
2542df59c50SJF Bastien   return 0;
255a9e65961SEric Fiselier }
256