]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/20_util/variant/exception_safety.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / variant / exception_safety.cc
CommitLineData
8d9254fc 1// Copyright (C) 2019-2020 Free Software Foundation, Inc.
10f26de9
JW
2//
3// This file is part of the GNU ISO C++ Library. This library is free
4// software; you can redistribute it and/or modify it under the
5// terms of the GNU General Public License as published by the
6// Free Software Foundation; either version 3, or (at your option)
7// any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License along
15// with this library; see the file COPYING3. If not see
16// <http://www.gnu.org/licenses/>.
17
18// { dg-options "-std=gnu++17" }
19// { dg-do run { target c++17 } }
20
21#include <variant>
22#include <vector>
23#include <string>
24#include <memory_resource>
25#include <memory>
26#include <functional>
27#include <any>
28#include <testsuite_hooks.h>
29
30void
31test01()
32{
33#if _GLIBCXX_USE_CXX11_ABI
34 std::variant<int, std::pmr::string, std::pmr::vector<int>> v(1);
35 VERIFY( v.index() == 0 );
36
37 try
38 {
39 std::pmr::string s = "how long is a piece of SSO string?";
40 v.emplace<1>(s, std::pmr::null_memory_resource());
41 VERIFY( false );
42 }
43 catch(const std::bad_alloc&)
44 {
45 VERIFY( v.valueless_by_exception() );
46 }
47
48 v.emplace<0>(2);
49 VERIFY( v.index() == 0 );
50
51 try
52 {
53 v.emplace<2>({1, 2, 3}, std::pmr::null_memory_resource());
54 VERIFY( false );
55 }
56 catch(const std::bad_alloc&)
57 {
58 VERIFY( v.valueless_by_exception() );
59 }
60#endif
61}
62
63void
64test02()
65{
66 struct X
67 {
68 X(int i) : i(1) { if (i > 2) throw 3; }
69 X(std::initializer_list<int> l) : i(2) { if (l.size() > 2) throw 3; }
70 int i;
71 };
72 static_assert( std::is_trivially_copyable_v<X> );
73
74 std::variant<std::monostate, int, X> v(111);
75 VERIFY( v.index() == 1 );
76
77 try
78 {
79 v.emplace<X>(3);
80 VERIFY( false );
81 }
82 catch(int)
83 {
84 VERIFY( !v.valueless_by_exception() );
85 VERIFY( v.index() == 1 );
86 VERIFY( std::get<int>(v) == 111 );
87 }
88
89 v.emplace<X>(1);
90 VERIFY( v.index() == 2 );
91 VERIFY( std::get<X>(v).i == 1 );
92
93 try
94 {
95 v.emplace<X>(3);
96 VERIFY( false );
97 }
98 catch(int)
99 {
100 VERIFY( !v.valueless_by_exception() );
101 VERIFY( v.index() == 2 );
102 VERIFY( std::get<X>(v).i == 1 );
103 }
104
105 try
106 {
107 v.emplace<X>({1, 2, 3});
108 VERIFY( false );
109 }
110 catch(int)
111 {
112 VERIFY( !v.valueless_by_exception() );
113 VERIFY( v.index() == 2 );
114 VERIFY( std::get<X>(v).i == 1 );
115 }
116}
117
118template<typename T, typename V>
119 bool bad_emplace(V& v)
120 {
121 struct X {
122 operator T() const { throw 1; }
123 };
124
125 const auto index = v.index();
126
127 try
128 {
129 if (std::is_same_v<T, std::any>)
130 {
131 // Need to test std::any differently, because emplace<std::any>(X{})
132 // would create a std::any with a contained X, instead of using
133 // X::operator any() to convert to std::any.
134 struct ThrowOnCopy {
135 ThrowOnCopy() { }
136 ThrowOnCopy(const ThrowOnCopy&) { throw 1; }
137 } t;
138 v.template emplace<std::any>(t);
139 }
140 else
141 v.template emplace<T>(X{});
142 }
143 catch (int)
144 {
145 return v.index() == index;
146 }
147 return false;
148 }
149
150void
151test03()
152{
153 struct TriviallyCopyable { int i = 0; };
154
155 std::variant<std::monostate, int, TriviallyCopyable, std::optional<int>,
156 std::string, std::vector<int>, std::function<void()>, std::any,
157 std::shared_ptr<int>, std::weak_ptr<int>, std::unique_ptr<int>> v(1);
158 VERIFY( v.index() == 1 );
159
160 VERIFY( bad_emplace<int>(v) );
161 VERIFY( bad_emplace<TriviallyCopyable>(v) );
162 VERIFY( bad_emplace<std::optional<int>>(v) );
163 VERIFY( bad_emplace<std::string>(v) );
164 VERIFY( bad_emplace<std::vector<int>>(v) );
165 VERIFY( bad_emplace<std::function<void()>>(v) );
166 VERIFY( bad_emplace<std::any>(v) );
167 VERIFY( bad_emplace<std::shared_ptr<int>>(v) );
168 VERIFY( bad_emplace<std::weak_ptr<int>>(v) );
169 VERIFY( bad_emplace<std::unique_ptr<int>>(v) );
170}
171
86a57ce1
JW
172void
173test04()
174{
175 // LWG 2904. Make variant move-assignment more exception safe
176
177 struct ThrowOnCopy
178 {
179 ThrowOnCopy() { }
180 ThrowOnCopy(const ThrowOnCopy&) { throw 1; }
181 ThrowOnCopy& operator=(const ThrowOnCopy&) { throw "shouldn't happen"; }
182 ThrowOnCopy(ThrowOnCopy&&) noexcept { }
183 };
184
185 std::variant<int, ThrowOnCopy> v1(std::in_place_type<ThrowOnCopy>), v2(2);
186 try
187 {
188 v2 = v1; // uses variant<Types...>::operator=(const variant&)
189 VERIFY( false );
190 }
191 catch (int)
192 {
193 VERIFY( !v2.valueless_by_exception() );
194 VERIFY( v2.index() == 0 );
195 VERIFY( std::get<0>(v2) == 2 );
196 }
197
198 try
199 {
200 ThrowOnCopy toc;
201 v2 = toc; // uses variant<Types...>::operator=(T&&)
202 VERIFY( false );
203 }
204 catch (int)
205 {
206 VERIFY( !v2.valueless_by_exception() );
207 VERIFY( v2.index() == 0 );
208 VERIFY( std::get<0>(v2) == 2 );
209 }
210}
211
10f26de9
JW
212int
213main()
214{
215 test01();
216 test02();
217 test03();
86a57ce1 218 test04();
10f26de9 219}