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 #ifndef TEST_CALLABLE_TYPES_H 10 #define TEST_CALLABLE_TYPES_H 11 12 #include "test_macros.h" 13 #include "type_id.h" 14 15 /////////////////////////////////////////////////////////////////////////////// 16 // CALLABLE TEST TYPES 17 /////////////////////////////////////////////////////////////////////////////// 18 returns_true()19constexpr bool returns_true() { return true; } 20 21 template <class Ret> 22 struct MoveOnlyCallable { 23 MoveOnlyCallable(MoveOnlyCallable const&) = delete; MoveOnlyCallableMoveOnlyCallable24 constexpr MoveOnlyCallable(MoveOnlyCallable&& other) 25 : value(other.value) 26 { other.value = !other.value; } 27 28 template <class ...Args> operatorMoveOnlyCallable29 constexpr Ret operator()(Args&&...) { return Ret{value}; } 30 MoveOnlyCallableMoveOnlyCallable31 constexpr explicit MoveOnlyCallable(bool x) : value(x) {} 32 Ret value; 33 }; 34 35 template <class Ret> 36 struct CopyCallable { CopyCallableCopyCallable37 constexpr CopyCallable(CopyCallable const& other) 38 : value(other.value) {} 39 CopyCallableCopyCallable40 constexpr CopyCallable(CopyCallable&& other) 41 : value(other.value) { other.value = !other.value; } 42 43 template <class ...Args> operatorCopyCallable44 constexpr Ret operator()(Args&&...) { return Ret{value}; } 45 CopyCallableCopyCallable46 constexpr explicit CopyCallable(bool x) : value(x) {} 47 Ret value; 48 }; 49 50 51 template <class Ret> 52 struct ConstCallable { ConstCallableConstCallable53 constexpr ConstCallable(ConstCallable const& other) 54 : value(other.value) {} 55 ConstCallableConstCallable56 constexpr ConstCallable(ConstCallable&& other) 57 : value(other.value) { other.value = !other.value; } 58 59 template <class ...Args> operatorConstCallable60 constexpr Ret operator()(Args&&...) const { return Ret{value}; } 61 ConstCallableConstCallable62 constexpr explicit ConstCallable(bool x) : value(x) {} 63 Ret value; 64 }; 65 66 67 68 template <class Ret> 69 struct NoExceptCallable { NoExceptCallableNoExceptCallable70 constexpr NoExceptCallable(NoExceptCallable const& other) 71 : value(other.value) {} 72 73 template <class ...Args> operatorNoExceptCallable74 constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } 75 76 template <class ...Args> operatorNoExceptCallable77 constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; } 78 NoExceptCallableNoExceptCallable79 constexpr explicit NoExceptCallable(bool x) : value(x) {} 80 Ret value; 81 }; 82 83 struct CopyAssignableWrapper { 84 constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default; 85 constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default; 86 constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; 87 constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; 88 89 template <class ...Args> operatorCopyAssignableWrapper90 constexpr bool operator()(Args&&...) { return value; } 91 CopyAssignableWrapperCopyAssignableWrapper92 constexpr explicit CopyAssignableWrapper(bool x) : value(x) {} 93 bool value; 94 }; 95 96 97 struct MoveAssignableWrapper { 98 constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; 99 constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default; 100 constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; 101 constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; 102 103 template <class ...Args> operatorMoveAssignableWrapper104 constexpr bool operator()(Args&&...) { return value; } 105 MoveAssignableWrapperMoveAssignableWrapper106 constexpr explicit MoveAssignableWrapper(bool x) : value(x) {} 107 bool value; 108 }; 109 110 struct MemFunCallable { MemFunCallableMemFunCallable111 constexpr explicit MemFunCallable(bool x) : value(x) {} 112 return_valueMemFunCallable113 constexpr bool return_value() const { return value; } return_value_ncMemFunCallable114 constexpr bool return_value_nc() { return value; } 115 bool value; 116 }; 117 118 enum CallType : unsigned { 119 CT_None, 120 CT_NonConst = 1, 121 CT_Const = 2, 122 CT_LValue = 4, 123 CT_RValue = 8 124 }; 125 126 inline constexpr CallType operator|(CallType LHS, CallType RHS) { 127 return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS)); 128 } 129 130 struct ForwardingCallObject { 131 struct State { 132 CallType last_call_type = CT_None; 133 TypeID const& (*last_call_args)() = nullptr; 134 135 template <class ...Args> set_callForwardingCallObject::State136 constexpr void set_call(CallType type) { 137 assert(last_call_type == CT_None); 138 assert(last_call_args == nullptr); 139 last_call_type = type; 140 last_call_args = &makeArgumentID<Args...>; 141 } 142 143 template <class ...Args> check_callForwardingCallObject::State144 constexpr bool check_call(CallType type) { 145 bool result = 146 last_call_type == type 147 && last_call_args 148 && *last_call_args == &makeArgumentID<Args...>; 149 last_call_type = CT_None; 150 last_call_args = nullptr; 151 return result; 152 } 153 }; 154 155 State *st_; 156 ForwardingCallObjectForwardingCallObject157 explicit constexpr ForwardingCallObject(State& st) : st_(&st) {} 158 159 template <class ...Args> operatorForwardingCallObject160 constexpr bool operator()(Args&&...) & { 161 st_->set_call<Args&&...>(CT_NonConst | CT_LValue); 162 return true; 163 } 164 165 template <class ...Args> operatorForwardingCallObject166 constexpr bool operator()(Args&&...) const & { 167 st_->set_call<Args&&...>(CT_Const | CT_LValue); 168 return true; 169 } 170 171 // Don't allow the call operator to be invoked as an rvalue. 172 template <class ...Args> operatorForwardingCallObject173 constexpr bool operator()(Args&&...) && { 174 st_->set_call<Args&&...>(CT_NonConst | CT_RValue); 175 return true; 176 } 177 178 template <class ...Args> operatorForwardingCallObject179 constexpr bool operator()(Args&&...) const && { 180 st_->set_call<Args&&...>(CT_Const | CT_RValue); 181 return true; 182 } 183 }; 184 185 186 #endif // TEST_CALLABLE_TYPES_H 187