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 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // template <class F> unspecified not_fn(F&& f);
12 
13 #include <functional>
14 #include <type_traits>
15 #include <string>
16 #include <cassert>
17 
18 #include "test_macros.h"
19 #include "type_id.h"
20 #include "callable_types.h"
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 //                        BOOL TEST TYPES
24 ///////////////////////////////////////////////////////////////////////////////
25 
26 struct EvilBool {
27   static int bang_called;
28 
29   EvilBool(EvilBool const&) = default;
30   EvilBool(EvilBool&&) = default;
31 
operator !(EvilBool const & other)32   friend EvilBool operator!(EvilBool const& other) {
33     ++bang_called;
34     return EvilBool{!other.value};
35   }
36 
37 private:
38   friend struct MoveOnlyCallable<EvilBool>;
39   friend struct CopyCallable<EvilBool>;
40   friend struct NoExceptCallable<EvilBool>;
41 
EvilBoolEvilBool42   constexpr explicit EvilBool(bool x) : value(x) {}
43   EvilBool& operator=(EvilBool const& other) = default;
44 
45 public:
46   bool value;
47 };
48 
49 int EvilBool::bang_called = 0;
50 
51 struct ExplicitBool {
52   ExplicitBool(ExplicitBool const&) = default;
53   ExplicitBool(ExplicitBool&&) = default;
54 
operator boolExplicitBool55   constexpr explicit operator bool() const { return value; }
56 
57 private:
58   friend struct MoveOnlyCallable<ExplicitBool>;
59   friend struct CopyCallable<ExplicitBool>;
60 
ExplicitBoolExplicitBool61   constexpr explicit ExplicitBool(bool x) : value(x) {}
operator =ExplicitBool62   constexpr ExplicitBool& operator=(bool x) {
63       value = x;
64       return *this;
65   }
66 
67   bool value;
68 };
69 
70 
71 struct NoExceptEvilBool {
72   NoExceptEvilBool(NoExceptEvilBool const&) = default;
73   NoExceptEvilBool(NoExceptEvilBool&&) = default;
74   NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
75 
NoExceptEvilBoolNoExceptEvilBool76   constexpr explicit NoExceptEvilBool(bool x) : value(x) {}
77 
operator !(NoExceptEvilBool const & other)78   friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
79     return NoExceptEvilBool{!other.value};
80   }
81 
82   bool value;
83 };
84 
85 
86 
87 TEST_CONSTEXPR_CXX20
constructor_tests()88 bool constructor_tests()
89 {
90     {
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);
110     }
111     {
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);
134     }
135     {
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);
146     }
147     {
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);
159     }
160     return true;
161 }
162 
return_type_tests()163 void return_type_tests()
164 {
165     using std::is_same;
166     {
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);
172     }
173     {
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);
179     }
180     {
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);
190     }
191 }
192 
193 // Other tests only test using objects with call operators. Test various
194 // other callable types here.
195 TEST_CONSTEXPR_CXX20
other_callable_types_test()196 bool other_callable_types_test()
197 {
198     { // test with function pointer
199         auto ret = std::not_fn(returns_true);
200         assert(ret() == false);
201     }
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);
207     }
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);
216     }
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);
225     }
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);
234     }
235     return true;
236 }
237 
throws_in_constructor_test()238 void throws_in_constructor_test()
239 {
240 #ifndef TEST_HAS_NO_EXCEPTIONS
241     struct ThrowsOnCopy {
242       ThrowsOnCopy(ThrowsOnCopy const&) {
243         throw 42;
244       }
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
253       }
254     };
255     {
256         ThrowsOnCopy cp;
257         try {
258             (void)std::not_fn(cp);
259             assert(false);
260         } catch (int const& value) {
261             assert(value == 42);
262         }
263     }
264 #endif
265 }
266 
267 TEST_CONSTEXPR_CXX20
call_operator_sfinae_test()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, "");
273     }
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, "");
278     }
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, "");
285     }
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, "");
291     }
292     return true;
293 }
294 
295 TEST_CONSTEXPR_CXX20
call_operator_forwarding_test()296 bool call_operator_forwarding_test()
297 {
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));
311     }
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));
325     }
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));
339     }
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));
353     }
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));
367     }
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)));
380     }
381     return true;
382 }
383 
384 TEST_CONSTEXPR_CXX20
call_operator_noexcept_test()385 bool call_operator_noexcept_test()
386 {
387     {
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");
394     }
395     {
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");
406     }
407     {
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");
414     }
415     {
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");
422     }
423     return true;
424 }
425 
426 TEST_CONSTEXPR_CXX20
test_lwg2767()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; } };
432     {
433         Derived d;
434         Abstract &a = d;
435         bool b = std::not_fn(F{})(std::move(a));
436         assert(b);
437     }
438     return true;
439 }
440 
main(int,char **)441 int main(int, char**)
442 {
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();
451 
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
460 
461     return 0;
462 }
463