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 
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 //                       CALLABLE TEST TYPES
24 ///////////////////////////////////////////////////////////////////////////////
25 
26 constexpr bool returns_true() { return true; }
27 
28 template <class Ret = bool>
29 struct MoveOnlyCallable {
30   MoveOnlyCallable(MoveOnlyCallable const&) = delete;
31   constexpr MoveOnlyCallable(MoveOnlyCallable&& other)
32       : value(other.value)
33   { other.value = !other.value; }
34 
35   template <class ...Args>
36   constexpr Ret operator()(Args&&...) { return Ret{value}; }
37 
38   constexpr explicit MoveOnlyCallable(bool x) : value(x) {}
39   Ret value;
40 };
41 
42 template <class Ret = bool>
43 struct CopyCallable {
44   constexpr CopyCallable(CopyCallable const& other)
45       : value(other.value) {}
46 
47   constexpr CopyCallable(CopyCallable&& other)
48       : value(other.value) { other.value = !other.value; }
49 
50   template <class ...Args>
51   constexpr Ret operator()(Args&&...) { return Ret{value}; }
52 
53   constexpr explicit CopyCallable(bool x) : value(x)  {}
54   Ret value;
55 };
56 
57 
58 template <class Ret = bool>
59 struct ConstCallable {
60   constexpr ConstCallable(ConstCallable const& other)
61       : value(other.value) {}
62 
63   constexpr ConstCallable(ConstCallable&& other)
64       : value(other.value) { other.value = !other.value; }
65 
66   template <class ...Args>
67   constexpr Ret operator()(Args&&...) const { return Ret{value}; }
68 
69   constexpr explicit ConstCallable(bool x) : value(x)  {}
70   Ret value;
71 };
72 
73 
74 
75 template <class Ret = bool>
76 struct NoExceptCallable {
77   constexpr NoExceptCallable(NoExceptCallable const& other)
78       : value(other.value) {}
79 
80   template <class ...Args>
81   constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; }
82 
83   template <class ...Args>
84   constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; }
85 
86   constexpr explicit NoExceptCallable(bool x) : value(x)  {}
87   Ret value;
88 };
89 
90 struct CopyAssignableWrapper {
91   constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
92   constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
93   constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
94   constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
95 
96   template <class ...Args>
97   constexpr bool operator()(Args&&...) { return value; }
98 
99   constexpr explicit CopyAssignableWrapper(bool x) : value(x) {}
100   bool value;
101 };
102 
103 
104 struct MoveAssignableWrapper {
105   constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
106   constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
107   constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
108   constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
109 
110   template <class ...Args>
111   constexpr bool operator()(Args&&...) { return value; }
112 
113   constexpr explicit MoveAssignableWrapper(bool x) : value(x) {}
114   bool value;
115 };
116 
117 struct MemFunCallable {
118   constexpr explicit MemFunCallable(bool x) : value(x) {}
119 
120   constexpr bool return_value() const { return value; }
121   constexpr bool return_value_nc() { return value; }
122   bool value;
123 };
124 
125 enum CallType : unsigned {
126   CT_None,
127   CT_NonConst = 1,
128   CT_Const = 2,
129   CT_LValue = 4,
130   CT_RValue = 8
131 };
132 
133 inline constexpr CallType operator|(CallType LHS, CallType RHS) {
134     return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS));
135 }
136 
137 struct ForwardingCallObject {
138   struct State {
139     CallType      last_call_type = CT_None;
140     TypeID const& (*last_call_args)() = nullptr;
141 
142     template <class ...Args>
143     constexpr void set_call(CallType type) {
144       assert(last_call_type == CT_None);
145       assert(last_call_args == nullptr);
146       last_call_type = type;
147       last_call_args = &makeArgumentID<Args...>;
148     }
149 
150     template <class ...Args>
151     constexpr bool check_call(CallType type) {
152       bool result =
153            last_call_type == type
154         && last_call_args
155         && *last_call_args == &makeArgumentID<Args...>;
156       last_call_type = CT_None;
157       last_call_args = nullptr;
158       return result;
159     }
160   };
161 
162   State *st_;
163 
164   explicit constexpr ForwardingCallObject(State& st) : st_(&st) {}
165 
166   template <class ...Args>
167   constexpr bool operator()(Args&&...) & {
168       st_->set_call<Args&&...>(CT_NonConst | CT_LValue);
169       return true;
170   }
171 
172   template <class ...Args>
173   constexpr bool operator()(Args&&...) const & {
174       st_->set_call<Args&&...>(CT_Const | CT_LValue);
175       return true;
176   }
177 
178   // Don't allow the call operator to be invoked as an rvalue.
179   template <class ...Args>
180   constexpr bool operator()(Args&&...) && {
181       st_->set_call<Args&&...>(CT_NonConst | CT_RValue);
182       return true;
183   }
184 
185   template <class ...Args>
186   constexpr bool operator()(Args&&...) const && {
187       st_->set_call<Args&&...>(CT_Const | CT_RValue);
188       return true;
189   }
190 };
191 
192 
193 ///////////////////////////////////////////////////////////////////////////////
194 //                        BOOL TEST TYPES
195 ///////////////////////////////////////////////////////////////////////////////
196 
197 struct EvilBool {
198   static int bang_called;
199 
200   EvilBool(EvilBool const&) = default;
201   EvilBool(EvilBool&&) = default;
202 
203   friend EvilBool operator!(EvilBool const& other) {
204     ++bang_called;
205     return EvilBool{!other.value};
206   }
207 
208 private:
209   friend struct MoveOnlyCallable<EvilBool>;
210   friend struct CopyCallable<EvilBool>;
211   friend struct NoExceptCallable<EvilBool>;
212 
213   constexpr explicit EvilBool(bool x) : value(x) {}
214   EvilBool& operator=(EvilBool const& other) = default;
215 
216 public:
217   bool value;
218 };
219 
220 int EvilBool::bang_called = 0;
221 
222 struct ExplicitBool {
223   ExplicitBool(ExplicitBool const&) = default;
224   ExplicitBool(ExplicitBool&&) = default;
225 
226   constexpr explicit operator bool() const { return value; }
227 
228 private:
229   friend struct MoveOnlyCallable<ExplicitBool>;
230   friend struct CopyCallable<ExplicitBool>;
231 
232   constexpr explicit ExplicitBool(bool x) : value(x) {}
233   constexpr ExplicitBool& operator=(bool x) {
234       value = x;
235       return *this;
236   }
237 
238   bool value;
239 };
240 
241 
242 struct NoExceptEvilBool {
243   NoExceptEvilBool(NoExceptEvilBool const&) = default;
244   NoExceptEvilBool(NoExceptEvilBool&&) = default;
245   NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
246 
247   constexpr explicit NoExceptEvilBool(bool x) : value(x) {}
248 
249   friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
250     return NoExceptEvilBool{!other.value};
251   }
252 
253   bool value;
254 };
255 
256 
257 
258 TEST_CONSTEXPR_CXX20
259 bool constructor_tests()
260 {
261     {
262         using T = MoveOnlyCallable<bool>;
263         T value(true);
264         using RetT = decltype(std::not_fn(std::move(value)));
265         static_assert(std::is_move_constructible<RetT>::value, "");
266         static_assert(!std::is_copy_constructible<RetT>::value, "");
267         static_assert(!std::is_move_assignable<RetT>::value, "");
268         static_assert(!std::is_copy_assignable<RetT>::value, "");
269         auto ret = std::not_fn(std::move(value));
270         // test it was moved from
271         assert(value.value == false);
272         // test that ret() negates the original value 'true'
273         assert(ret() == false);
274         assert(ret(0, 0.0, "blah") == false);
275         // Move ret and test that it was moved from and that ret2 got the
276         // original value.
277         auto ret2 = std::move(ret);
278         assert(ret() == true);
279         assert(ret2() == false);
280         assert(ret2(42) == false);
281     }
282     {
283         using T = CopyCallable<bool>;
284         T value(false);
285         using RetT = decltype(std::not_fn(value));
286         static_assert(std::is_move_constructible<RetT>::value, "");
287         static_assert(std::is_copy_constructible<RetT>::value, "");
288         static_assert(!std::is_move_assignable<RetT>::value, "");
289         static_assert(!std::is_copy_assignable<RetT>::value, "");
290         auto ret = std::not_fn(value);
291         // test that value is unchanged (copied not moved)
292         assert(value.value == false);
293         // test 'ret' has the original value
294         assert(ret() == true);
295         assert(ret(42, 100) == true);
296         // move from 'ret' and check that 'ret2' has the original value.
297         auto ret2 = std::move(ret);
298         assert(ret() == false);
299         assert(ret2() == true);
300         assert(ret2("abc") == true);
301     }
302     {
303         using T = CopyAssignableWrapper;
304         T value(true);
305         T value2(false);
306         using RetT = decltype(std::not_fn(value));
307         static_assert(std::is_move_constructible<RetT>::value, "");
308         static_assert(std::is_copy_constructible<RetT>::value, "");
309         LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, "");
310         LIBCPP_STATIC_ASSERT(std::is_copy_assignable<RetT>::value, "");
311         auto ret = std::not_fn(value);
312         assert(ret() == false);
313         auto ret2 = std::not_fn(value2);
314         assert(ret2() == true);
315 #if defined(_LIBCPP_VERSION)
316         ret = ret2;
317         assert(ret() == true);
318         assert(ret2() == true);
319 #endif // _LIBCPP_VERSION
320     }
321     {
322         using T = MoveAssignableWrapper;
323         T value(true);
324         T value2(false);
325         using RetT = decltype(std::not_fn(std::move(value)));
326         static_assert(std::is_move_constructible<RetT>::value, "");
327         static_assert(!std::is_copy_constructible<RetT>::value, "");
328         LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, "");
329         static_assert(!std::is_copy_assignable<RetT>::value, "");
330         auto ret = std::not_fn(std::move(value));
331         assert(ret() == false);
332         auto ret2 = std::not_fn(std::move(value2));
333         assert(ret2() == true);
334 #if defined(_LIBCPP_VERSION)
335         ret = std::move(ret2);
336         assert(ret() == true);
337 #endif // _LIBCPP_VERSION
338     }
339     return true;
340 }
341 
342 void return_type_tests()
343 {
344     using std::is_same;
345     {
346         using T = CopyCallable<bool>;
347         auto ret = std::not_fn(T{false});
348         static_assert(is_same<decltype(ret()), bool>::value, "");
349         static_assert(is_same<decltype(ret("abc")), bool>::value, "");
350         assert(ret() == true);
351     }
352     {
353         using T = CopyCallable<ExplicitBool>;
354         auto ret = std::not_fn(T{true});
355         static_assert(is_same<decltype(ret()), bool>::value, "");
356         static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
357         assert(ret() == false);
358     }
359     {
360         using T = CopyCallable<EvilBool>;
361         auto ret = std::not_fn(T{false});
362         static_assert(is_same<decltype(ret()), EvilBool>::value, "");
363         EvilBool::bang_called = 0;
364         auto value_ret = ret();
365         assert(EvilBool::bang_called == 1);
366         assert(value_ret.value == true);
367         ret();
368         assert(EvilBool::bang_called == 2);
369     }
370 }
371 
372 // Other tests only test using objects with call operators. Test various
373 // other callable types here.
374 TEST_CONSTEXPR_CXX20
375 bool other_callable_types_test()
376 {
377     { // test with function pointer
378         auto ret = std::not_fn(returns_true);
379         assert(ret() == false);
380     }
381     { // test with lambda
382         auto returns_value = [](bool value) { return value; };
383         auto ret = std::not_fn(returns_value);
384         assert(ret(true) == false);
385         assert(ret(false) == true);
386     }
387     { // test with pointer to member function
388         MemFunCallable mt(true);
389         const MemFunCallable mf(false);
390         auto ret = std::not_fn(&MemFunCallable::return_value);
391         assert(ret(mt) == false);
392         assert(ret(mf) == true);
393         assert(ret(&mt) == false);
394         assert(ret(&mf) == true);
395     }
396     { // test with pointer to member function
397         MemFunCallable mt(true);
398         MemFunCallable mf(false);
399         auto ret = std::not_fn(&MemFunCallable::return_value_nc);
400         assert(ret(mt) == false);
401         assert(ret(mf) == true);
402         assert(ret(&mt) == false);
403         assert(ret(&mf) == true);
404     }
405     { // test with pointer to member data
406         MemFunCallable mt(true);
407         const MemFunCallable mf(false);
408         auto ret = std::not_fn(&MemFunCallable::value);
409         assert(ret(mt) == false);
410         assert(ret(mf) == true);
411         assert(ret(&mt) == false);
412         assert(ret(&mf) == true);
413     }
414     return true;
415 }
416 
417 void throws_in_constructor_test()
418 {
419 #ifndef TEST_HAS_NO_EXCEPTIONS
420     struct ThrowsOnCopy {
421       ThrowsOnCopy(ThrowsOnCopy const&) {
422         throw 42;
423       }
424       ThrowsOnCopy() = default;
425       bool operator()() const {
426         assert(false);
427 #if defined(TEST_COMPILER_C1XX)
428         __assume(0);
429 #else
430         __builtin_unreachable();
431 #endif
432       }
433     };
434     {
435         ThrowsOnCopy cp;
436         try {
437             (void)std::not_fn(cp);
438             assert(false);
439         } catch (int const& value) {
440             assert(value == 42);
441         }
442     }
443 #endif
444 }
445 
446 TEST_CONSTEXPR_CXX20
447 bool call_operator_sfinae_test() {
448     { // wrong number of arguments
449         using T = decltype(std::not_fn(returns_true));
450         static_assert(std::is_invocable<T>::value, ""); // callable only with no args
451         static_assert(!std::is_invocable<T, bool>::value, "");
452     }
453     { // violates const correctness (member function pointer)
454         using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
455         static_assert(std::is_invocable<T, MemFunCallable&>::value, "");
456         static_assert(!std::is_invocable<T, const MemFunCallable&>::value, "");
457     }
458     { // violates const correctness (call object)
459         using Obj = CopyCallable<bool>;
460         using NCT = decltype(std::not_fn(Obj{true}));
461         using CT = const NCT;
462         static_assert(std::is_invocable<NCT>::value, "");
463         static_assert(!std::is_invocable<CT>::value, "");
464     }
465     { // returns bad type with no operator!
466         auto fn = [](auto x) { return x; };
467         using T = decltype(std::not_fn(fn));
468         static_assert(std::is_invocable<T, bool>::value, "");
469         static_assert(!std::is_invocable<T, std::string>::value, "");
470     }
471     return true;
472 }
473 
474 TEST_CONSTEXPR_CXX20
475 bool call_operator_forwarding_test()
476 {
477     using Fn = ForwardingCallObject;
478     Fn::State st;
479     auto obj = std::not_fn(Fn{st});
480     const auto& c_obj = obj;
481     { // test zero args
482         obj();
483         assert(st.check_call<>(CT_NonConst | CT_LValue));
484         std::move(obj)();
485         assert(st.check_call<>(CT_NonConst | CT_RValue));
486         c_obj();
487         assert(st.check_call<>(CT_Const | CT_LValue));
488         std::move(c_obj)();
489         assert(st.check_call<>(CT_Const | CT_RValue));
490     }
491     { // test value categories
492         int x = 42;
493         const int cx = 42;
494         obj(x);
495         assert(st.check_call<int&>(CT_NonConst | CT_LValue));
496         obj(cx);
497         assert(st.check_call<const int&>(CT_NonConst | CT_LValue));
498         obj(std::move(x));
499         assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
500         obj(std::move(cx));
501         assert(st.check_call<const int&&>(CT_NonConst | CT_LValue));
502         obj(42);
503         assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
504     }
505     { // test value categories - rvalue
506         int x = 42;
507         const int cx = 42;
508         std::move(obj)(x);
509         assert(st.check_call<int&>(CT_NonConst | CT_RValue));
510         std::move(obj)(cx);
511         assert(st.check_call<const int&>(CT_NonConst | CT_RValue));
512         std::move(obj)(std::move(x));
513         assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
514         std::move(obj)(std::move(cx));
515         assert(st.check_call<const int&&>(CT_NonConst | CT_RValue));
516         std::move(obj)(42);
517         assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
518     }
519     { // test value categories - const call
520         int x = 42;
521         const int cx = 42;
522         c_obj(x);
523         assert(st.check_call<int&>(CT_Const | CT_LValue));
524         c_obj(cx);
525         assert(st.check_call<const int&>(CT_Const | CT_LValue));
526         c_obj(std::move(x));
527         assert(st.check_call<int&&>(CT_Const | CT_LValue));
528         c_obj(std::move(cx));
529         assert(st.check_call<const int&&>(CT_Const | CT_LValue));
530         c_obj(42);
531         assert(st.check_call<int&&>(CT_Const | CT_LValue));
532     }
533     { // test value categories - const call rvalue
534         int x = 42;
535         const int cx = 42;
536         std::move(c_obj)(x);
537         assert(st.check_call<int&>(CT_Const | CT_RValue));
538         std::move(c_obj)(cx);
539         assert(st.check_call<const int&>(CT_Const | CT_RValue));
540         std::move(c_obj)(std::move(x));
541         assert(st.check_call<int&&>(CT_Const | CT_RValue));
542         std::move(c_obj)(std::move(cx));
543         assert(st.check_call<const int&&>(CT_Const | CT_RValue));
544         std::move(c_obj)(42);
545         assert(st.check_call<int&&>(CT_Const | CT_RValue));
546     }
547     { // test multi arg
548         using String = const char *;
549         const double y = 3.14;
550         String s = "abc";
551         obj(42, std::move(y), s, String{"foo"});
552         assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue)));
553         std::move(obj)(42, std::move(y), s, String{"foo"});
554         assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue)));
555         c_obj(42, std::move(y), s, String{"foo"});
556         assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const  | CT_LValue)));
557         std::move(c_obj)(42, std::move(y), s, String{"foo"});
558         assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const  | CT_RValue)));
559     }
560     return true;
561 }
562 
563 TEST_CONSTEXPR_CXX20
564 bool call_operator_noexcept_test()
565 {
566     {
567         using T = ConstCallable<bool>;
568         T value(true);
569         auto ret = std::not_fn(value);
570         static_assert(!noexcept(ret()), "call should not be noexcept");
571         auto const& cret = ret;
572         static_assert(!noexcept(cret()), "call should not be noexcept");
573     }
574     {
575         using T = NoExceptCallable<bool>;
576         T value(true);
577         auto ret = std::not_fn(value);
578         LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), "");
579 #if TEST_STD_VER > 14
580         static_assert(noexcept(!std::invoke(value)), "");
581 #endif
582         static_assert(noexcept(ret()), "call should be noexcept");
583         auto const& cret = ret;
584         static_assert(noexcept(cret()), "call should be noexcept");
585     }
586     {
587         using T = NoExceptCallable<NoExceptEvilBool>;
588         T value(true);
589         auto ret = std::not_fn(value);
590         static_assert(noexcept(ret()), "call should not be noexcept");
591         auto const& cret = ret;
592         static_assert(noexcept(cret()), "call should not be noexcept");
593     }
594     {
595         using T = NoExceptCallable<EvilBool>;
596         T value(true);
597         auto ret = std::not_fn(value);
598         static_assert(!noexcept(ret()), "call should not be noexcept");
599         auto const& cret = ret;
600         static_assert(!noexcept(cret()), "call should not be noexcept");
601     }
602     return true;
603 }
604 
605 TEST_CONSTEXPR_CXX20
606 bool test_lwg2767() {
607     // See https://cplusplus.github.io/LWG/lwg-defects.html#2767
608     struct Abstract { virtual void f() const = 0; };
609     struct Derived : public Abstract { void f() const {} };
610     struct F { constexpr bool operator()(Abstract&&) { return false; } };
611     {
612         Derived d;
613         Abstract &a = d;
614         bool b = std::not_fn(F{})(std::move(a));
615         assert(b);
616     }
617     return true;
618 }
619 
620 int main(int, char**)
621 {
622     constructor_tests();
623     return_type_tests();
624     other_callable_types_test();
625     throws_in_constructor_test();
626     call_operator_sfinae_test(); // somewhat of an extension
627     call_operator_forwarding_test();
628     call_operator_noexcept_test();
629     test_lwg2767();
630 
631 #if TEST_STD_VER >= 20
632     static_assert(constructor_tests());
633     static_assert(other_callable_types_test());
634     static_assert(call_operator_sfinae_test()); // somewhat of an extension
635     static_assert(call_operator_forwarding_test());
636     static_assert(call_operator_noexcept_test());
637     static_assert(test_lwg2767());
638 #endif
639 
640     return 0;
641 }
642