[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / libcxx / test / std / utilities / variant / variant.visit / visit.pass.cpp
blob097b784f2bf2ceb86a12b8613dac47aae281e24a
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
11 // <variant>
12 // template <class Visitor, class... Variants>
13 // constexpr see below visit(Visitor&& vis, Variants&&... vars);
15 #include <cassert>
16 #include <memory>
17 #include <string>
18 #include <type_traits>
19 #include <utility>
20 #include <variant>
22 #include "test_macros.h"
23 #include "variant_test_helpers.h"
25 void test_call_operator_forwarding() {
26 using Fn = ForwardingCallObject;
27 Fn obj{};
28 const Fn &cobj = obj;
29 { // test call operator forwarding - no variant
30 std::visit(obj);
31 assert(Fn::check_call<>(CT_NonConst | CT_LValue));
32 std::visit(cobj);
33 assert(Fn::check_call<>(CT_Const | CT_LValue));
34 std::visit(std::move(obj));
35 assert(Fn::check_call<>(CT_NonConst | CT_RValue));
36 std::visit(std::move(cobj));
37 assert(Fn::check_call<>(CT_Const | CT_RValue));
39 { // test call operator forwarding - single variant, single arg
40 using V = std::variant<int>;
41 V v(42);
42 std::visit(obj, v);
43 assert(Fn::check_call<int &>(CT_NonConst | CT_LValue));
44 std::visit(cobj, v);
45 assert(Fn::check_call<int &>(CT_Const | CT_LValue));
46 std::visit(std::move(obj), v);
47 assert(Fn::check_call<int &>(CT_NonConst | CT_RValue));
48 std::visit(std::move(cobj), v);
49 assert(Fn::check_call<int &>(CT_Const | CT_RValue));
51 { // test call operator forwarding - single variant, multi arg
52 using V = std::variant<int, long, double>;
53 V v(42l);
54 std::visit(obj, v);
55 assert(Fn::check_call<long &>(CT_NonConst | CT_LValue));
56 std::visit(cobj, v);
57 assert(Fn::check_call<long &>(CT_Const | CT_LValue));
58 std::visit(std::move(obj), v);
59 assert(Fn::check_call<long &>(CT_NonConst | CT_RValue));
60 std::visit(std::move(cobj), v);
61 assert(Fn::check_call<long &>(CT_Const | CT_RValue));
63 { // test call operator forwarding - multi variant, multi arg
64 using V = std::variant<int, long, double>;
65 using V2 = std::variant<int *, std::string>;
66 V v(42l);
67 V2 v2("hello");
68 std::visit(obj, v, v2);
69 assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_LValue)));
70 std::visit(cobj, v, v2);
71 assert((Fn::check_call<long &, std::string &>(CT_Const | CT_LValue)));
72 std::visit(std::move(obj), v, v2);
73 assert((Fn::check_call<long &, std::string &>(CT_NonConst | CT_RValue)));
74 std::visit(std::move(cobj), v, v2);
75 assert((Fn::check_call<long &, std::string &>(CT_Const | CT_RValue)));
78 using V = std::variant<int, long, double, std::string>;
79 V v1(42l), v2("hello"), v3(101), v4(1.1);
80 std::visit(obj, v1, v2, v3, v4);
81 assert((Fn::check_call<long &, std::string &, int &, double &>(CT_NonConst | CT_LValue)));
82 std::visit(cobj, v1, v2, v3, v4);
83 assert((Fn::check_call<long &, std::string &, int &, double &>(CT_Const | CT_LValue)));
84 std::visit(std::move(obj), v1, v2, v3, v4);
85 assert((Fn::check_call<long &, std::string &, int &, double &>(CT_NonConst | CT_RValue)));
86 std::visit(std::move(cobj), v1, v2, v3, v4);
87 assert((Fn::check_call<long &, std::string &, int &, double &>(CT_Const | CT_RValue)));
90 using V = std::variant<int, long, double, int*, std::string>;
91 V v1(42l), v2("hello"), v3(nullptr), v4(1.1);
92 std::visit(obj, v1, v2, v3, v4);
93 assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_NonConst | CT_LValue)));
94 std::visit(cobj, v1, v2, v3, v4);
95 assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_Const | CT_LValue)));
96 std::visit(std::move(obj), v1, v2, v3, v4);
97 assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_NonConst | CT_RValue)));
98 std::visit(std::move(cobj), v1, v2, v3, v4);
99 assert((Fn::check_call<long &, std::string &, int *&, double &>(CT_Const | CT_RValue)));
103 void test_argument_forwarding() {
104 using Fn = ForwardingCallObject;
105 Fn obj{};
106 const auto Val = CT_LValue | CT_NonConst;
107 { // single argument - value type
108 using V = std::variant<int>;
109 V v(42);
110 const V &cv = v;
111 std::visit(obj, v);
112 assert(Fn::check_call<int &>(Val));
113 std::visit(obj, cv);
114 assert(Fn::check_call<const int &>(Val));
115 std::visit(obj, std::move(v));
116 assert(Fn::check_call<int &&>(Val));
117 std::visit(obj, std::move(cv));
118 assert(Fn::check_call<const int &&>(Val));
120 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
121 { // single argument - lvalue reference
122 using V = std::variant<int &>;
123 int x = 42;
124 V v(x);
125 const V &cv = v;
126 std::visit(obj, v);
127 assert(Fn::check_call<int &>(Val));
128 std::visit(obj, cv);
129 assert(Fn::check_call<int &>(Val));
130 std::visit(obj, std::move(v));
131 assert(Fn::check_call<int &>(Val));
132 std::visit(obj, std::move(cv));
133 assert(Fn::check_call<int &>(Val));
135 { // single argument - rvalue reference
136 using V = std::variant<int &&>;
137 int x = 42;
138 V v(std::move(x));
139 const V &cv = v;
140 std::visit(obj, v);
141 assert(Fn::check_call<int &>(Val));
142 std::visit(obj, cv);
143 assert(Fn::check_call<int &>(Val));
144 std::visit(obj, std::move(v));
145 assert(Fn::check_call<int &&>(Val));
146 std::visit(obj, std::move(cv));
147 assert(Fn::check_call<int &&>(Val));
149 #endif
150 { // multi argument - multi variant
151 using V = std::variant<int, std::string, long>;
152 V v1(42), v2("hello"), v3(43l);
153 std::visit(obj, v1, v2, v3);
154 assert((Fn::check_call<int &, std::string &, long &>(Val)));
155 std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3));
156 assert((Fn::check_call<const int &, const std::string &, long &&>(Val)));
159 using V = std::variant<int, long, double, std::string>;
160 V v1(42l), v2("hello"), v3(101), v4(1.1);
161 std::visit(obj, v1, v2, v3, v4);
162 assert((Fn::check_call<long &, std::string &, int &, double &>(Val)));
163 std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3), std::move(v4));
164 assert((Fn::check_call<const long &, const std::string &, int &&, double &&>(Val)));
167 using V = std::variant<int, long, double, int*, std::string>;
168 V v1(42l), v2("hello"), v3(nullptr), v4(1.1);
169 std::visit(obj, v1, v2, v3, v4);
170 assert((Fn::check_call<long &, std::string &, int *&, double &>(Val)));
171 std::visit(obj, std::as_const(v1), std::as_const(v2), std::move(v3), std::move(v4));
172 assert((Fn::check_call<const long &, const std::string &, int *&&, double &&>(Val)));
176 void test_return_type() {
177 using Fn = ForwardingCallObject;
178 Fn obj{};
179 const Fn &cobj = obj;
180 { // test call operator forwarding - no variant
181 static_assert(std::is_same_v<decltype(std::visit(obj)), Fn&>);
182 static_assert(std::is_same_v<decltype(std::visit(cobj)), const Fn&>);
183 static_assert(std::is_same_v<decltype(std::visit(std::move(obj))), Fn&&>);
184 static_assert(std::is_same_v<decltype(std::visit(std::move(cobj))), const Fn&&>);
186 { // test call operator forwarding - single variant, single arg
187 using V = std::variant<int>;
188 V v(42);
189 static_assert(std::is_same_v<decltype(std::visit(obj, v)), Fn&>);
190 static_assert(std::is_same_v<decltype(std::visit(cobj, v)), const Fn&>);
191 static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v)), Fn&&>);
192 static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v)), const Fn&&>);
194 { // test call operator forwarding - single variant, multi arg
195 using V = std::variant<int, long, double>;
196 V v(42l);
197 static_assert(std::is_same_v<decltype(std::visit(obj, v)), Fn&>);
198 static_assert(std::is_same_v<decltype(std::visit(cobj, v)), const Fn&>);
199 static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v)), Fn&&>);
200 static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v)), const Fn&&>);
202 { // test call operator forwarding - multi variant, multi arg
203 using V = std::variant<int, long, double>;
204 using V2 = std::variant<int *, std::string>;
205 V v(42l);
206 V2 v2("hello");
207 static_assert(std::is_same_v<decltype(std::visit(obj, v, v2)), Fn&>);
208 static_assert(std::is_same_v<decltype(std::visit(cobj, v, v2)), const Fn&>);
209 static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v, v2)), Fn&&>);
210 static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v, v2)), const Fn&&>);
213 using V = std::variant<int, long, double, std::string>;
214 V v1(42l), v2("hello"), v3(101), v4(1.1);
215 static_assert(std::is_same_v<decltype(std::visit(obj, v1, v2, v3, v4)), Fn&>);
216 static_assert(std::is_same_v<decltype(std::visit(cobj, v1, v2, v3, v4)), const Fn&>);
217 static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v1, v2, v3, v4)), Fn&&>);
218 static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v1, v2, v3, v4)), const Fn&&>);
221 using V = std::variant<int, long, double, int*, std::string>;
222 V v1(42l), v2("hello"), v3(nullptr), v4(1.1);
223 static_assert(std::is_same_v<decltype(std::visit(obj, v1, v2, v3, v4)), Fn&>);
224 static_assert(std::is_same_v<decltype(std::visit(cobj, v1, v2, v3, v4)), const Fn&>);
225 static_assert(std::is_same_v<decltype(std::visit(std::move(obj), v1, v2, v3, v4)), Fn&&>);
226 static_assert(std::is_same_v<decltype(std::visit(std::move(cobj), v1, v2, v3, v4)), const Fn&&>);
230 void test_constexpr() {
231 constexpr ReturnFirst obj{};
232 constexpr ReturnArity aobj{};
234 using V = std::variant<int>;
235 constexpr V v(42);
236 static_assert(std::visit(obj, v) == 42, "");
239 using V = std::variant<short, long, char>;
240 constexpr V v(42l);
241 static_assert(std::visit(obj, v) == 42, "");
244 using V1 = std::variant<int>;
245 using V2 = std::variant<int, char *, long long>;
246 using V3 = std::variant<bool, int, int>;
247 constexpr V1 v1;
248 constexpr V2 v2(nullptr);
249 constexpr V3 v3;
250 static_assert(std::visit(aobj, v1, v2, v3) == 3, "");
253 using V1 = std::variant<int>;
254 using V2 = std::variant<int, char *, long long>;
255 using V3 = std::variant<void *, int, int>;
256 constexpr V1 v1;
257 constexpr V2 v2(nullptr);
258 constexpr V3 v3;
259 static_assert(std::visit(aobj, v1, v2, v3) == 3, "");
262 using V = std::variant<int, long, double, int *>;
263 constexpr V v1(42l), v2(101), v3(nullptr), v4(1.1);
264 static_assert(std::visit(aobj, v1, v2, v3, v4) == 4, "");
267 using V = std::variant<int, long, double, long long, int *>;
268 constexpr V v1(42l), v2(101), v3(nullptr), v4(1.1);
269 static_assert(std::visit(aobj, v1, v2, v3, v4) == 4, "");
273 void test_exceptions() {
274 #ifndef TEST_HAS_NO_EXCEPTIONS
275 ReturnArity obj{};
276 auto test = [&](auto &&... args) {
277 try {
278 std::visit(obj, args...);
279 } catch (const std::bad_variant_access &) {
280 return true;
281 } catch (...) {
283 return false;
286 using V = std::variant<int, MakeEmptyT>;
287 V v;
288 makeEmpty(v);
289 assert(test(v));
292 using V = std::variant<int, MakeEmptyT>;
293 using V2 = std::variant<long, std::string, void *>;
294 V v;
295 makeEmpty(v);
296 V2 v2("hello");
297 assert(test(v, v2));
300 using V = std::variant<int, MakeEmptyT>;
301 using V2 = std::variant<long, std::string, void *>;
302 V v;
303 makeEmpty(v);
304 V2 v2("hello");
305 assert(test(v2, v));
308 using V = std::variant<int, MakeEmptyT>;
309 using V2 = std::variant<long, std::string, void *, MakeEmptyT>;
310 V v;
311 makeEmpty(v);
312 V2 v2;
313 makeEmpty(v2);
314 assert(test(v, v2));
317 using V = std::variant<int, long, double, MakeEmptyT>;
318 V v1(42l), v2(101), v3(202), v4(1.1);
319 makeEmpty(v1);
320 assert(test(v1, v2, v3, v4));
323 using V = std::variant<int, long, double, long long, MakeEmptyT>;
324 V v1(42l), v2(101), v3(202), v4(1.1);
325 makeEmpty(v1);
326 makeEmpty(v2);
327 makeEmpty(v3);
328 makeEmpty(v4);
329 assert(test(v1, v2, v3, v4));
331 #endif
334 // See https://llvm.org/PR31916
335 void test_caller_accepts_nonconst() {
336 struct A {};
337 struct Visitor {
338 void operator()(A&) {}
340 std::variant<A> v;
341 std::visit(Visitor{}, v);
344 struct MyVariant : std::variant<short, long, float> {};
346 namespace std {
347 template <std::size_t Index>
348 void get(const MyVariant&) {
349 assert(false);
351 } // namespace std
353 void test_derived_from_variant() {
354 auto v1 = MyVariant{42};
355 const auto cv1 = MyVariant{142};
356 std::visit([](auto x) { assert(x == 42); }, v1);
357 std::visit([](auto x) { assert(x == 142); }, cv1);
358 std::visit([](auto x) { assert(x == -1.25f); }, MyVariant{-1.25f});
359 std::visit([](auto x) { assert(x == 42); }, std::move(v1));
360 std::visit([](auto x) { assert(x == 142); }, std::move(cv1));
362 // Check that visit does not take index nor valueless_by_exception members from the base class.
363 struct EvilVariantBase {
364 int index;
365 char valueless_by_exception;
368 struct EvilVariant1 : std::variant<int, long, double>,
369 std::tuple<int>,
370 EvilVariantBase {
371 using std::variant<int, long, double>::variant;
374 std::visit([](auto x) { assert(x == 12); }, EvilVariant1{12});
375 std::visit([](auto x) { assert(x == 12.3); }, EvilVariant1{12.3});
377 // Check that visit unambiguously picks the variant, even if the other base has __impl member.
378 struct ImplVariantBase {
379 struct Callable {
380 bool operator()() const { assert(false); return false; }
383 Callable __impl;
386 struct EvilVariant2 : std::variant<int, long, double>, ImplVariantBase {
387 using std::variant<int, long, double>::variant;
390 std::visit([](auto x) { assert(x == 12); }, EvilVariant2{12});
391 std::visit([](auto x) { assert(x == 12.3); }, EvilVariant2{12.3});
394 struct any_visitor {
395 template <typename T>
396 void operator()(const T&) const {}
399 template <typename T, typename = decltype(std::visit(
400 std::declval<any_visitor&>(), std::declval<T>()))>
401 constexpr bool has_visit(int) {
402 return true;
405 template <typename T>
406 constexpr bool has_visit(...) {
407 return false;
410 void test_sfinae() {
411 struct BadVariant : std::variant<short>, std::variant<long, float> {};
412 struct BadVariant2 : private std::variant<long, float> {};
413 struct GoodVariant : std::variant<long, float> {};
414 struct GoodVariant2 : GoodVariant {};
416 static_assert(!has_visit<int>(0));
417 static_assert(!has_visit<BadVariant>(0));
418 static_assert(!has_visit<BadVariant2>(0));
419 static_assert(has_visit<std::variant<int>>(0));
420 static_assert(has_visit<GoodVariant>(0));
421 static_assert(has_visit<GoodVariant2>(0));
424 int main(int, char**) {
425 test_call_operator_forwarding();
426 test_argument_forwarding();
427 test_return_type();
428 test_constexpr();
429 test_exceptions();
430 test_caller_accepts_nonconst();
431 test_derived_from_variant();
432 test_sfinae();
434 return 0;