AMDGPU: Make vector_shuffle legal for v2i32 with v_pk_mov_b32 (#123684)
[llvm-project.git] / libcxx / test / std / utilities / variant / variant.visit.member / visit.pass.cpp
blob0da23fd58ccaa7093fb68f2c080c043e9c2ba12f
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, c++17, c++20, c++23
10 // The tested functionality needs deducing this.
11 // UNSUPPORTED: clang-17
12 // XFAIL: apple-clang
14 // <variant>
16 // class variant;
18 // template<class Self, class Visitor>
19 // constexpr decltype(auto) visit(this Self&&, Visitor&&); // since C++26
21 #include <cassert>
22 #include <memory>
23 #include <string>
24 #include <tuple>
25 #include <type_traits>
26 #include <utility>
27 #include <variant>
29 #include "test_macros.h"
30 #include "variant_test_helpers.h"
32 void test_call_operator_forwarding() {
33 using Fn = ForwardingCallObject;
34 Fn obj{};
35 const Fn& cobj = obj;
37 { // test call operator forwarding - single variant, single arg
38 using V = std::variant<int>;
39 V v(42);
41 v.visit(obj);
42 assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
43 v.visit(cobj);
44 assert(Fn::check_call<int&>(CT_Const | CT_LValue));
45 v.visit(std::move(obj));
46 assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
47 v.visit(std::move(cobj));
48 assert(Fn::check_call<int&>(CT_Const | CT_RValue));
50 { // test call operator forwarding - single variant, multi arg
51 using V = std::variant<int, long, double>;
52 V v(42L);
54 v.visit(obj);
55 assert(Fn::check_call<long&>(CT_NonConst | CT_LValue));
56 v.visit(cobj);
57 assert(Fn::check_call<long&>(CT_Const | CT_LValue));
58 v.visit(std::move(obj));
59 assert(Fn::check_call<long&>(CT_NonConst | CT_RValue));
60 v.visit(std::move(cobj));
61 assert(Fn::check_call<long&>(CT_Const | CT_RValue));
65 // Applies to non-member `std::visit` only.
66 void test_argument_forwarding() {
67 using Fn = ForwardingCallObject;
68 Fn obj{};
69 const auto val = CT_LValue | CT_NonConst;
71 { // single argument - value type
72 using V = std::variant<int>;
73 V v(42);
74 const V& cv = v;
76 v.visit(obj);
77 assert(Fn::check_call<int&>(val));
78 cv.visit(obj);
79 assert(Fn::check_call<const int&>(val));
80 std::move(v).visit(obj);
81 assert(Fn::check_call<int&&>(val));
82 std::move(cv).visit(obj);
83 assert(Fn::check_call<const int&&>(val));
87 void test_return_type() {
88 using Fn = ForwardingCallObject;
89 Fn obj{};
90 const Fn& cobj = obj;
92 { // test call operator forwarding - single variant, single arg
93 using V = std::variant<int>;
94 V v(42);
96 static_assert(std::is_same_v<decltype(v.visit(obj)), Fn&>);
97 static_assert(std::is_same_v<decltype(v.visit(cobj)), const Fn&>);
98 static_assert(std::is_same_v<decltype(v.visit(std::move(obj))), Fn&&>);
99 static_assert(std::is_same_v<decltype(v.visit(std::move(cobj))), const Fn&&>);
101 { // test call operator forwarding - single variant, multi arg
102 using V = std::variant<int, long, double>;
103 V v(42L);
105 static_assert(std::is_same_v<decltype(v.visit(obj)), Fn&>);
106 static_assert(std::is_same_v<decltype(v.visit(cobj)), const Fn&>);
107 static_assert(std::is_same_v<decltype(v.visit(std::move(obj))), Fn&&>);
108 static_assert(std::is_same_v<decltype(v.visit(std::move(cobj))), const Fn&&>);
112 void test_constexpr() {
113 constexpr ReturnFirst obj{};
116 using V = std::variant<int>;
117 constexpr V v(42);
119 static_assert(v.visit(obj) == 42);
122 using V = std::variant<short, long, char>;
123 constexpr V v(42L);
125 static_assert(v.visit(obj) == 42);
129 void test_exceptions() {
130 #ifndef TEST_HAS_NO_EXCEPTIONS
131 ReturnArity obj{};
133 auto test = [&](auto&& v) {
134 try {
135 v.visit(obj);
136 } catch (const std::bad_variant_access&) {
137 return true;
138 } catch (...) {
140 return false;
144 using V = std::variant<int, MakeEmptyT>;
145 V v;
146 makeEmpty(v);
148 assert(test(v));
150 #endif
153 // See https://llvm.org/PR31916
154 void test_caller_accepts_nonconst() {
155 struct A {};
156 struct Visitor {
157 void operator()(A&) {}
159 std::variant<A> v;
161 v.visit(Visitor{});
164 struct MyVariant : std::variant<short, long, float> {};
166 // FIXME: This is UB according to [namespace.std]
167 namespace std {
168 template <std::size_t Index>
169 void get(const MyVariant&) {
170 assert(false);
172 } // namespace std
174 void test_derived_from_variant() {
175 auto v1 = MyVariant{42};
176 const auto cv1 = MyVariant{142};
178 v1.visit([](auto x) { assert(x == 42); });
179 cv1.visit([](auto x) { assert(x == 142); });
180 MyVariant{-1.25f}.visit([](auto x) { assert(x == -1.25f); });
181 std::move(v1).visit([](auto x) { assert(x == 42); });
182 std::move(cv1).visit([](auto x) { assert(x == 142); });
184 // Check that visit does not take index nor valueless_by_exception members from the base class.
185 struct EvilVariantBase {
186 int index;
187 char valueless_by_exception;
190 struct EvilVariant1 : std::variant<int, long, double>, std::tuple<int>, EvilVariantBase {
191 using std::variant<int, long, double>::variant;
194 EvilVariant1{12}.visit([](auto x) { assert(x == 12); });
195 EvilVariant1{12.3}.visit([](auto x) { assert(x == 12.3); });
197 // Check that visit unambiguously picks the variant, even if the other base has __impl member.
198 struct ImplVariantBase {
199 struct Callable {
200 bool operator()() const {
201 assert(false);
202 return false;
206 Callable __impl;
209 struct EvilVariant2 : std::variant<int, long, double>, ImplVariantBase {
210 using std::variant<int, long, double>::variant;
213 EvilVariant2{12}.visit([](auto x) { assert(x == 12); });
214 EvilVariant2{12.3}.visit([](auto x) { assert(x == 12.3); });
217 int main(int, char**) {
218 test_call_operator_forwarding();
219 test_argument_forwarding();
220 test_return_type();
221 test_constexpr();
222 test_exceptions();
223 test_caller_accepts_nonconst();
224 test_derived_from_variant();
226 return 0;