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