Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / utilities / variant / variant.variant / variant.ctor / copy.pass.cpp
blob3a487c7e1f08683774606fba12c131691b9890ca
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
11 // XFAIL: availability-bad_variant_access-missing && !no-exceptions
13 // <variant>
15 // template <class ...Types> class variant;
17 // constexpr variant(variant const&);
19 #include <cassert>
20 #include <type_traits>
21 #include <variant>
23 #include "test_macros.h"
24 #include "test_workarounds.h"
26 struct NonT {
27 NonT(int v) : value(v) {}
28 NonT(const NonT &o) : value(o.value) {}
29 int value;
31 static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
33 struct NoCopy {
34 NoCopy(const NoCopy &) = delete;
37 struct MoveOnly {
38 MoveOnly(const MoveOnly &) = delete;
39 MoveOnly(MoveOnly &&) = default;
42 struct MoveOnlyNT {
43 MoveOnlyNT(const MoveOnlyNT &) = delete;
44 MoveOnlyNT(MoveOnlyNT &&) {}
47 struct NTCopy {
48 constexpr NTCopy(int v) : value(v) {}
49 NTCopy(const NTCopy &that) : value(that.value) {}
50 NTCopy(NTCopy &&) = delete;
51 int value;
54 static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, "");
55 static_assert(std::is_copy_constructible<NTCopy>::value, "");
57 struct TCopy {
58 constexpr TCopy(int v) : value(v) {}
59 TCopy(TCopy const &) = default;
60 TCopy(TCopy &&) = delete;
61 int value;
64 static_assert(std::is_trivially_copy_constructible<TCopy>::value, "");
66 struct TCopyNTMove {
67 constexpr TCopyNTMove(int v) : value(v) {}
68 TCopyNTMove(const TCopyNTMove&) = default;
69 TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; }
70 int value;
73 static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, "");
75 #ifndef TEST_HAS_NO_EXCEPTIONS
76 struct MakeEmptyT {
77 static int alive;
78 MakeEmptyT() { ++alive; }
79 MakeEmptyT(const MakeEmptyT &) {
80 ++alive;
81 // Don't throw from the copy constructor since variant's assignment
82 // operator performs a copy before committing to the assignment.
84 MakeEmptyT(MakeEmptyT &&) { throw 42; }
85 MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
86 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
87 ~MakeEmptyT() { --alive; }
90 int MakeEmptyT::alive = 0;
92 template <class Variant> void makeEmpty(Variant &v) {
93 Variant v2(std::in_place_type<MakeEmptyT>);
94 try {
95 v = std::move(v2);
96 assert(false);
97 } catch (...) {
98 assert(v.valueless_by_exception());
101 #endif // TEST_HAS_NO_EXCEPTIONS
103 void test_copy_ctor_sfinae() {
105 using V = std::variant<int, long>;
106 static_assert(std::is_copy_constructible<V>::value, "");
109 using V = std::variant<int, NoCopy>;
110 static_assert(!std::is_copy_constructible<V>::value, "");
113 using V = std::variant<int, MoveOnly>;
114 static_assert(!std::is_copy_constructible<V>::value, "");
117 using V = std::variant<int, MoveOnlyNT>;
118 static_assert(!std::is_copy_constructible<V>::value, "");
121 // Make sure we properly propagate triviality (see P0602R4).
123 using V = std::variant<int, long>;
124 static_assert(std::is_trivially_copy_constructible<V>::value, "");
127 using V = std::variant<int, NTCopy>;
128 static_assert(!std::is_trivially_copy_constructible<V>::value, "");
129 static_assert(std::is_copy_constructible<V>::value, "");
132 using V = std::variant<int, TCopy>;
133 static_assert(std::is_trivially_copy_constructible<V>::value, "");
136 using V = std::variant<int, TCopyNTMove>;
137 static_assert(std::is_trivially_copy_constructible<V>::value, "");
141 void test_copy_ctor_basic() {
143 std::variant<int> v(std::in_place_index<0>, 42);
144 std::variant<int> v2 = v;
145 assert(v2.index() == 0);
146 assert(std::get<0>(v2) == 42);
149 std::variant<int, long> v(std::in_place_index<1>, 42);
150 std::variant<int, long> v2 = v;
151 assert(v2.index() == 1);
152 assert(std::get<1>(v2) == 42);
155 std::variant<NonT> v(std::in_place_index<0>, 42);
156 assert(v.index() == 0);
157 std::variant<NonT> v2(v);
158 assert(v2.index() == 0);
159 assert(std::get<0>(v2).value == 42);
162 std::variant<int, NonT> v(std::in_place_index<1>, 42);
163 assert(v.index() == 1);
164 std::variant<int, NonT> v2(v);
165 assert(v2.index() == 1);
166 assert(std::get<1>(v2).value == 42);
169 // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
171 constexpr std::variant<int> v(std::in_place_index<0>, 42);
172 static_assert(v.index() == 0, "");
173 constexpr std::variant<int> v2 = v;
174 static_assert(v2.index() == 0, "");
175 static_assert(std::get<0>(v2) == 42, "");
178 constexpr std::variant<int, long> v(std::in_place_index<1>, 42);
179 static_assert(v.index() == 1, "");
180 constexpr std::variant<int, long> v2 = v;
181 static_assert(v2.index() == 1, "");
182 static_assert(std::get<1>(v2) == 42, "");
185 constexpr std::variant<TCopy> v(std::in_place_index<0>, 42);
186 static_assert(v.index() == 0, "");
187 constexpr std::variant<TCopy> v2(v);
188 static_assert(v2.index() == 0, "");
189 static_assert(std::get<0>(v2).value == 42, "");
192 constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42);
193 static_assert(v.index() == 1, "");
194 constexpr std::variant<int, TCopy> v2(v);
195 static_assert(v2.index() == 1, "");
196 static_assert(std::get<1>(v2).value == 42, "");
199 constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42);
200 static_assert(v.index() == 0, "");
201 constexpr std::variant<TCopyNTMove> v2(v);
202 static_assert(v2.index() == 0, "");
203 static_assert(std::get<0>(v2).value == 42, "");
206 constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42);
207 static_assert(v.index() == 1, "");
208 constexpr std::variant<int, TCopyNTMove> v2(v);
209 static_assert(v2.index() == 1, "");
210 static_assert(std::get<1>(v2).value == 42, "");
214 void test_copy_ctor_valueless_by_exception() {
215 #ifndef TEST_HAS_NO_EXCEPTIONS
216 using V = std::variant<int, MakeEmptyT>;
217 V v1;
218 makeEmpty(v1);
219 const V &cv1 = v1;
220 V v(cv1);
221 assert(v.valueless_by_exception());
222 #endif // TEST_HAS_NO_EXCEPTIONS
225 template <std::size_t Idx>
226 constexpr bool test_constexpr_copy_ctor_imp(std::variant<long, void*, const int> const& v) {
227 auto v2 = v;
228 return v2.index() == v.index() &&
229 v2.index() == Idx &&
230 std::get<Idx>(v2) == std::get<Idx>(v);
233 void test_constexpr_copy_ctor() {
234 // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
235 using V = std::variant<long, void*, const int>;
236 #ifdef TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
237 static_assert(std::is_trivially_destructible<V>::value, "");
238 static_assert(std::is_trivially_copy_constructible<V>::value, "");
239 static_assert(std::is_trivially_move_constructible<V>::value, "");
240 static_assert(!std::is_copy_assignable<V>::value, "");
241 static_assert(!std::is_move_assignable<V>::value, "");
242 #else // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
243 static_assert(std::is_trivially_copyable<V>::value, "");
244 #endif // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
245 static_assert(test_constexpr_copy_ctor_imp<0>(V(42l)), "");
246 static_assert(test_constexpr_copy_ctor_imp<1>(V(nullptr)), "");
247 static_assert(test_constexpr_copy_ctor_imp<2>(V(101)), "");
250 int main(int, char**) {
251 test_copy_ctor_basic();
252 test_copy_ctor_valueless_by_exception();
253 test_copy_ctor_sfinae();
254 test_constexpr_copy_ctor();
255 return 0;