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
931cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
10a9e65961SEric Fiselier // <optional>
11a9e65961SEric Fiselier
12a9e65961SEric Fiselier // template <class U> optional<T>& operator=(U&& v);
13a9e65961SEric Fiselier
14a9e65961SEric Fiselier #include <optional>
15a9e65961SEric Fiselier #include <type_traits>
16a9e65961SEric Fiselier #include <cassert>
17a9e65961SEric Fiselier #include <memory>
18a9e65961SEric Fiselier
19a9e65961SEric Fiselier #include "test_macros.h"
20cc89063bSNico Weber #include "archetypes.h"
21a9e65961SEric Fiselier
22a9e65961SEric Fiselier using std::optional;
23a9e65961SEric Fiselier
24a9e65961SEric Fiselier struct ThrowAssign {
25a9e65961SEric Fiselier static int dtor_called;
26a9e65961SEric Fiselier ThrowAssign() = default;
ThrowAssignThrowAssign27a9e65961SEric Fiselier ThrowAssign(int) { TEST_THROW(42); }
operator =ThrowAssign28a9e65961SEric Fiselier ThrowAssign& operator=(int) {
29a9e65961SEric Fiselier TEST_THROW(42);
30a9e65961SEric Fiselier }
~ThrowAssignThrowAssign31a9e65961SEric Fiselier ~ThrowAssign() { ++dtor_called; }
32a9e65961SEric Fiselier };
33a9e65961SEric Fiselier int ThrowAssign::dtor_called = 0;
34a9e65961SEric Fiselier
35a9e65961SEric Fiselier template <class T, class Arg = T, bool Expect = true>
assert_assignable()36a9e65961SEric Fiselier void assert_assignable() {
37a9e65961SEric Fiselier static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, "");
38a9e65961SEric Fiselier static_assert(!std::is_assignable<const optional<T>&, Arg>::value, "");
39a9e65961SEric Fiselier }
40a9e65961SEric Fiselier
41a9e65961SEric Fiselier struct MismatchType {
MismatchTypeMismatchType42a9e65961SEric Fiselier explicit MismatchType(int) {}
MismatchTypeMismatchType43a9e65961SEric Fiselier explicit MismatchType(char*) {}
44a9e65961SEric Fiselier explicit MismatchType(int*) = delete;
operator =MismatchType45a9e65961SEric Fiselier MismatchType& operator=(int) { return *this; }
operator =MismatchType46a9e65961SEric Fiselier MismatchType& operator=(int*) { return *this; }
47a9e65961SEric Fiselier MismatchType& operator=(char*) = delete;
48a9e65961SEric Fiselier };
49a9e65961SEric Fiselier
50015fcffdSEric Fiselier struct FromOptionalType {
51015fcffdSEric Fiselier using Opt = std::optional<FromOptionalType>;
52015fcffdSEric Fiselier FromOptionalType() = default;
53015fcffdSEric Fiselier FromOptionalType(FromOptionalType const&) = delete;
54015fcffdSEric Fiselier template <class Dummy = void>
FromOptionalTypeFromOptionalType55015fcffdSEric Fiselier constexpr FromOptionalType(Opt&) { Dummy::BARK; }
56015fcffdSEric Fiselier template <class Dummy = void>
operator =FromOptionalType57015fcffdSEric Fiselier constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; }
58015fcffdSEric Fiselier };
59015fcffdSEric Fiselier
test_sfinae()60a9e65961SEric Fiselier void test_sfinae() {
61a9e65961SEric Fiselier using I = TestTypes::TestType;
62a9e65961SEric Fiselier using E = ExplicitTestTypes::TestType;
63a9e65961SEric Fiselier assert_assignable<int>();
64a9e65961SEric Fiselier assert_assignable<int, int&>();
65a9e65961SEric Fiselier assert_assignable<int, int const&>();
66a9e65961SEric Fiselier // Implicit test type
67a9e65961SEric Fiselier assert_assignable<I, I const&>();
68a9e65961SEric Fiselier assert_assignable<I, I&&>();
69a9e65961SEric Fiselier assert_assignable<I, int>();
70a9e65961SEric Fiselier assert_assignable<I, void*, false>();
71a9e65961SEric Fiselier // Explicit test type
72a9e65961SEric Fiselier assert_assignable<E, E const&>();
73a9e65961SEric Fiselier assert_assignable<E, E &&>();
74a9e65961SEric Fiselier assert_assignable<E, int>();
75a9e65961SEric Fiselier assert_assignable<E, void*, false>();
76a9e65961SEric Fiselier // Mismatch type
77a9e65961SEric Fiselier assert_assignable<MismatchType, int>();
78a9e65961SEric Fiselier assert_assignable<MismatchType, int*, false>();
79a9e65961SEric Fiselier assert_assignable<MismatchType, char*, false>();
80015fcffdSEric Fiselier // Type constructible from optional
81015fcffdSEric Fiselier assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>();
82a9e65961SEric Fiselier }
83a9e65961SEric Fiselier
test_with_test_type()84a9e65961SEric Fiselier void test_with_test_type()
85a9e65961SEric Fiselier {
86a9e65961SEric Fiselier using T = TestTypes::TestType;
87a9e65961SEric Fiselier T::reset();
88a9e65961SEric Fiselier { // to empty
89a9e65961SEric Fiselier optional<T> opt;
90a9e65961SEric Fiselier opt = 3;
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>(opt) == true);
97a9e65961SEric Fiselier assert(*opt == T(3));
98a9e65961SEric Fiselier }
99a9e65961SEric Fiselier { // to existing
100a9e65961SEric Fiselier optional<T> opt(42);
101a9e65961SEric Fiselier T::reset_constructors();
102a9e65961SEric Fiselier opt = 3;
103a9e65961SEric Fiselier assert(T::alive == 1);
104a9e65961SEric Fiselier assert(T::constructed == 0);
105a9e65961SEric Fiselier assert(T::assigned == 1);
106a9e65961SEric Fiselier assert(T::value_assigned == 1);
107a9e65961SEric Fiselier assert(T::destroyed == 0);
108a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
109a9e65961SEric Fiselier assert(*opt == T(3));
110a9e65961SEric Fiselier }
111a9e65961SEric Fiselier { // test default argument
112a9e65961SEric Fiselier optional<T> opt;
113a9e65961SEric Fiselier T::reset_constructors();
114a9e65961SEric Fiselier opt = {1, 2};
115a9e65961SEric Fiselier assert(T::alive == 1);
116a9e65961SEric Fiselier assert(T::constructed == 2);
117a9e65961SEric Fiselier assert(T::value_constructed == 1);
118a9e65961SEric Fiselier assert(T::move_constructed == 1);
119a9e65961SEric Fiselier assert(T::assigned == 0);
120a9e65961SEric Fiselier assert(T::destroyed == 1);
121a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
122a9e65961SEric Fiselier assert(*opt == T(1, 2));
123a9e65961SEric Fiselier }
124a9e65961SEric Fiselier { // test default argument
125a9e65961SEric Fiselier optional<T> opt(42);
126a9e65961SEric Fiselier T::reset_constructors();
127a9e65961SEric Fiselier opt = {1, 2};
128a9e65961SEric Fiselier assert(T::alive == 1);
129a9e65961SEric Fiselier assert(T::constructed == 1);
130a9e65961SEric Fiselier assert(T::value_constructed == 1);
131a9e65961SEric Fiselier assert(T::assigned == 1);
132a9e65961SEric Fiselier assert(T::move_assigned == 1);
133a9e65961SEric Fiselier assert(T::destroyed == 1);
134a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
135a9e65961SEric Fiselier assert(*opt == T(1, 2));
136a9e65961SEric Fiselier }
137a9e65961SEric Fiselier { // test default argument
138a9e65961SEric Fiselier optional<T> opt;
139a9e65961SEric Fiselier T::reset_constructors();
140a9e65961SEric Fiselier opt = {1};
141a9e65961SEric Fiselier assert(T::alive == 1);
142a9e65961SEric Fiselier assert(T::constructed == 2);
143a9e65961SEric Fiselier assert(T::value_constructed == 1);
144a9e65961SEric Fiselier assert(T::move_constructed == 1);
145a9e65961SEric Fiselier assert(T::assigned == 0);
146a9e65961SEric Fiselier assert(T::destroyed == 1);
147a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
148a9e65961SEric Fiselier assert(*opt == T(1));
149a9e65961SEric Fiselier }
150a9e65961SEric Fiselier { // test default argument
151a9e65961SEric Fiselier optional<T> opt(42);
152a9e65961SEric Fiselier T::reset_constructors();
153a9e65961SEric Fiselier opt = {};
154a9e65961SEric Fiselier assert(static_cast<bool>(opt) == false);
155a9e65961SEric Fiselier assert(T::alive == 0);
156a9e65961SEric Fiselier assert(T::constructed == 0);
157a9e65961SEric Fiselier assert(T::assigned == 0);
158a9e65961SEric Fiselier assert(T::destroyed == 1);
159a9e65961SEric Fiselier }
160a9e65961SEric Fiselier }
161a9e65961SEric Fiselier
162a9e65961SEric Fiselier template <class T, class Value = int>
test_with_type()163a9e65961SEric Fiselier void test_with_type() {
164a9e65961SEric Fiselier { // to empty
165a9e65961SEric Fiselier optional<T> opt;
166a9e65961SEric Fiselier opt = Value(3);
167a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
168a9e65961SEric Fiselier assert(*opt == T(3));
169a9e65961SEric Fiselier }
170a9e65961SEric Fiselier { // to existing
171a9e65961SEric Fiselier optional<T> opt(Value(42));
172a9e65961SEric Fiselier opt = Value(3);
173a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
174a9e65961SEric Fiselier assert(*opt == T(3));
175a9e65961SEric Fiselier }
176a9e65961SEric Fiselier { // test const
177a9e65961SEric Fiselier optional<T> opt(Value(42));
178a9e65961SEric Fiselier const T t(Value(3));
179a9e65961SEric Fiselier opt = t;
180a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
181a9e65961SEric Fiselier assert(*opt == T(3));
182a9e65961SEric Fiselier }
183a9e65961SEric Fiselier { // test default argument
184a9e65961SEric Fiselier optional<T> opt;
185a9e65961SEric Fiselier opt = {Value(1)};
186a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
187a9e65961SEric Fiselier assert(*opt == T(1));
188a9e65961SEric Fiselier }
189a9e65961SEric Fiselier { // test default argument
190a9e65961SEric Fiselier optional<T> opt(Value(42));
191a9e65961SEric Fiselier opt = {};
192a9e65961SEric Fiselier assert(static_cast<bool>(opt) == false);
193a9e65961SEric Fiselier }
194a9e65961SEric Fiselier }
195a9e65961SEric Fiselier
196a9e65961SEric Fiselier template <class T>
test_with_type_multi()197a9e65961SEric Fiselier void test_with_type_multi() {
198a9e65961SEric Fiselier test_with_type<T>();
199a9e65961SEric Fiselier { // test default argument
200a9e65961SEric Fiselier optional<T> opt;
201a9e65961SEric Fiselier opt = {1, 2};
202a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
203a9e65961SEric Fiselier assert(*opt == T(1, 2));
204a9e65961SEric Fiselier }
205a9e65961SEric Fiselier { // test default argument
206a9e65961SEric Fiselier optional<T> opt(42);
207a9e65961SEric Fiselier opt = {1, 2};
208a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
209a9e65961SEric Fiselier assert(*opt == T(1, 2));
210a9e65961SEric Fiselier }
211a9e65961SEric Fiselier }
212a9e65961SEric Fiselier
test_throws()213a9e65961SEric Fiselier void test_throws()
214a9e65961SEric Fiselier {
215a9e65961SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
216a9e65961SEric Fiselier using T = ThrowAssign;
217a9e65961SEric Fiselier {
218a9e65961SEric Fiselier optional<T> opt;
219a9e65961SEric Fiselier try {
220a9e65961SEric Fiselier opt = 42;
221a9e65961SEric Fiselier assert(false);
222a9e65961SEric Fiselier } catch (int) {}
223a9e65961SEric Fiselier assert(static_cast<bool>(opt) == false);
224a9e65961SEric Fiselier }
225a9e65961SEric Fiselier assert(T::dtor_called == 0);
226a9e65961SEric Fiselier {
227a9e65961SEric Fiselier T::dtor_called = 0;
228a9e65961SEric Fiselier optional<T> opt(std::in_place);
229a9e65961SEric Fiselier try {
230a9e65961SEric Fiselier opt = 42;
231a9e65961SEric Fiselier assert(false);
232a9e65961SEric Fiselier } catch (int) {}
233a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
234a9e65961SEric Fiselier assert(T::dtor_called == 0);
235a9e65961SEric Fiselier }
236a9e65961SEric Fiselier assert(T::dtor_called == 1);
237a9e65961SEric Fiselier #endif
238a9e65961SEric Fiselier }
239a9e65961SEric Fiselier
240a9e65961SEric Fiselier enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 };
241a9e65961SEric Fiselier
242a9e65961SEric Fiselier using Fn = void(*)();
243a9e65961SEric Fiselier
244*3c62198cSLouis Dionne // https://llvm.org/PR38638
245954014a0SMarshall Clow template <class T>
pr38638(T v)246954014a0SMarshall Clow constexpr T pr38638(T v)
247954014a0SMarshall Clow {
248954014a0SMarshall Clow std::optional<T> o;
249954014a0SMarshall Clow o = v;
250954014a0SMarshall Clow return *o + 2;
251954014a0SMarshall Clow }
252954014a0SMarshall Clow
253954014a0SMarshall Clow
main(int,char **)2542df59c50SJF Bastien int main(int, char**)
255a9e65961SEric Fiselier {
256a9e65961SEric Fiselier test_sfinae();
257a9e65961SEric Fiselier // Test with instrumented type
258a9e65961SEric Fiselier test_with_test_type();
259a9e65961SEric Fiselier // Test with various scalar types
260a9e65961SEric Fiselier test_with_type<int>();
261a9e65961SEric Fiselier test_with_type<MyEnum, MyEnum>();
262a9e65961SEric Fiselier test_with_type<int, MyEnum>();
263a9e65961SEric Fiselier test_with_type<Fn, Fn>();
264a9e65961SEric Fiselier // Test types with multi argument constructors
265a9e65961SEric Fiselier test_with_type_multi<ConstexprTestTypes::TestType>();
266a9e65961SEric Fiselier test_with_type_multi<TrivialTestTypes::TestType>();
267a9e65961SEric Fiselier // Test move only types
268a9e65961SEric Fiselier {
269a9e65961SEric Fiselier optional<std::unique_ptr<int>> opt;
270a9e65961SEric Fiselier opt = std::unique_ptr<int>(new int(3));
271a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
272a9e65961SEric Fiselier assert(**opt == 3);
273a9e65961SEric Fiselier }
274a9e65961SEric Fiselier {
275a9e65961SEric Fiselier optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2)));
276a9e65961SEric Fiselier opt = std::unique_ptr<int>(new int(3));
277a9e65961SEric Fiselier assert(static_cast<bool>(opt) == true);
278a9e65961SEric Fiselier assert(**opt == 3);
279a9e65961SEric Fiselier }
280a9e65961SEric Fiselier test_throws();
2812df59c50SJF Bastien
282954014a0SMarshall Clow static_assert(pr38638(3) == 5, "");
283954014a0SMarshall Clow
2842df59c50SJF Bastien return 0;
285a9e65961SEric Fiselier }
286