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