[RISCV] Fix mgather -> riscv.masked.strided.load combine not extending indices (...
[llvm-project.git] / libcxx / test / std / utilities / function.objects / func.not_fn / not_fn.pass.cpp
blob1bf833b151dd30b233f9b47e5694d4a0f51c7948
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 // template <class F> unspecified not_fn(F&& f);
13 #include <functional>
14 #include <type_traits>
15 #include <string>
16 #include <cassert>
18 #include "test_macros.h"
19 #include "type_id.h"
20 #include "callable_types.h"
22 ///////////////////////////////////////////////////////////////////////////////
23 // BOOL TEST TYPES
24 ///////////////////////////////////////////////////////////////////////////////
26 struct EvilBool {
27 static int bang_called;
29 EvilBool(EvilBool const&) = default;
30 EvilBool(EvilBool&&) = default;
32 friend EvilBool operator!(EvilBool const& other) {
33 ++bang_called;
34 return EvilBool{!other.value};
37 private:
38 friend struct MoveOnlyCallable<EvilBool>;
39 friend struct CopyCallable<EvilBool>;
40 friend struct NoExceptCallable<EvilBool>;
42 constexpr explicit EvilBool(bool x) : value(x) {}
43 EvilBool& operator=(EvilBool const& other) = default;
45 public:
46 bool value;
49 int EvilBool::bang_called = 0;
51 struct ExplicitBool {
52 ExplicitBool(ExplicitBool const&) = default;
53 ExplicitBool(ExplicitBool&&) = default;
55 constexpr explicit operator bool() const { return value; }
57 private:
58 friend struct MoveOnlyCallable<ExplicitBool>;
59 friend struct CopyCallable<ExplicitBool>;
61 constexpr explicit ExplicitBool(bool x) : value(x) {}
62 constexpr ExplicitBool& operator=(bool x) {
63 value = x;
64 return *this;
67 bool value;
71 struct NoExceptEvilBool {
72 NoExceptEvilBool(NoExceptEvilBool const&) = default;
73 NoExceptEvilBool(NoExceptEvilBool&&) = default;
74 NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
76 constexpr explicit NoExceptEvilBool(bool x) : value(x) {}
78 friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
79 return NoExceptEvilBool{!other.value};
82 bool value;
87 TEST_CONSTEXPR_CXX20
88 bool constructor_tests()
91 using T = MoveOnlyCallable<bool>;
92 T value(true);
93 using RetT = decltype(std::not_fn(std::move(value)));
94 static_assert(std::is_move_constructible<RetT>::value, "");
95 static_assert(!std::is_copy_constructible<RetT>::value, "");
96 static_assert(!std::is_move_assignable<RetT>::value, "");
97 static_assert(!std::is_copy_assignable<RetT>::value, "");
98 auto ret = std::not_fn(std::move(value));
99 // test it was moved from
100 assert(value.value == false);
101 // test that ret() negates the original value 'true'
102 assert(ret() == false);
103 assert(ret(0, 0.0, "blah") == false);
104 // Move ret and test that it was moved from and that ret2 got the
105 // original value.
106 auto ret2 = std::move(ret);
107 assert(ret() == true);
108 assert(ret2() == false);
109 assert(ret2(42) == false);
112 using T = CopyCallable<bool>;
113 T value(false);
114 using RetT = decltype(std::not_fn(value));
115 static_assert(std::is_move_constructible<RetT>::value, "");
116 static_assert(std::is_copy_constructible<RetT>::value, "");
117 static_assert(!std::is_move_assignable<RetT>::value, "");
118 static_assert(!std::is_copy_assignable<RetT>::value, "");
119 auto ret = std::not_fn(value);
120 // test that value is unchanged (copied not moved)
121 assert(value.value == false);
122 // test 'ret' has the original value
123 assert(ret() == true);
124 assert(ret(42, 100) == true);
125 // move from 'ret' and check that 'ret2' has the original value.
126 auto ret2 = std::move(ret);
127 assert(ret() == false);
128 assert(ret2() == true);
129 assert(ret2("abc") == true);
130 // initialize not_fn with rvalue
131 auto ret3 = std::not_fn(std::move(value));
132 assert(ret(0) == false);
133 assert(ret3(0) == true);
136 using T = CopyAssignableWrapper;
137 T value(true);
138 T value2(false);
139 using RetT = decltype(std::not_fn(value));
140 static_assert(std::is_move_constructible<RetT>::value, "");
141 static_assert(std::is_copy_constructible<RetT>::value, "");
142 auto ret = std::not_fn(value);
143 assert(ret() == false);
144 auto ret2 = std::not_fn(value2);
145 assert(ret2() == true);
148 using T = MoveAssignableWrapper;
149 T value(true);
150 T value2(false);
151 using RetT = decltype(std::not_fn(std::move(value)));
152 static_assert(std::is_move_constructible<RetT>::value, "");
153 static_assert(!std::is_copy_constructible<RetT>::value, "");
154 static_assert(!std::is_copy_assignable<RetT>::value, "");
155 auto ret = std::not_fn(std::move(value));
156 assert(ret() == false);
157 auto ret2 = std::not_fn(std::move(value2));
158 assert(ret2() == true);
160 return true;
163 void return_type_tests()
165 using std::is_same;
167 using T = CopyCallable<bool>;
168 auto ret = std::not_fn(T{false});
169 static_assert(is_same<decltype(ret()), bool>::value, "");
170 static_assert(is_same<decltype(ret("abc")), bool>::value, "");
171 assert(ret() == true);
174 using T = CopyCallable<ExplicitBool>;
175 auto ret = std::not_fn(T{true});
176 static_assert(is_same<decltype(ret()), bool>::value, "");
177 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
178 assert(ret() == false);
181 using T = CopyCallable<EvilBool>;
182 auto ret = std::not_fn(T{false});
183 static_assert(is_same<decltype(ret()), EvilBool>::value, "");
184 EvilBool::bang_called = 0;
185 auto value_ret = ret();
186 assert(EvilBool::bang_called == 1);
187 assert(value_ret.value == true);
188 ret();
189 assert(EvilBool::bang_called == 2);
193 // Other tests only test using objects with call operators. Test various
194 // other callable types here.
195 TEST_CONSTEXPR_CXX20
196 bool other_callable_types_test()
198 { // test with function pointer
199 auto ret = std::not_fn(returns_true);
200 assert(ret() == false);
202 { // test with lambda
203 auto returns_value = [](bool value) { return value; };
204 auto ret = std::not_fn(returns_value);
205 assert(ret(true) == false);
206 assert(ret(false) == true);
208 { // test with pointer to member function
209 MemFunCallable mt(true);
210 const MemFunCallable mf(false);
211 auto ret = std::not_fn(&MemFunCallable::return_value);
212 assert(ret(mt) == false);
213 assert(ret(mf) == true);
214 assert(ret(&mt) == false);
215 assert(ret(&mf) == true);
217 { // test with pointer to member function
218 MemFunCallable mt(true);
219 MemFunCallable mf(false);
220 auto ret = std::not_fn(&MemFunCallable::return_value_nc);
221 assert(ret(mt) == false);
222 assert(ret(mf) == true);
223 assert(ret(&mt) == false);
224 assert(ret(&mf) == true);
226 { // test with pointer to member data
227 MemFunCallable mt(true);
228 const MemFunCallable mf(false);
229 auto ret = std::not_fn(&MemFunCallable::value);
230 assert(ret(mt) == false);
231 assert(ret(mf) == true);
232 assert(ret(&mt) == false);
233 assert(ret(&mf) == true);
235 return true;
238 void throws_in_constructor_test()
240 #ifndef TEST_HAS_NO_EXCEPTIONS
241 struct ThrowsOnCopy {
242 ThrowsOnCopy(ThrowsOnCopy const&) {
243 throw 42;
245 ThrowsOnCopy() = default;
246 bool operator()() const {
247 assert(false);
248 #ifdef TEST_COMPILER_MSVC
249 __assume(0);
250 #else
251 __builtin_unreachable();
252 #endif
256 ThrowsOnCopy cp;
257 try {
258 (void)std::not_fn(cp);
259 assert(false);
260 } catch (int const& value) {
261 assert(value == 42);
264 #endif
267 TEST_CONSTEXPR_CXX20
268 bool call_operator_sfinae_test() {
269 { // wrong number of arguments
270 using T = decltype(std::not_fn(returns_true));
271 static_assert(std::is_invocable<T>::value, ""); // callable only with no args
272 static_assert(!std::is_invocable<T, bool>::value, "");
274 { // violates const correctness (member function pointer)
275 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
276 static_assert(std::is_invocable<T, MemFunCallable&>::value, "");
277 static_assert(!std::is_invocable<T, const MemFunCallable&>::value, "");
279 { // violates const correctness (call object)
280 using Obj = CopyCallable<bool>;
281 using NCT = decltype(std::not_fn(Obj{true}));
282 using CT = const NCT;
283 static_assert(std::is_invocable<NCT>::value, "");
284 static_assert(!std::is_invocable<CT>::value, "");
286 { // returns bad type with no operator!
287 auto fn = [](auto x) { return x; };
288 using T = decltype(std::not_fn(fn));
289 static_assert(std::is_invocable<T, bool>::value, "");
290 static_assert(!std::is_invocable<T, std::string>::value, "");
292 return true;
295 TEST_CONSTEXPR_CXX20
296 bool call_operator_forwarding_test()
298 using Fn = ForwardingCallObject;
299 Fn::State st;
300 auto obj = std::not_fn(Fn{st});
301 const auto& c_obj = obj;
302 { // test zero args
303 obj();
304 assert(st.check_call<>(CT_NonConst | CT_LValue));
305 std::move(obj)();
306 assert(st.check_call<>(CT_NonConst | CT_RValue));
307 c_obj();
308 assert(st.check_call<>(CT_Const | CT_LValue));
309 std::move(c_obj)();
310 assert(st.check_call<>(CT_Const | CT_RValue));
312 { // test value categories
313 int x = 42;
314 const int cx = 42;
315 obj(x);
316 assert(st.check_call<int&>(CT_NonConst | CT_LValue));
317 obj(cx);
318 assert(st.check_call<const int&>(CT_NonConst | CT_LValue));
319 obj(std::move(x));
320 assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
321 obj(std::move(cx));
322 assert(st.check_call<const int&&>(CT_NonConst | CT_LValue));
323 obj(42);
324 assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
326 { // test value categories - rvalue
327 int x = 42;
328 const int cx = 42;
329 std::move(obj)(x);
330 assert(st.check_call<int&>(CT_NonConst | CT_RValue));
331 std::move(obj)(cx);
332 assert(st.check_call<const int&>(CT_NonConst | CT_RValue));
333 std::move(obj)(std::move(x));
334 assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
335 std::move(obj)(std::move(cx));
336 assert(st.check_call<const int&&>(CT_NonConst | CT_RValue));
337 std::move(obj)(42);
338 assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
340 { // test value categories - const call
341 int x = 42;
342 const int cx = 42;
343 c_obj(x);
344 assert(st.check_call<int&>(CT_Const | CT_LValue));
345 c_obj(cx);
346 assert(st.check_call<const int&>(CT_Const | CT_LValue));
347 c_obj(std::move(x));
348 assert(st.check_call<int&&>(CT_Const | CT_LValue));
349 c_obj(std::move(cx));
350 assert(st.check_call<const int&&>(CT_Const | CT_LValue));
351 c_obj(42);
352 assert(st.check_call<int&&>(CT_Const | CT_LValue));
354 { // test value categories - const call rvalue
355 int x = 42;
356 const int cx = 42;
357 std::move(c_obj)(x);
358 assert(st.check_call<int&>(CT_Const | CT_RValue));
359 std::move(c_obj)(cx);
360 assert(st.check_call<const int&>(CT_Const | CT_RValue));
361 std::move(c_obj)(std::move(x));
362 assert(st.check_call<int&&>(CT_Const | CT_RValue));
363 std::move(c_obj)(std::move(cx));
364 assert(st.check_call<const int&&>(CT_Const | CT_RValue));
365 std::move(c_obj)(42);
366 assert(st.check_call<int&&>(CT_Const | CT_RValue));
368 { // test multi arg
369 using String = const char *;
370 const double y = 3.14;
371 String s = "abc";
372 obj(42, std::move(y), s, String{"foo"});
373 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue)));
374 std::move(obj)(42, std::move(y), s, String{"foo"});
375 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue)));
376 c_obj(42, std::move(y), s, String{"foo"});
377 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_LValue)));
378 std::move(c_obj)(42, std::move(y), s, String{"foo"});
379 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_RValue)));
381 return true;
384 TEST_CONSTEXPR_CXX20
385 bool call_operator_noexcept_test()
388 using T = ConstCallable<bool>;
389 T value(true);
390 auto ret = std::not_fn(value);
391 static_assert(!noexcept(ret()), "call should not be noexcept");
392 auto const& cret = ret;
393 static_assert(!noexcept(cret()), "call should not be noexcept");
396 using T = NoExceptCallable<bool>;
397 T value(true);
398 auto ret = std::not_fn(value);
399 LIBCPP_STATIC_ASSERT(noexcept(!std::__invoke(value)), "");
400 #if TEST_STD_VER > 14
401 static_assert(noexcept(!std::invoke(value)), "");
402 #endif
403 static_assert(noexcept(ret()), "call should be noexcept");
404 auto const& cret = ret;
405 static_assert(noexcept(cret()), "call should be noexcept");
408 using T = NoExceptCallable<NoExceptEvilBool>;
409 T value(true);
410 auto ret = std::not_fn(value);
411 static_assert(noexcept(ret()), "call should not be noexcept");
412 auto const& cret = ret;
413 static_assert(noexcept(cret()), "call should not be noexcept");
416 using T = NoExceptCallable<EvilBool>;
417 T value(true);
418 auto ret = std::not_fn(value);
419 static_assert(!noexcept(ret()), "call should not be noexcept");
420 auto const& cret = ret;
421 static_assert(!noexcept(cret()), "call should not be noexcept");
423 return true;
426 TEST_CONSTEXPR_CXX20
427 bool test_lwg2767() {
428 // See https://cplusplus.github.io/LWG/lwg-defects.html#2767
429 struct Abstract { virtual void f() const = 0; };
430 struct Derived : public Abstract { void f() const {} };
431 struct F { constexpr bool operator()(Abstract&&) { return false; } };
433 Derived d;
434 Abstract &a = d;
435 bool b = std::not_fn(F{})(std::move(a));
436 assert(b);
438 return true;
441 int main(int, char**)
443 constructor_tests();
444 return_type_tests();
445 other_callable_types_test();
446 throws_in_constructor_test();
447 call_operator_sfinae_test(); // somewhat of an extension
448 call_operator_forwarding_test();
449 call_operator_noexcept_test();
450 test_lwg2767();
452 #if TEST_STD_VER >= 20
453 static_assert(constructor_tests());
454 static_assert(other_callable_types_test());
455 static_assert(call_operator_sfinae_test()); // somewhat of an extension
456 static_assert(call_operator_forwarding_test());
457 static_assert(call_operator_noexcept_test());
458 static_assert(test_lwg2767());
459 #endif
461 return 0;