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 
12c1bcd4c1SMarshall Clow // constexpr optional(const optional<T>& rhs);
13a9e65961SEric Fiselier 
14a9e65961SEric Fiselier #include <optional>
15a9e65961SEric Fiselier #include <type_traits>
16a9e65961SEric Fiselier #include <cassert>
17a9e65961SEric Fiselier 
18a9e65961SEric Fiselier #include "test_macros.h"
19cc89063bSNico Weber #include "archetypes.h"
20a9e65961SEric Fiselier 
21a9e65961SEric Fiselier using std::optional;
22a9e65961SEric Fiselier 
23a9e65961SEric Fiselier template <class T, class ...InitArgs>
test(InitArgs &&...args)24a9e65961SEric Fiselier void test(InitArgs&&... args)
25a9e65961SEric Fiselier {
26a9e65961SEric Fiselier     const optional<T> rhs(std::forward<InitArgs>(args)...);
27a9e65961SEric Fiselier     bool rhs_engaged = static_cast<bool>(rhs);
28a9e65961SEric Fiselier     optional<T> lhs = rhs;
29a9e65961SEric Fiselier     assert(static_cast<bool>(lhs) == rhs_engaged);
30a9e65961SEric Fiselier     if (rhs_engaged)
31a9e65961SEric Fiselier         assert(*lhs == *rhs);
32a9e65961SEric Fiselier }
33a9e65961SEric Fiselier 
3429b75d69SMarshall Clow template <class T, class ...InitArgs>
constexpr_test(InitArgs &&...args)3529b75d69SMarshall Clow constexpr bool constexpr_test(InitArgs&&... args)
3629b75d69SMarshall Clow {
3729b75d69SMarshall Clow     static_assert( std::is_trivially_copy_constructible_v<T>, ""); // requirement
3829b75d69SMarshall Clow     const optional<T> rhs(std::forward<InitArgs>(args)...);
3929b75d69SMarshall Clow     optional<T> lhs = rhs;
4029b75d69SMarshall Clow     return (lhs.has_value() == rhs.has_value()) &&
4129b75d69SMarshall Clow            (lhs.has_value() ? *lhs == *rhs : true);
4229b75d69SMarshall Clow }
4329b75d69SMarshall Clow 
test_throwing_ctor()44a9e65961SEric Fiselier void test_throwing_ctor() {
45a9e65961SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
46a9e65961SEric Fiselier     struct Z {
47a9e65961SEric Fiselier         Z() : count(0) {}
48a9e65961SEric Fiselier         Z(Z const& o) : count(o.count + 1)
49a9e65961SEric Fiselier         { if (count == 2) throw 6; }
50a9e65961SEric Fiselier         int count;
51a9e65961SEric Fiselier     };
52a9e65961SEric Fiselier     const Z z;
53a9e65961SEric Fiselier     const optional<Z> rhs(z);
54a9e65961SEric Fiselier     try
55a9e65961SEric Fiselier     {
56a9e65961SEric Fiselier         optional<Z> lhs(rhs);
57a9e65961SEric Fiselier         assert(false);
58a9e65961SEric Fiselier     }
59a9e65961SEric Fiselier     catch (int i)
60a9e65961SEric Fiselier     {
61a9e65961SEric Fiselier         assert(i == 6);
62a9e65961SEric Fiselier     }
63a9e65961SEric Fiselier #endif
64a9e65961SEric Fiselier }
65a9e65961SEric Fiselier 
66a9e65961SEric Fiselier template <class T, class ...InitArgs>
test_ref(InitArgs &&...args)67a9e65961SEric Fiselier void test_ref(InitArgs&&... args)
68a9e65961SEric Fiselier {
69a9e65961SEric Fiselier     const optional<T> rhs(std::forward<InitArgs>(args)...);
70a9e65961SEric Fiselier     bool rhs_engaged = static_cast<bool>(rhs);
71a9e65961SEric Fiselier     optional<T> lhs = rhs;
72a9e65961SEric Fiselier     assert(static_cast<bool>(lhs) == rhs_engaged);
73a9e65961SEric Fiselier     if (rhs_engaged)
74a9e65961SEric Fiselier         assert(&(*lhs) == &(*rhs));
75a9e65961SEric Fiselier }
76a9e65961SEric Fiselier 
77a9e65961SEric Fiselier 
test_reference_extension()78a9e65961SEric Fiselier void test_reference_extension()
79a9e65961SEric Fiselier {
80a9e65961SEric Fiselier #if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
81a9e65961SEric Fiselier     using T = TestTypes::TestType;
82a9e65961SEric Fiselier     T::reset();
83a9e65961SEric Fiselier     {
84a9e65961SEric Fiselier         T t;
85a9e65961SEric Fiselier         T::reset_constructors();
86a9e65961SEric Fiselier         test_ref<T&>();
87a9e65961SEric Fiselier         test_ref<T&>(t);
88a9e65961SEric Fiselier         assert(T::alive == 1);
89a9e65961SEric Fiselier         assert(T::constructed == 0);
90a9e65961SEric Fiselier         assert(T::assigned == 0);
91a9e65961SEric Fiselier         assert(T::destroyed == 0);
92a9e65961SEric Fiselier     }
93a9e65961SEric Fiselier     assert(T::destroyed == 1);
94a9e65961SEric Fiselier     assert(T::alive == 0);
95a9e65961SEric Fiselier     {
96a9e65961SEric Fiselier         T t;
97a9e65961SEric Fiselier         const T& ct = t;
98a9e65961SEric Fiselier         T::reset_constructors();
99a9e65961SEric Fiselier         test_ref<T const&>();
100a9e65961SEric Fiselier         test_ref<T const&>(t);
101a9e65961SEric Fiselier         test_ref<T const&>(ct);
102a9e65961SEric Fiselier         assert(T::alive == 1);
103a9e65961SEric Fiselier         assert(T::constructed == 0);
104a9e65961SEric Fiselier         assert(T::assigned == 0);
105a9e65961SEric Fiselier         assert(T::destroyed == 0);
106a9e65961SEric Fiselier     }
107a9e65961SEric Fiselier     assert(T::alive == 0);
108a9e65961SEric Fiselier     assert(T::destroyed == 1);
109a9e65961SEric Fiselier     {
110a9e65961SEric Fiselier         static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
111a9e65961SEric Fiselier         static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
112a9e65961SEric Fiselier     }
113a9e65961SEric Fiselier #endif
114a9e65961SEric Fiselier }
115a9e65961SEric Fiselier 
main(int,char **)1162df59c50SJF Bastien int main(int, char**)
117a9e65961SEric Fiselier {
118a9e65961SEric Fiselier     test<int>();
119a9e65961SEric Fiselier     test<int>(3);
12029b75d69SMarshall Clow     static_assert(constexpr_test<int>(), "" );
12129b75d69SMarshall Clow     static_assert(constexpr_test<int>(3), "" );
12229b75d69SMarshall Clow 
123a9e65961SEric Fiselier     {
12464428acfSEric Fiselier         const optional<const int> o(42);
12564428acfSEric Fiselier         optional<const int> o2(o);
12664428acfSEric Fiselier         assert(*o2 == 42);
12764428acfSEric Fiselier     }
12864428acfSEric Fiselier     {
129a9e65961SEric Fiselier         using T = TestTypes::TestType;
130a9e65961SEric Fiselier         T::reset();
131a9e65961SEric Fiselier         const optional<T> rhs;
132a9e65961SEric Fiselier         assert(T::alive == 0);
133a9e65961SEric Fiselier         const optional<T> lhs(rhs);
134a9e65961SEric Fiselier         assert(lhs.has_value() == false);
135a9e65961SEric Fiselier         assert(T::alive == 0);
136a9e65961SEric Fiselier     }
137a9e65961SEric Fiselier     TestTypes::TestType::reset();
138a9e65961SEric Fiselier     {
139a9e65961SEric Fiselier         using T = TestTypes::TestType;
140a9e65961SEric Fiselier         T::reset();
141a9e65961SEric Fiselier         const optional<T> rhs(42);
142a9e65961SEric Fiselier         assert(T::alive == 1);
143a9e65961SEric Fiselier         assert(T::value_constructed == 1);
144a9e65961SEric Fiselier         assert(T::copy_constructed == 0);
145a9e65961SEric Fiselier         const optional<T> lhs(rhs);
146a9e65961SEric Fiselier         assert(lhs.has_value());
147a9e65961SEric Fiselier         assert(T::copy_constructed == 1);
148a9e65961SEric Fiselier         assert(T::alive == 2);
149a9e65961SEric Fiselier     }
150a9e65961SEric Fiselier     TestTypes::TestType::reset();
151a9e65961SEric Fiselier     {
152a9e65961SEric Fiselier         using namespace ConstexprTestTypes;
153a9e65961SEric Fiselier         test<TestType>();
154a9e65961SEric Fiselier         test<TestType>(42);
155a9e65961SEric Fiselier     }
156a9e65961SEric Fiselier     {
157a9e65961SEric Fiselier         using namespace TrivialTestTypes;
158a9e65961SEric Fiselier         test<TestType>();
159a9e65961SEric Fiselier         test<TestType>(42);
160a9e65961SEric Fiselier     }
161a9e65961SEric Fiselier     {
162a9e65961SEric Fiselier         test_throwing_ctor();
163a9e65961SEric Fiselier     }
164a9e65961SEric Fiselier     {
165a9e65961SEric Fiselier         test_reference_extension();
166a9e65961SEric Fiselier     }
167c1bcd4c1SMarshall Clow     {
168c1bcd4c1SMarshall Clow         constexpr std::optional<int> o1{4};
169c1bcd4c1SMarshall Clow         constexpr std::optional<int> o2 = o1;
170c1bcd4c1SMarshall Clow         static_assert( *o2 == 4, "" );
171c1bcd4c1SMarshall Clow     }
1722df59c50SJF Bastien 
1732df59c50SJF Bastien   return 0;
174a9e65961SEric Fiselier }
175