1// Copyright (C) 2013-2020 Free Software Foundation, Inc.
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
18namespace cons_value {
19
20struct tracker
21{
22  tracker(int value) : value(value) { ++count; }
23  ~tracker() { --count; }
24
25  tracker(tracker const& other) : value(other.value) { ++count; }
26  tracker(tracker&& other) : value(other.value)
27  {
28    other.value = -1;
29    ++count;
30  }
31
32  tracker& operator=(tracker const&) = default;
33  tracker& operator=(tracker&&) = default;
34
35  int value;
36
37  static int count;
38};
39
40int tracker::count = 0;
41
42struct exception { };
43
44struct throwing_construction
45{
46  explicit throwing_construction(bool propagate) : propagate(propagate) { }
47
48  throwing_construction(throwing_construction const& other)
49  : propagate(other.propagate)
50  {
51    if(propagate)
52      throw exception {};
53  }
54
55  bool propagate;
56};
57
58static void
59test ()
60{
61  // [20.5.4.1] Constructors
62
63  {
64    auto i = 0x1234ABCD;
65    gdb::optional<long> o { i };
66    VERIFY( o );
67    VERIFY( *o == 0x1234ABCD );
68    VERIFY( i == 0x1234ABCD );
69  }
70
71  {
72    auto i = 0x1234ABCD;
73    gdb::optional<long> o = i;
74    VERIFY( o );
75    VERIFY( *o == 0x1234ABCD );
76    VERIFY( i == 0x1234ABCD );
77  }
78
79  {
80    auto i = 0x1234ABCD;
81    gdb::optional<long> o = { i };
82    VERIFY( o );
83    VERIFY( *o == 0x1234ABCD );
84    VERIFY( i == 0x1234ABCD );
85  }
86
87  {
88    auto i = 0x1234ABCD;
89    gdb::optional<long> o { std::move(i) };
90    VERIFY( o );
91    VERIFY( *o == 0x1234ABCD );
92    VERIFY( i == 0x1234ABCD );
93  }
94
95  {
96    auto i = 0x1234ABCD;
97    gdb::optional<long> o = std::move(i);
98    VERIFY( o );
99    VERIFY( *o == 0x1234ABCD );
100    VERIFY( i == 0x1234ABCD );
101  }
102
103  {
104    auto i = 0x1234ABCD;
105    gdb::optional<long> o = { std::move(i) };
106    VERIFY( o );
107    VERIFY( *o == 0x1234ABCD );
108    VERIFY( i == 0x1234ABCD );
109  }
110
111#ifndef GDB_OPTIONAL
112  {
113    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
114    gdb::optional<std::vector<int>> o { v };
115    VERIFY( !v.empty() );
116    VERIFY( o->size() == 6 );
117  }
118#endif
119
120  {
121    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
122    gdb::optional<std::vector<int>> o = v;
123    VERIFY( !v.empty() );
124    VERIFY( o->size() == 6 );
125  }
126
127  {
128    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
129    gdb::optional<std::vector<int>> o { v };
130    VERIFY( !v.empty() );
131    VERIFY( o->size() == 6 );
132  }
133
134  {
135    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
136    gdb::optional<std::vector<int>> o { std::move(v) };
137    VERIFY( v.empty() );
138    VERIFY( o->size() == 6 );
139  }
140
141  {
142    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
143    gdb::optional<std::vector<int>> o = std::move(v);
144    VERIFY( v.empty() );
145    VERIFY( o->size() == 6 );
146  }
147
148  {
149    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
150    gdb::optional<std::vector<int>> o { std::move(v) };
151    VERIFY( v.empty() );
152    VERIFY( o->size() == 6 );
153  }
154
155  {
156    tracker t { 333 };
157    gdb::optional<tracker> o = t;
158    VERIFY( o->value == 333 );
159    VERIFY( tracker::count == 2 );
160    VERIFY( t.value == 333 );
161  }
162
163  {
164    tracker t { 333 };
165    gdb::optional<tracker> o = std::move(t);
166    VERIFY( o->value == 333 );
167    VERIFY( tracker::count == 2 );
168    VERIFY( t.value == -1 );
169  }
170
171  enum outcome { nothrow, caught, bad_catch };
172
173  {
174    outcome result = nothrow;
175    throwing_construction t { false };
176
177    try
178    {
179      gdb::optional<throwing_construction> o { t };
180    }
181    catch(exception const&)
182    { result = caught; }
183    catch(...)
184    { result = bad_catch; }
185
186    VERIFY( result == nothrow );
187  }
188
189  {
190    outcome result = nothrow;
191    throwing_construction t { true };
192
193    try
194    {
195      gdb::optional<throwing_construction> o { t };
196    }
197    catch(exception const&)
198    { result = caught; }
199    catch(...)
200    { result = bad_catch; }
201
202    VERIFY( result == caught );
203  }
204
205  {
206    outcome result = nothrow;
207    throwing_construction t { false };
208
209    try
210    {
211      gdb::optional<throwing_construction> o { std::move(t) };
212    }
213    catch(exception const&)
214    { result = caught; }
215    catch(...)
216    { result = bad_catch; }
217
218    VERIFY( result == nothrow );
219  }
220
221  {
222    outcome result = nothrow;
223    throwing_construction t { true };
224
225    try
226    {
227      gdb::optional<throwing_construction> o { std::move(t) };
228    }
229    catch(exception const&)
230    { result = caught; }
231    catch(...)
232    { result = bad_catch; }
233
234    VERIFY( result == caught );
235  }
236
237  {
238#ifndef GDB_OPTIONAL
239    gdb::optional<std::string> os = "foo";
240#endif
241    struct X
242    {
243      explicit X(int) {}
244      X& operator=(int) {return *this;}
245    };
246#ifndef GDB_OPTIONAL
247    gdb::optional<X> ox{42};
248#endif
249    gdb::optional<int> oi{42};
250#ifndef GDB_OPTIONAL
251    gdb::optional<X> ox2{oi};
252#endif
253    gdb::optional<std::string> os2;
254    os2 = "foo";
255#ifndef GDB_OPTIONAL
256    gdb::optional<X> ox3;
257    ox3 = 42;
258    gdb::optional<X> ox4;
259    ox4 = oi;
260#endif
261  }
262  {
263    // no converting construction.
264#ifndef GDB_OPTIONAL
265    gdb::optional<int> oi = gdb::optional<short>();
266    VERIFY(!bool(oi));
267    gdb::optional<std::string> os = gdb::optional<const char*>();
268    VERIFY(!bool(os));
269#endif
270    gdb::optional<gdb::optional<int>> ooi = gdb::optional<int>();
271    VERIFY(bool(ooi));
272    ooi = gdb::optional<int>();
273    VERIFY(bool(ooi));
274    ooi = gdb::optional<int>(42);
275    VERIFY(bool(ooi));
276    VERIFY(bool(*ooi));
277#ifndef GDB_OPTIONAL
278    gdb::optional<gdb::optional<int>> ooi2 = gdb::optional<short>();
279    VERIFY(bool(ooi2));
280    ooi2 = gdb::optional<short>();
281    VERIFY(bool(ooi2));
282    ooi2 = gdb::optional<short>(6);
283    VERIFY(bool(ooi2));
284    VERIFY(bool(*ooi2));
285    gdb::optional<gdb::optional<int>> ooi3 = gdb::optional<int>(42);
286    VERIFY(bool(ooi3));
287    VERIFY(bool(*ooi3));
288    gdb::optional<gdb::optional<int>> ooi4 = gdb::optional<short>(6);
289    VERIFY(bool(ooi4));
290    VERIFY(bool(*ooi4));
291#endif
292  }
293}
294
295} // namespace cons_value
296