1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++03, c++11, c++14
11 
12 // Throwing bad_variant_access is supported starting in macosx10.13
13 // XFAIL: with_system_cxx_lib=macosx10.12 && !no-exceptions
14 // XFAIL: with_system_cxx_lib=macosx10.11 && !no-exceptions
15 // XFAIL: with_system_cxx_lib=macosx10.10 && !no-exceptions
16 // XFAIL: with_system_cxx_lib=macosx10.9 && !no-exceptions
17 
18 // <variant>
19 
20 // template <size_t I, class... Types>
21 //   constexpr variant_alternative_t<I, variant<Types...>>&
22 //   get(variant<Types...>& v);
23 // template <size_t I, class... Types>
24 //   constexpr variant_alternative_t<I, variant<Types...>>&&
25 //   get(variant<Types...>&& v);
26 // template <size_t I, class... Types>
27 //   constexpr variant_alternative_t<I, variant<Types...>> const& get(const
28 //   variant<Types...>& v);
29 // template <size_t I, class... Types>
30 //  constexpr variant_alternative_t<I, variant<Types...>> const&& get(const
31 //  variant<Types...>&& v);
32 
33 #include "test_macros.h"
34 #include "test_workarounds.h"
35 #include "variant_test_helpers.h"
36 #include <cassert>
37 #include <type_traits>
38 #include <utility>
39 #include <variant>
40 
test_const_lvalue_get()41 void test_const_lvalue_get() {
42   {
43     using V = std::variant<int, const long>;
44     constexpr V v(42);
45 #ifdef TEST_WORKAROUND_CONSTEXPR_IMPLIES_NOEXCEPT
46     ASSERT_NOEXCEPT(std::get<0>(v));
47 #else
48     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
49 #endif
50     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
51     static_assert(std::get<0>(v) == 42, "");
52   }
53   {
54     using V = std::variant<int, const long>;
55     const V v(42);
56     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
57     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
58     assert(std::get<0>(v) == 42);
59   }
60   {
61     using V = std::variant<int, const long>;
62     constexpr V v(42l);
63 #ifdef TEST_WORKAROUND_CONSTEXPR_IMPLIES_NOEXCEPT
64     ASSERT_NOEXCEPT(std::get<1>(v));
65 #else
66     ASSERT_NOT_NOEXCEPT(std::get<1>(v));
67 #endif
68     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
69     static_assert(std::get<1>(v) == 42, "");
70   }
71   {
72     using V = std::variant<int, const long>;
73     const V v(42l);
74     ASSERT_NOT_NOEXCEPT(std::get<1>(v));
75     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
76     assert(std::get<1>(v) == 42);
77   }
78 // FIXME: Remove these once reference support is reinstated
79 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
80   {
81     using V = std::variant<int &>;
82     int x = 42;
83     const V v(x);
84     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
85     assert(&std::get<0>(v) == &x);
86   }
87   {
88     using V = std::variant<int &&>;
89     int x = 42;
90     const V v(std::move(x));
91     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
92     assert(&std::get<0>(v) == &x);
93   }
94   {
95     using V = std::variant<const int &&>;
96     int x = 42;
97     const V v(std::move(x));
98     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
99     assert(&std::get<0>(v) == &x);
100   }
101 #endif
102 }
103 
test_lvalue_get()104 void test_lvalue_get() {
105   {
106     using V = std::variant<int, const long>;
107     V v(42);
108     ASSERT_NOT_NOEXCEPT(std::get<0>(v));
109     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
110     assert(std::get<0>(v) == 42);
111   }
112   {
113     using V = std::variant<int, const long>;
114     V v(42l);
115     ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
116     assert(std::get<1>(v) == 42);
117   }
118 // FIXME: Remove these once reference support is reinstated
119 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
120   {
121     using V = std::variant<int &>;
122     int x = 42;
123     V v(x);
124     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
125     assert(&std::get<0>(v) == &x);
126   }
127   {
128     using V = std::variant<const int &>;
129     int x = 42;
130     V v(x);
131     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
132     assert(&std::get<0>(v) == &x);
133   }
134   {
135     using V = std::variant<int &&>;
136     int x = 42;
137     V v(std::move(x));
138     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
139     assert(&std::get<0>(v) == &x);
140   }
141   {
142     using V = std::variant<const int &&>;
143     int x = 42;
144     V v(std::move(x));
145     ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
146     assert(&std::get<0>(v) == &x);
147   }
148 #endif
149 }
150 
test_rvalue_get()151 void test_rvalue_get() {
152   {
153     using V = std::variant<int, const long>;
154     V v(42);
155     ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
156     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
157     assert(std::get<0>(std::move(v)) == 42);
158   }
159   {
160     using V = std::variant<int, const long>;
161     V v(42l);
162     ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
163     assert(std::get<1>(std::move(v)) == 42);
164   }
165 // FIXME: Remove these once reference support is reinstated
166 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
167   {
168     using V = std::variant<int &>;
169     int x = 42;
170     V v(x);
171     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &);
172     assert(&std::get<0>(std::move(v)) == &x);
173   }
174   {
175     using V = std::variant<const int &>;
176     int x = 42;
177     V v(x);
178     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &);
179     assert(&std::get<0>(std::move(v)) == &x);
180   }
181   {
182     using V = std::variant<int &&>;
183     int x = 42;
184     V v(std::move(x));
185     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
186     int &&xref = std::get<0>(std::move(v));
187     assert(&xref == &x);
188   }
189   {
190     using V = std::variant<const int &&>;
191     int x = 42;
192     V v(std::move(x));
193     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
194     const int &&xref = std::get<0>(std::move(v));
195     assert(&xref == &x);
196   }
197 #endif
198 }
199 
test_const_rvalue_get()200 void test_const_rvalue_get() {
201   {
202     using V = std::variant<int, const long>;
203     const V v(42);
204     ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
205     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
206     assert(std::get<0>(std::move(v)) == 42);
207   }
208   {
209     using V = std::variant<int, const long>;
210     const V v(42l);
211     ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
212     assert(std::get<1>(std::move(v)) == 42);
213   }
214 // FIXME: Remove these once reference support is reinstated
215 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
216   {
217     using V = std::variant<int &>;
218     int x = 42;
219     const V v(x);
220     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &);
221     assert(&std::get<0>(std::move(v)) == &x);
222   }
223   {
224     using V = std::variant<const int &>;
225     int x = 42;
226     const V v(x);
227     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &);
228     assert(&std::get<0>(std::move(v)) == &x);
229   }
230   {
231     using V = std::variant<int &&>;
232     int x = 42;
233     const V v(std::move(x));
234     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
235     int &&xref = std::get<0>(std::move(v));
236     assert(&xref == &x);
237   }
238   {
239     using V = std::variant<const int &&>;
240     int x = 42;
241     const V v(std::move(x));
242     ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
243     const int &&xref = std::get<0>(std::move(v));
244     assert(&xref == &x);
245   }
246 #endif
247 }
248 
249 template <std::size_t I> using Idx = std::integral_constant<size_t, I>;
250 
test_throws_for_all_value_categories()251 void test_throws_for_all_value_categories() {
252 #ifndef TEST_HAS_NO_EXCEPTIONS
253   using V = std::variant<int, long>;
254   V v0(42);
255   const V &cv0 = v0;
256   assert(v0.index() == 0);
257   V v1(42l);
258   const V &cv1 = v1;
259   assert(v1.index() == 1);
260   std::integral_constant<size_t, 0> zero;
261   std::integral_constant<size_t, 1> one;
262   auto test = [](auto idx, auto &&v) {
263     using Idx = decltype(idx);
264     try {
265       TEST_IGNORE_NODISCARD std::get<Idx::value>(std::forward<decltype(v)>(v));
266     } catch (const std::bad_variant_access &) {
267       return true;
268     } catch (...) { /* ... */
269     }
270     return false;
271   };
272   { // lvalue test cases
273     assert(test(one, v0));
274     assert(test(zero, v1));
275   }
276   { // const lvalue test cases
277     assert(test(one, cv0));
278     assert(test(zero, cv1));
279   }
280   { // rvalue test cases
281     assert(test(one, std::move(v0)));
282     assert(test(zero, std::move(v1)));
283   }
284   { // const rvalue test cases
285     assert(test(one, std::move(cv0)));
286     assert(test(zero, std::move(cv1)));
287   }
288 #endif
289 }
290 
main(int,char **)291 int main(int, char**) {
292   test_const_lvalue_get();
293   test_lvalue_get();
294   test_rvalue_get();
295   test_const_rvalue_get();
296   test_throws_for_all_value_categories();
297 
298   return 0;
299 }
300