• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++98, c++03, c++11, c++14
11 
12 // template <class F> unspecified not_fn(F&& f);
13 
14 #include <functional>
15 #include <type_traits>
16 #include <string>
17 #include <cassert>
18 
19 #include "test_macros.h"
20 #include "type_id.h"
21 
22 
23 ///////////////////////////////////////////////////////////////////////////////
24 //                       CALLABLE TEST TYPES
25 ///////////////////////////////////////////////////////////////////////////////
26 
returns_true()27 bool returns_true() { return true; }
28 
29 template <class Ret = bool>
30 struct MoveOnlyCallable {
31   MoveOnlyCallable(MoveOnlyCallable const&) = delete;
MoveOnlyCallableMoveOnlyCallable32   MoveOnlyCallable(MoveOnlyCallable&& other)
33       : value(other.value)
34   { other.value = !other.value; }
35 
36   template <class ...Args>
operator ()MoveOnlyCallable37   Ret operator()(Args&&...) { return Ret{value}; }
38 
MoveOnlyCallableMoveOnlyCallable39   explicit MoveOnlyCallable(bool x) : value(x) {}
40   Ret value;
41 };
42 
43 template <class Ret = bool>
44 struct CopyCallable {
CopyCallableCopyCallable45   CopyCallable(CopyCallable const& other)
46       : value(other.value) {}
47 
CopyCallableCopyCallable48   CopyCallable(CopyCallable&& other)
49       : value(other.value) { other.value = !other.value; }
50 
51   template <class ...Args>
operator ()CopyCallable52   Ret operator()(Args&&...) { return Ret{value}; }
53 
CopyCallableCopyCallable54   explicit CopyCallable(bool x) : value(x)  {}
55   Ret value;
56 };
57 
58 
59 template <class Ret = bool>
60 struct ConstCallable {
ConstCallableConstCallable61   ConstCallable(ConstCallable const& other)
62       : value(other.value) {}
63 
ConstCallableConstCallable64   ConstCallable(ConstCallable&& other)
65       : value(other.value) { other.value = !other.value; }
66 
67   template <class ...Args>
operator ()ConstCallable68   Ret operator()(Args&&...) const { return Ret{value}; }
69 
ConstCallableConstCallable70   explicit ConstCallable(bool x) : value(x)  {}
71   Ret value;
72 };
73 
74 
75 
76 template <class Ret = bool>
77 struct NoExceptCallable {
NoExceptCallableNoExceptCallable78   NoExceptCallable(NoExceptCallable const& other)
79       : value(other.value) {}
80 
81   template <class ...Args>
operator ()NoExceptCallable82   Ret operator()(Args&&...) noexcept { return Ret{value}; }
83 
84   template <class ...Args>
operator ()NoExceptCallable85   Ret operator()(Args&&...) const noexcept { return Ret{value}; }
86 
NoExceptCallableNoExceptCallable87   explicit NoExceptCallable(bool x) : value(x)  {}
88   Ret value;
89 };
90 
91 struct CopyAssignableWrapper {
92   CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
93   CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
94   CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
95   CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
96 
97   template <class ...Args>
operator ()CopyAssignableWrapper98   bool operator()(Args&&...) { return value; }
99 
CopyAssignableWrapperCopyAssignableWrapper100   explicit CopyAssignableWrapper(bool x) : value(x) {}
101   bool value;
102 };
103 
104 
105 struct MoveAssignableWrapper {
106   MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
107   MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
108   MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
109   MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
110 
111   template <class ...Args>
operator ()MoveAssignableWrapper112   bool operator()(Args&&...) { return value; }
113 
MoveAssignableWrapperMoveAssignableWrapper114   explicit MoveAssignableWrapper(bool x) : value(x) {}
115   bool value;
116 };
117 
118 struct MemFunCallable {
MemFunCallableMemFunCallable119   explicit MemFunCallable(bool x) : value(x) {}
120 
return_valueMemFunCallable121   bool return_value() const { return value; }
return_value_ncMemFunCallable122   bool return_value_nc() { return value; }
123   bool value;
124 };
125 
126 enum CallType : unsigned {
127   CT_None,
128   CT_NonConst = 1,
129   CT_Const = 2,
130   CT_LValue = 4,
131   CT_RValue = 8
132 };
133 
operator |(CallType LHS,CallType RHS)134 inline constexpr CallType operator|(CallType LHS, CallType RHS) {
135     return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS));
136 }
137 
138 struct ForwardingCallObject {
139 
140   template <class ...Args>
operator ()ForwardingCallObject141   bool operator()(Args&&...) & {
142       set_call<Args&&...>(CT_NonConst | CT_LValue);
143       return true;
144   }
145 
146   template <class ...Args>
operator ()ForwardingCallObject147   bool operator()(Args&&...) const & {
148       set_call<Args&&...>(CT_Const | CT_LValue);
149       return true;
150   }
151 
152   // Don't allow the call operator to be invoked as an rvalue.
153   template <class ...Args>
operator ()ForwardingCallObject154   bool operator()(Args&&...) && {
155       set_call<Args&&...>(CT_NonConst | CT_RValue);
156       return true;
157   }
158 
159   template <class ...Args>
operator ()ForwardingCallObject160   bool operator()(Args&&...) const && {
161       set_call<Args&&...>(CT_Const | CT_RValue);
162       return true;
163   }
164 
165   template <class ...Args>
set_callForwardingCallObject166   static void set_call(CallType type) {
167       assert(last_call_type == CT_None);
168       assert(last_call_args == nullptr);
169       last_call_type = type;
170       last_call_args = &makeArgumentID<Args...>();
171   }
172 
173   template <class ...Args>
check_callForwardingCallObject174   static bool check_call(CallType type) {
175       bool result =
176            last_call_type == type
177         && last_call_args
178         && *last_call_args == makeArgumentID<Args...>();
179       last_call_type = CT_None;
180       last_call_args = nullptr;
181       return result;
182   }
183 
184   static CallType      last_call_type;
185   static TypeID const* last_call_args;
186 };
187 
188 CallType ForwardingCallObject::last_call_type = CT_None;
189 TypeID const* ForwardingCallObject::last_call_args = nullptr;
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 
operator !(EvilBool const & other)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 
EvilBoolEvilBool213   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 
operator boolExplicitBool226   explicit operator bool() const { return value; }
227 
228 private:
229   friend struct MoveOnlyCallable<ExplicitBool>;
230   friend struct CopyCallable<ExplicitBool>;
231 
ExplicitBoolExplicitBool232   explicit ExplicitBool(bool x) : value(x) {}
operator =ExplicitBool233   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 
NoExceptEvilBoolNoExceptEvilBool247   explicit NoExceptEvilBool(bool x) : value(x) {}
248 
operator !(NoExceptEvilBool const & other)249   friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
250     return NoExceptEvilBool{!other.value};
251   }
252 
253   bool value;
254 };
255 
256 
257 
constructor_tests()258 void constructor_tests()
259 {
260     {
261         using T = MoveOnlyCallable<bool>;
262         T value(true);
263         using RetT = decltype(std::not_fn(std::move(value)));
264         static_assert(std::is_move_constructible<RetT>::value, "");
265         static_assert(!std::is_copy_constructible<RetT>::value, "");
266         static_assert(!std::is_move_assignable<RetT>::value, "");
267         static_assert(!std::is_copy_assignable<RetT>::value, "");
268         auto ret = std::not_fn(std::move(value));
269         // test it was moved from
270         assert(value.value == false);
271         // test that ret() negates the original value 'true'
272         assert(ret() == false);
273         assert(ret(0, 0.0, "blah") == false);
274         // Move ret and test that it was moved from and that ret2 got the
275         // original value.
276         auto ret2 = std::move(ret);
277         assert(ret() == true);
278         assert(ret2() == false);
279         assert(ret2(42) == false);
280     }
281     {
282         using T = CopyCallable<bool>;
283         T value(false);
284         using RetT = decltype(std::not_fn(value));
285         static_assert(std::is_move_constructible<RetT>::value, "");
286         static_assert(std::is_copy_constructible<RetT>::value, "");
287         static_assert(!std::is_move_assignable<RetT>::value, "");
288         static_assert(!std::is_copy_assignable<RetT>::value, "");
289         auto ret = std::not_fn(value);
290         // test that value is unchanged (copied not moved)
291         assert(value.value == false);
292         // test 'ret' has the original value
293         assert(ret() == true);
294         assert(ret(42, 100) == true);
295         // move from 'ret' and check that 'ret2' has the original value.
296         auto ret2 = std::move(ret);
297         assert(ret() == false);
298         assert(ret2() == true);
299         assert(ret2("abc") == true);
300     }
301     {
302         using T = CopyAssignableWrapper;
303         T value(true);
304         T value2(false);
305         using RetT = decltype(std::not_fn(value));
306         static_assert(std::is_move_constructible<RetT>::value, "");
307         static_assert(std::is_copy_constructible<RetT>::value, "");
308         LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, "");
309         LIBCPP_STATIC_ASSERT(std::is_copy_assignable<RetT>::value, "");
310         auto ret = std::not_fn(value);
311         assert(ret() == false);
312         auto ret2 = std::not_fn(value2);
313         assert(ret2() == true);
314 #if defined(_LIBCPP_VERSION)
315         ret = ret2;
316         assert(ret() == true);
317         assert(ret2() == true);
318 #endif // _LIBCPP_VERSION
319     }
320     {
321         using T = MoveAssignableWrapper;
322         T value(true);
323         T value2(false);
324         using RetT = decltype(std::not_fn(std::move(value)));
325         static_assert(std::is_move_constructible<RetT>::value, "");
326         static_assert(!std::is_copy_constructible<RetT>::value, "");
327         LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, "");
328         static_assert(!std::is_copy_assignable<RetT>::value, "");
329         auto ret = std::not_fn(std::move(value));
330         assert(ret() == false);
331         auto ret2 = std::not_fn(std::move(value2));
332         assert(ret2() == true);
333 #if defined(_LIBCPP_VERSION)
334         ret = std::move(ret2);
335         assert(ret() == true);
336 #endif // _LIBCPP_VERSION
337     }
338 }
339 
return_type_tests()340 void return_type_tests()
341 {
342     using std::is_same;
343     {
344         using T = CopyCallable<bool>;
345         auto ret = std::not_fn(T{false});
346         static_assert(is_same<decltype(ret()), bool>::value, "");
347         static_assert(is_same<decltype(ret("abc")), bool>::value, "");
348         assert(ret() == true);
349     }
350     {
351         using T = CopyCallable<ExplicitBool>;
352         auto ret = std::not_fn(T{true});
353         static_assert(is_same<decltype(ret()), bool>::value, "");
354         static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
355         assert(ret() == false);
356     }
357     {
358         using T = CopyCallable<EvilBool>;
359         auto ret = std::not_fn(T{false});
360         static_assert(is_same<decltype(ret()), EvilBool>::value, "");
361         EvilBool::bang_called = 0;
362         auto value_ret = ret();
363         assert(EvilBool::bang_called == 1);
364         assert(value_ret.value == true);
365         ret();
366         assert(EvilBool::bang_called == 2);
367     }
368 }
369 
370 // Other tests only test using objects with call operators. Test various
371 // other callable types here.
other_callable_types_test()372 void other_callable_types_test()
373 {
374     { // test with function pointer
375         auto ret = std::not_fn(returns_true);
376         assert(ret() == false);
377     }
378     { // test with lambda
379         auto returns_value = [](bool value) { return value; };
380         auto ret = std::not_fn(returns_value);
381         assert(ret(true) == false);
382         assert(ret(false) == true);
383     }
384     { // test with pointer to member function
385         MemFunCallable mt(true);
386         const MemFunCallable mf(false);
387         auto ret = std::not_fn(&MemFunCallable::return_value);
388         assert(ret(mt) == false);
389         assert(ret(mf) == true);
390         assert(ret(&mt) == false);
391         assert(ret(&mf) == true);
392     }
393     { // test with pointer to member function
394         MemFunCallable mt(true);
395         MemFunCallable mf(false);
396         auto ret = std::not_fn(&MemFunCallable::return_value_nc);
397         assert(ret(mt) == false);
398         assert(ret(mf) == true);
399         assert(ret(&mt) == false);
400         assert(ret(&mf) == true);
401     }
402     { // test with pointer to member data
403         MemFunCallable mt(true);
404         const MemFunCallable mf(false);
405         auto ret = std::not_fn(&MemFunCallable::value);
406         assert(ret(mt) == false);
407         assert(ret(mf) == true);
408         assert(ret(&mt) == false);
409         assert(ret(&mf) == true);
410     }
411 }
412 
throws_in_constructor_test()413 void throws_in_constructor_test()
414 {
415 #ifndef TEST_HAS_NO_EXCEPTIONS
416     struct ThrowsOnCopy {
417       ThrowsOnCopy(ThrowsOnCopy const&) {
418         throw 42;
419       }
420       ThrowsOnCopy() = default;
421       bool operator()() const {
422         assert(false);
423 #if defined(TEST_COMPILER_C1XX)
424         __assume(0);
425 #else
426         __builtin_unreachable();
427 #endif
428       }
429     };
430     {
431         ThrowsOnCopy cp;
432         try {
433             (void)std::not_fn(cp);
434             assert(false);
435         } catch (int const& value) {
436             assert(value == 42);
437         }
438     }
439 #endif
440 }
441 
call_operator_sfinae_test()442 void call_operator_sfinae_test() {
443     { // wrong number of arguments
444         using T = decltype(std::not_fn(returns_true));
445         static_assert(std::is_invocable<T>::value, ""); // callable only with no args
446         static_assert(!std::is_invocable<T, bool>::value, "");
447     }
448     { // violates const correctness (member function pointer)
449         using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
450         static_assert(std::is_invocable<T, MemFunCallable&>::value, "");
451         static_assert(!std::is_invocable<T, const MemFunCallable&>::value, "");
452     }
453     { // violates const correctness (call object)
454         using Obj = CopyCallable<bool>;
455         using NCT = decltype(std::not_fn(Obj{true}));
456         using CT = const NCT;
457         static_assert(std::is_invocable<NCT>::value, "");
458         static_assert(!std::is_invocable<CT>::value, "");
459     }
460     { // returns bad type with no operator!
461         auto fn = [](auto x) { return x; };
462         using T = decltype(std::not_fn(fn));
463         static_assert(std::is_invocable<T, bool>::value, "");
464         static_assert(!std::is_invocable<T, std::string>::value, "");
465     }
466 }
467 
call_operator_forwarding_test()468 void call_operator_forwarding_test()
469 {
470     using Fn = ForwardingCallObject;
471     auto obj = std::not_fn(Fn{});
472     const auto& c_obj = obj;
473     { // test zero args
474         obj();
475         assert(Fn::check_call<>(CT_NonConst | CT_LValue));
476         std::move(obj)();
477         assert(Fn::check_call<>(CT_NonConst | CT_RValue));
478         c_obj();
479         assert(Fn::check_call<>(CT_Const | CT_LValue));
480         std::move(c_obj)();
481         assert(Fn::check_call<>(CT_Const | CT_RValue));
482     }
483     { // test value categories
484         int x = 42;
485         const int cx = 42;
486         obj(x);
487         assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
488         obj(cx);
489         assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue));
490         obj(std::move(x));
491         assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
492         obj(std::move(cx));
493         assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue));
494         obj(42);
495         assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
496     }
497     { // test value categories - rvalue
498         int x = 42;
499         const int cx = 42;
500         std::move(obj)(x);
501         assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
502         std::move(obj)(cx);
503         assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue));
504         std::move(obj)(std::move(x));
505         assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
506         std::move(obj)(std::move(cx));
507         assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue));
508         std::move(obj)(42);
509         assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
510     }
511     { // test value categories - const call
512         int x = 42;
513         const int cx = 42;
514         c_obj(x);
515         assert(Fn::check_call<int&>(CT_Const | CT_LValue));
516         c_obj(cx);
517         assert(Fn::check_call<const int&>(CT_Const | CT_LValue));
518         c_obj(std::move(x));
519         assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
520         c_obj(std::move(cx));
521         assert(Fn::check_call<const int&&>(CT_Const | CT_LValue));
522         c_obj(42);
523         assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
524     }
525     { // test value categories - const call rvalue
526         int x = 42;
527         const int cx = 42;
528         std::move(c_obj)(x);
529         assert(Fn::check_call<int&>(CT_Const | CT_RValue));
530         std::move(c_obj)(cx);
531         assert(Fn::check_call<const int&>(CT_Const | CT_RValue));
532         std::move(c_obj)(std::move(x));
533         assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
534         std::move(c_obj)(std::move(cx));
535         assert(Fn::check_call<const int&&>(CT_Const | CT_RValue));
536         std::move(c_obj)(42);
537         assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
538     }
539     { // test multi arg
540         const double y = 3.14;
541         std::string s = "abc";
542         obj(42, std::move(y), s, std::string{"foo"});
543         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue);
544         std::move(obj)(42, std::move(y), s, std::string{"foo"});
545         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue);
546         c_obj(42, std::move(y), s, std::string{"foo"});
547         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const  | CT_LValue);
548         std::move(c_obj)(42, std::move(y), s, std::string{"foo"});
549         Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const  | CT_RValue);
550     }
551 }
552 
call_operator_noexcept_test()553 void call_operator_noexcept_test()
554 {
555     {
556         using T = ConstCallable<bool>;
557         T value(true);
558         auto ret = std::not_fn(value);
559         static_assert(!noexcept(ret()), "call should not be noexcept");
560         auto const& cret = ret;
561         static_assert(!noexcept(cret()), "call should not be noexcept");
562     }
563     {
564         using T = NoExceptCallable<bool>;
565         T value(true);
566         auto ret = std::not_fn(value);
567         LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), "");
568 #if TEST_STD_VER > 14
569         static_assert(noexcept(!std::invoke(value)), "");
570 #endif
571         static_assert(noexcept(ret()), "call should be noexcept");
572         auto const& cret = ret;
573         static_assert(noexcept(cret()), "call should be noexcept");
574     }
575     {
576         using T = NoExceptCallable<NoExceptEvilBool>;
577         T value(true);
578         auto ret = std::not_fn(value);
579         static_assert(noexcept(ret()), "call should not be noexcept");
580         auto const& cret = ret;
581         static_assert(noexcept(cret()), "call should not be noexcept");
582     }
583     {
584         using T = NoExceptCallable<EvilBool>;
585         T value(true);
586         auto ret = std::not_fn(value);
587         static_assert(!noexcept(ret()), "call should not be noexcept");
588         auto const& cret = ret;
589         static_assert(!noexcept(cret()), "call should not be noexcept");
590     }
591 }
592 
test_lwg2767()593 void test_lwg2767() {
594     // See https://cplusplus.github.io/LWG/lwg-defects.html#2767
595     struct Abstract { virtual void f() const = 0; };
596     struct Derived : public Abstract { void f() const {} };
597     struct F { bool operator()(Abstract&&) { return false; } };
598     {
599         Derived d;
600         Abstract &a = d;
601         bool b = std::not_fn(F{})(std::move(a));
602         assert(b);
603     }
604 }
605 
main()606 int main()
607 {
608     constructor_tests();
609     return_type_tests();
610     other_callable_types_test();
611     throws_in_constructor_test();
612     call_operator_sfinae_test(); // somewhat of an extension
613     call_operator_forwarding_test();
614     call_operator_noexcept_test();
615     test_lwg2767();
616 }
617