| //===----------------------------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef TEST_CALLABLE_TYPES_H |
| #define TEST_CALLABLE_TYPES_H |
| |
| #include "test_macros.h" |
| #include "type_id.h" |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // CALLABLE TEST TYPES |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| constexpr bool returns_true() { return true; } |
| |
| template <class Ret = bool> |
| struct MoveOnlyCallable { |
| MoveOnlyCallable(MoveOnlyCallable const&) = delete; |
| constexpr MoveOnlyCallable(MoveOnlyCallable&& other) |
| : value(other.value) |
| { other.value = !other.value; } |
| |
| template <class ...Args> |
| constexpr Ret operator()(Args&&...) { return Ret{value}; } |
| |
| constexpr explicit MoveOnlyCallable(bool x) : value(x) {} |
| Ret value; |
| }; |
| |
| template <class Ret = bool> |
| struct CopyCallable { |
| constexpr CopyCallable(CopyCallable const& other) |
| : value(other.value) {} |
| |
| constexpr CopyCallable(CopyCallable&& other) |
| : value(other.value) { other.value = !other.value; } |
| |
| template <class ...Args> |
| constexpr Ret operator()(Args&&...) { return Ret{value}; } |
| |
| constexpr explicit CopyCallable(bool x) : value(x) {} |
| Ret value; |
| }; |
| |
| |
| template <class Ret = bool> |
| struct ConstCallable { |
| constexpr ConstCallable(ConstCallable const& other) |
| : value(other.value) {} |
| |
| constexpr ConstCallable(ConstCallable&& other) |
| : value(other.value) { other.value = !other.value; } |
| |
| template <class ...Args> |
| constexpr Ret operator()(Args&&...) const { return Ret{value}; } |
| |
| constexpr explicit ConstCallable(bool x) : value(x) {} |
| Ret value; |
| }; |
| |
| |
| |
| template <class Ret = bool> |
| struct NoExceptCallable { |
| constexpr NoExceptCallable(NoExceptCallable const& other) |
| : value(other.value) {} |
| |
| template <class ...Args> |
| constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } |
| |
| template <class ...Args> |
| constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; } |
| |
| constexpr explicit NoExceptCallable(bool x) : value(x) {} |
| Ret value; |
| }; |
| |
| struct CopyAssignableWrapper { |
| constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default; |
| constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default; |
| constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; |
| constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; |
| |
| template <class ...Args> |
| constexpr bool operator()(Args&&...) { return value; } |
| |
| constexpr explicit CopyAssignableWrapper(bool x) : value(x) {} |
| bool value; |
| }; |
| |
| |
| struct MoveAssignableWrapper { |
| constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; |
| constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default; |
| constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; |
| constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; |
| |
| template <class ...Args> |
| constexpr bool operator()(Args&&...) { return value; } |
| |
| constexpr explicit MoveAssignableWrapper(bool x) : value(x) {} |
| bool value; |
| }; |
| |
| struct MemFunCallable { |
| constexpr explicit MemFunCallable(bool x) : value(x) {} |
| |
| constexpr bool return_value() const { return value; } |
| constexpr bool return_value_nc() { return value; } |
| bool value; |
| }; |
| |
| enum CallType : unsigned { |
| CT_None, |
| CT_NonConst = 1, |
| CT_Const = 2, |
| CT_LValue = 4, |
| CT_RValue = 8 |
| }; |
| |
| inline constexpr CallType operator|(CallType LHS, CallType RHS) { |
| return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS)); |
| } |
| |
| struct ForwardingCallObject { |
| struct State { |
| CallType last_call_type = CT_None; |
| TypeID const& (*last_call_args)() = nullptr; |
| |
| template <class ...Args> |
| constexpr void set_call(CallType type) { |
| assert(last_call_type == CT_None); |
| assert(last_call_args == nullptr); |
| last_call_type = type; |
| last_call_args = &makeArgumentID<Args...>; |
| } |
| |
| template <class ...Args> |
| constexpr bool check_call(CallType type) { |
| bool result = |
| last_call_type == type |
| && last_call_args |
| && *last_call_args == &makeArgumentID<Args...>; |
| last_call_type = CT_None; |
| last_call_args = nullptr; |
| return result; |
| } |
| }; |
| |
| State *st_; |
| |
| explicit constexpr ForwardingCallObject(State& st) : st_(&st) {} |
| |
| template <class ...Args> |
| constexpr bool operator()(Args&&...) & { |
| st_->set_call<Args&&...>(CT_NonConst | CT_LValue); |
| return true; |
| } |
| |
| template <class ...Args> |
| constexpr bool operator()(Args&&...) const & { |
| st_->set_call<Args&&...>(CT_Const | CT_LValue); |
| return true; |
| } |
| |
| // Don't allow the call operator to be invoked as an rvalue. |
| template <class ...Args> |
| constexpr bool operator()(Args&&...) && { |
| st_->set_call<Args&&...>(CT_NonConst | CT_RValue); |
| return true; |
| } |
| |
| template <class ...Args> |
| constexpr bool operator()(Args&&...) const && { |
| st_->set_call<Args&&...>(CT_Const | CT_RValue); |
| return true; |
| } |
| }; |
| |
| |
| #endif // TEST_CALLABLE_TYPES_H |