From 522b1d14efe523b983eea899ab07524b27d14ff7 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 28 Jul 2015 01:25:36 +0000 Subject: Checking more __invoke tests. Before I start trying to fix __invoke in C++03 it needs better test coverage. This patch adds a large amount of tests for __invoke. llvm-svn: 243366 --- .../function.objects/func.require/invoke_helpers.h | 317 +++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h (limited to 'libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h') diff --git a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h new file mode 100644 index 00000000000..0583b624da3 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h @@ -0,0 +1,317 @@ +#ifndef INVOKE_HELPERS_H +#define INVOKE_HELPERS_H + +#include +#include +#include + +#include "test_macros.h" + +template +struct Int : public std::integral_constant {}; + +template +struct Bool : public std::integral_constant {}; + +struct Q_None { + template + struct apply { typedef T type; }; +}; + +struct Q_Const { + template + struct apply { typedef T const type; }; +}; + +struct Q_Volatile { + template + struct apply { typedef T volatile type; }; +}; + +struct Q_CV { + template + struct apply { typedef T const volatile type; }; +}; + +// Caster - A functor object that performs cv-qualifier and value category +// conversions. +// QualTag - A metafunction type that applies cv-qualifiers to its argument. +// RValue - True if the resulting object should be an RValue reference. +// False otherwise. +template +struct Caster { + template + struct apply { + typedef typename std::remove_reference::type RawType; + typedef typename QualTag::template apply::type CVType; +#if TEST_STD_VER >= 11 + typedef typename std::conditional::type type; +#else + typedef CVType& type; +#endif + }; + + template + typename apply::type + operator()(T& obj) const { + typedef typename apply::type OutType; + return static_cast(obj); + } +}; + +typedef Caster LValueCaster; +typedef Caster ConstCaster; +typedef Caster VolatileCaster; +typedef Caster CVCaster; +typedef Caster MoveCaster; +typedef Caster MoveConstCaster; +typedef Caster MoveVolatileCaster; +typedef Caster MoveCVCaster; + +// A shorter name for 'static_cast' +template +QualType C_(Tp& v) { return static_cast(v); }; + +//============================================================================== +// ArgType - A non-copyable type intended to be used as a dummy argument type +// to test functions. +struct ArgType { + int value; + explicit ArgType(int val = 0) : value(val) {} +private: + ArgType(ArgType const&); + ArgType& operator=(ArgType const&); +}; + +//============================================================================== +// DerivedFromBase - A type that derives from it's template argument 'Base' +template +struct DerivedFromType : public Base { + DerivedFromType() : Base() {} + template + explicit DerivedFromType(Tp const& t) : Base(t) {} +}; + +//============================================================================== +// DerefToType - A type that dereferences to it's template argument 'To'. +// The cv-ref qualifiers of the 'DerefToType' object do not propagate +// to the resulting 'To' object. +template +struct DerefToType { + To object; + + DerefToType() {} + + template + explicit DerefToType(Up const& val) : object(val) {} + + To& operator*() const volatile { return const_cast(object); } +}; + +//============================================================================== +// DerefPropToType - A type that dereferences to it's template argument 'To'. +// The cv-ref qualifiers of the 'DerefPropToType' object propagate +// to the resulting 'To' object. +template +struct DerefPropType { + To object; + + DerefPropType() {} + + template + explicit DerefPropType(Up const& val) : object(val) {} + +#if TEST_STD_VER < 11 + To& operator*() { return object; } + To const& operator*() const { return object; } + To volatile& operator*() volatile { return object; } + To const volatile& operator*() const volatile { return object; } +#else + To& operator*() & { return object; } + To const& operator*() const & { return object; } + To volatile& operator*() volatile & { return object; } + To const volatile& operator*() const volatile & { return object; } + To&& operator*() && { return static_cast(object); } + To const&& operator*() const && { return static_cast(object); } + To volatile&& operator*() volatile && { return static_cast(object); } + To const volatile&& operator*() const volatile && { return static_cast(object); } +#endif +}; + +//============================================================================== +// MethodID - A type that uniquely identifies a member function for a class. +// This type is used to communicate between the member functions being tested +// and the tests invoking them. +// - Test methods should call 'setUncheckedCall()' whenever they are invoked. +// - Tests consume the unchecked call using checkCall()` to assert +// that the method has been called and that the return value of `__invoke` +// matches what the method actually returned. +template +struct MethodID { + typedef void* IDType; + + static int dummy; // A dummy memory location. + static void* id; // The "ID" is the value of this pointer. + static bool unchecked_call; // Has a call happened that has not been checked. + + static void*& setUncheckedCall() { + assert(unchecked_call == false); + unchecked_call = true; + return id; + } + + static bool checkCalled(void*& return_value) { + bool old = unchecked_call; + unchecked_call = false; + return old && id == return_value && &id == &return_value; + } +}; + +template int MethodID::dummy = 0; +template void* MethodID::id = (void*)&MethodID::dummy; +template bool MethodID::unchecked_call = false; + + +//============================================================================== +// FunctionPtrID - Like MethodID but for free function pointers. +template +struct FunctionPtrID { + static int dummy; // A dummy memory location. + static void* id; // The "ID" is the value of this pointer. + static bool unchecked_call; // Has a call happened that has not been checked. + + static void*& setUncheckedCall() { + assert(unchecked_call == false); + unchecked_call = true; + return id; + } + + static bool checkCalled(void*& return_value) { + bool old = unchecked_call; + unchecked_call = false; + return old && id == return_value && &id == &return_value; + } +}; + +template int FunctionPtrID::dummy = 0; +template void* FunctionPtrID::id = (void*)&FunctionPtrID::dummy; +template bool FunctionPtrID::unchecked_call = false; + +//============================================================================== +// BasicTest - The basic test structure for everything except +// member object pointers. +// ID - The "Function Identifier" type used either MethodID or FunctionPtrID. +// Arity - The Arity of the call signature. +// ObjectCaster - The object transformation functor type. +// ArgCaster - The extra argument transformation functor type. +template +struct BasicTest { + template + void runTest(ObjectT& object) { + Int A; + runTestImp(A, object); + } + + template + void runTest(MethodPtr ptr, ObjectT& object) { + Int A; + runTestImp(A, ptr, object); + } + +private: + typedef void*& CallRet; + ObjectCaster object_cast; + ArgCaster arg_cast; + ArgType a0, a1, a2; + + //========================================================================== + // BULLET 1 AND 2 TEST METHODS + //========================================================================== + template + void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(ptr, object_cast(object))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(ptr, object_cast(object)); + assert(ID::checkCalled(ret)); + } + + template + void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0)); + assert(ID::checkCalled(ret)); + } + + template + void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)); + assert(ID::checkCalled(ret)); + } + + template + void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); + assert(ID::checkCalled(ret)); + } + + //========================================================================== + // BULLET 5 TEST METHODS + //========================================================================== + template + void runTestImp(Int<0>, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(object_cast(object))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(object_cast(object)); + assert(ID::checkCalled(ret)); + } + + template + void runTestImp(Int<1>, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(object_cast(object), arg_cast(a0))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(object_cast(object), arg_cast(a0)); + assert(ID::checkCalled(ret)); + } + + template + void runTestImp(Int<2>, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)); + assert(ID::checkCalled(ret)); + } + + template + void runTestImp(Int<3>, ObjectT& object) { + static_assert((std::is_same< + decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) + , CallRet>::value), ""); + assert(ID::unchecked_call == false); + CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); + assert(ID::checkCalled(ret)); + } +}; + +#endif // INVOKE_HELPERS_H -- cgit v1.2.3