Home | History | Annotate | Download | only in func.require
      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 #ifndef INVOKE_HELPERS_H
     11 #define INVOKE_HELPERS_H
     12 
     13 #include <type_traits>
     14 #include <cassert>
     15 #include <functional>
     16 
     17 #include "test_macros.h"
     18 
     19 template <int I>
     20 struct Int : public std::integral_constant<int, I> {};
     21 
     22 template <bool P>
     23 struct Bool : public std::integral_constant<bool, P> {};
     24 
     25 struct Q_None {
     26     template <class T>
     27     struct apply { typedef T type; };
     28 };
     29 
     30 struct Q_Const {
     31     template <class T>
     32     struct apply { typedef T const type; };
     33 };
     34 
     35 struct Q_Volatile {
     36     template <class T>
     37     struct apply { typedef T volatile type; };
     38 };
     39 
     40 struct Q_CV {
     41     template <class T>
     42     struct apply { typedef T const volatile type; };
     43 };
     44 
     45 // Caster - A functor object that performs cv-qualifier and value category
     46 //   conversions.
     47 //   QualTag - A metafunction type that applies cv-qualifiers to its argument.
     48 //   RValue - True if the resulting object should be an RValue reference.
     49 //            False otherwise.
     50 template <class QualTag, bool RValue = false>
     51 struct Caster {
     52     template <class T>
     53     struct apply {
     54         typedef typename std::remove_reference<T>::type RawType;
     55         typedef typename QualTag::template apply<RawType>::type CVType;
     56 #if TEST_STD_VER >= 11
     57         typedef typename std::conditional<RValue,
     58             CVType&&, CVType&
     59         >::type type;
     60 #else
     61         typedef CVType& type;
     62 #endif
     63     };
     64 
     65     template <class T>
     66     typename apply<T>::type
     67     operator()(T& obj) const {
     68         typedef typename apply<T>::type OutType;
     69         return static_cast<OutType>(obj);
     70     }
     71 };
     72 
     73 typedef Caster<Q_None>           LValueCaster;
     74 typedef Caster<Q_Const>          ConstCaster;
     75 typedef Caster<Q_Volatile>       VolatileCaster;
     76 typedef Caster<Q_CV>             CVCaster;
     77 typedef Caster<Q_None,     true> MoveCaster;
     78 typedef Caster<Q_Const,    true> MoveConstCaster;
     79 typedef Caster<Q_Volatile, true> MoveVolatileCaster;
     80 typedef Caster<Q_CV,       true> MoveCVCaster;
     81 
     82 
     83 template <class Tp>
     84 Tp const& makeConst(Tp& ref) { return ref; }
     85 
     86 template <class Tp>
     87 Tp const* makeConst(Tp* ptr) { return ptr; }
     88 
     89 template <class Tp>
     90 std::reference_wrapper<const Tp> makeConst(std::reference_wrapper<Tp>& ref) {
     91     return std::reference_wrapper<const Tp>(ref.get());
     92 }
     93 
     94 template <class Tp>
     95 Tp volatile& makeVolatile(Tp& ref) { return ref; }
     96 
     97 template <class Tp>
     98 Tp volatile* makeVolatile(Tp* ptr) { return ptr; }
     99 
    100 template <class Tp>
    101 std::reference_wrapper<volatile Tp> makeVolatile(std::reference_wrapper<Tp>& ref) {
    102     return std::reference_wrapper<volatile Tp>(ref.get());
    103 }
    104 
    105 template <class Tp>
    106 Tp const volatile& makeCV(Tp& ref) { return ref; }
    107 
    108 template <class Tp>
    109 Tp const volatile* makeCV(Tp* ptr) { return ptr; }
    110 
    111 template <class Tp>
    112 std::reference_wrapper<const volatile Tp> makeCV(std::reference_wrapper<Tp>& ref) {
    113     return std::reference_wrapper<const volatile Tp>(ref.get());
    114 }
    115 
    116 // A shorter name for 'static_cast'
    117 template <class QualType, class Tp>
    118 QualType C_(Tp& v) { return static_cast<QualType>(v); };
    119 
    120 //==============================================================================
    121 // ArgType - A non-copyable type intended to be used as a dummy argument type
    122 //   to test functions.
    123 struct ArgType {
    124     int value;
    125     explicit ArgType(int val = 0) : value(val) {}
    126 private:
    127     ArgType(ArgType const&);
    128     ArgType& operator=(ArgType const&);
    129 };
    130 
    131 //==============================================================================
    132 // DerivedFromBase - A type that derives from its template argument 'Base'
    133 template <class Base>
    134 struct DerivedFromType : public Base {
    135     DerivedFromType() : Base() {}
    136     template <class Tp>
    137     explicit DerivedFromType(Tp const& t) : Base(t) {}
    138 };
    139 
    140 //==============================================================================
    141 // DerefToType - A type that dereferences to its template argument 'To'.
    142 //   The cv-ref qualifiers of the 'DerefToType' object do not propagate
    143 //   to the resulting 'To' object.
    144 template <class To>
    145 struct DerefToType {
    146     To object;
    147 
    148     DerefToType() {}
    149 
    150     template <class Up>
    151     explicit DerefToType(Up const& val) : object(val) {}
    152 
    153     To& operator*() const volatile { return const_cast<To&>(object); }
    154 };
    155 
    156 //==============================================================================
    157 // DerefPropToType - A type that dereferences to its template argument 'To'.
    158 //   The cv-ref qualifiers of the 'DerefPropToType' object propagate
    159 //   to the resulting 'To' object.
    160 template <class To>
    161 struct DerefPropType {
    162     To object;
    163 
    164     DerefPropType() {}
    165 
    166     template <class Up>
    167     explicit DerefPropType(Up const& val) : object(val) {}
    168 
    169 #if TEST_STD_VER < 11
    170     To& operator*() { return object; }
    171     To const& operator*() const { return object; }
    172     To volatile& operator*() volatile  { return object; }
    173     To const volatile& operator*() const volatile { return object; }
    174 #else
    175     To& operator*() & { return object; }
    176     To const& operator*() const & { return object; }
    177     To volatile& operator*() volatile  & { return object; }
    178     To const volatile& operator*() const volatile & { return object; }
    179     To&& operator*() && { return static_cast<To &&>(object); }
    180     To const&& operator*() const && { return static_cast<To const&&>(object); }
    181     To volatile&& operator*() volatile  && { return static_cast<To volatile&&>(object); }
    182     To const volatile&& operator*() const volatile && { return static_cast<To const volatile&&>(object); }
    183 #endif
    184 };
    185 
    186 //==============================================================================
    187 // MethodID - A type that uniquely identifies a member function for a class.
    188 //   This type is used to communicate between the member functions being tested
    189 //   and the tests invoking them.
    190 // - Test methods should call 'setUncheckedCall()' whenever they are invoked.
    191 // - Tests consume the unchecked call using checkCall(<return-value>)` to assert
    192 //   that the method has been called and that the return value of `__invoke`
    193 //   matches what the method actually returned.
    194 template <class T>
    195 struct MethodID {
    196     typedef void* IDType;
    197 
    198     static int dummy; // A dummy memory location.
    199     static void* id; // The "ID" is the value of this pointer.
    200     static bool unchecked_call; // Has a call happened that has not been checked.
    201 
    202     static void*& setUncheckedCall() {
    203         assert(unchecked_call == false);
    204         unchecked_call = true;
    205         return id;
    206     }
    207 
    208     static bool checkCalled(void*& return_value) {
    209         bool old = unchecked_call;
    210         unchecked_call = false;
    211         return old && id == return_value && &id == &return_value;
    212     }
    213 };
    214 
    215 template <class T> int   MethodID<T>::dummy = 0;
    216 template <class T> void* MethodID<T>::id = (void*)&MethodID<T>::dummy;
    217 template <class T> bool  MethodID<T>::unchecked_call = false;
    218 
    219 
    220 //==============================================================================
    221 // FunctionPtrID - Like MethodID but for free function pointers.
    222 template <class T, T*>
    223 struct FunctionPtrID {
    224     static int dummy; // A dummy memory location.
    225     static void* id; // The "ID" is the value of this pointer.
    226     static bool unchecked_call; // Has a call happened that has not been checked.
    227 
    228     static void*& setUncheckedCall() {
    229         assert(unchecked_call == false);
    230         unchecked_call = true;
    231         return id;
    232     }
    233 
    234     static bool checkCalled(void*& return_value) {
    235         bool old = unchecked_call;
    236         unchecked_call = false;
    237         return old && id == return_value && &id == &return_value;
    238     }
    239 };
    240 
    241 template <class T, T* Ptr> int   FunctionPtrID<T, Ptr>::dummy = 0;
    242 template <class T, T* Ptr> void* FunctionPtrID<T, Ptr>::id = (void*)&FunctionPtrID<T, Ptr>::dummy;
    243 template <class T, T* Ptr> bool  FunctionPtrID<T, Ptr>::unchecked_call = false;
    244 
    245 //==============================================================================
    246 // BasicTest - The basic test structure for everything except
    247 // member object pointers.
    248 // ID - The "Function Identifier" type used either MethodID or FunctionPtrID.
    249 // Arity - The Arity of the call signature.
    250 // ObjectCaster - The object transformation functor type.
    251 // ArgCaster - The extra argument transformation functor type.
    252 template <class ID, int Arity, class ObjectCaster = LValueCaster,
    253                                class ArgCaster    = LValueCaster>
    254 struct BasicTest {
    255     template <class ObjectT>
    256     void runTest(ObjectT& object) {
    257         Int<Arity> A;
    258         runTestImp(A, object);
    259     }
    260 
    261     template <class MethodPtr, class ObjectT>
    262     void runTest(MethodPtr ptr, ObjectT& object) {
    263         Int<Arity> A;
    264         runTestImp(A, ptr, object);
    265     }
    266 
    267 private:
    268     typedef void*& CallRet;
    269     ObjectCaster object_cast;
    270     ArgCaster arg_cast;
    271     ArgType a0, a1, a2;
    272 
    273     //==========================================================================
    274     //                       BULLET 1, 2 AND 3 TEST METHODS
    275     //==========================================================================
    276     template <class MethodPtr, class ObjectT>
    277     void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {
    278         {
    279             static_assert((std::is_same<
    280                 decltype(std::__invoke(ptr, object_cast(object)))
    281               , CallRet>::value), "");
    282             assert(ID::unchecked_call == false);
    283             CallRet ret = std::__invoke(ptr, object_cast(object));
    284             assert(ID::checkCalled(ret));
    285         }
    286 #if TEST_STD_VER >= 11
    287         {
    288             static_assert((std::is_same<
    289                 decltype(std::__invoke_constexpr(ptr, object_cast(object)))
    290               , CallRet>::value), "");
    291             assert(ID::unchecked_call == false);
    292             CallRet ret = std::__invoke_constexpr(ptr, object_cast(object));
    293             assert(ID::checkCalled(ret));
    294         }
    295 #endif
    296     }
    297 
    298     template <class MethodPtr, class ObjectT>
    299     void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {
    300         {
    301             static_assert((std::is_same<
    302                 decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
    303               , CallRet>::value), "");
    304             assert(ID::unchecked_call == false);
    305             CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
    306             assert(ID::checkCalled(ret));
    307         }
    308 #if TEST_STD_VER >= 11
    309         {
    310             static_assert((std::is_same<
    311                 decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0)))
    312               , CallRet>::value), "");
    313             assert(ID::unchecked_call == false);
    314             CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0));
    315             assert(ID::checkCalled(ret));
    316         }
    317 #endif
    318     }
    319 
    320     template <class MethodPtr, class ObjectT>
    321     void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {
    322         {
    323             static_assert((std::is_same<
    324                 decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
    325               , CallRet>::value), "");
    326             assert(ID::unchecked_call == false);
    327             CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
    328             assert(ID::checkCalled(ret));
    329         }
    330 #if TEST_STD_VER >= 11
    331         {
    332             static_assert((std::is_same<
    333                 decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
    334               , CallRet>::value), "");
    335             assert(ID::unchecked_call == false);
    336             CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
    337             assert(ID::checkCalled(ret));
    338         }
    339 #endif
    340     }
    341 
    342     template <class MethodPtr, class ObjectT>
    343     void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {
    344         {
    345             static_assert((std::is_same<
    346                 decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
    347               , CallRet>::value), "");
    348             assert(ID::unchecked_call == false);
    349             CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
    350             assert(ID::checkCalled(ret));
    351         }
    352 #if TEST_STD_VER >= 11
    353         {
    354             static_assert((std::is_same<
    355                 decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
    356               , CallRet>::value), "");
    357             assert(ID::unchecked_call == false);
    358             CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
    359             assert(ID::checkCalled(ret));
    360         }
    361 #endif
    362     }
    363 
    364     //==========================================================================
    365     //                       BULLET 7 TEST METHODS
    366     //==========================================================================
    367     template <class ObjectT>
    368     void runTestImp(Int<0>, ObjectT& object) {
    369         {
    370             static_assert((std::is_same<
    371                 decltype(std::__invoke(object_cast(object)))
    372               , CallRet>::value), "");
    373             assert(ID::unchecked_call == false);
    374             CallRet ret = std::__invoke(object_cast(object));
    375             assert(ID::checkCalled(ret));
    376         }
    377 #if TEST_STD_VER >= 11
    378         {
    379             static_assert((std::is_same<
    380                 decltype(std::__invoke_constexpr(object_cast(object)))
    381               , CallRet>::value), "");
    382             assert(ID::unchecked_call == false);
    383             CallRet ret = std::__invoke_constexpr(object_cast(object));
    384             assert(ID::checkCalled(ret));
    385         }
    386 #endif
    387     }
    388 
    389     template <class ObjectT>
    390     void runTestImp(Int<1>, ObjectT& object) {
    391         {
    392             static_assert((std::is_same<
    393                 decltype(std::__invoke(object_cast(object), arg_cast(a0)))
    394               , CallRet>::value), "");
    395             assert(ID::unchecked_call == false);
    396             CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
    397             assert(ID::checkCalled(ret));
    398         }
    399 #if TEST_STD_VER >= 11
    400         {
    401             static_assert((std::is_same<
    402                 decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0)))
    403               , CallRet>::value), "");
    404             assert(ID::unchecked_call == false);
    405             CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0));
    406             assert(ID::checkCalled(ret));
    407         }
    408 #endif
    409     }
    410 
    411     template <class ObjectT>
    412     void runTestImp(Int<2>, ObjectT& object) {
    413         {
    414             static_assert((std::is_same<
    415                 decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
    416               , CallRet>::value), "");
    417             assert(ID::unchecked_call == false);
    418             CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
    419             assert(ID::checkCalled(ret));
    420         }
    421 #if TEST_STD_VER >= 11
    422         {
    423             static_assert((std::is_same<
    424                 decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1)))
    425               , CallRet>::value), "");
    426             assert(ID::unchecked_call == false);
    427             CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1));
    428             assert(ID::checkCalled(ret));
    429         }
    430 #endif
    431     }
    432 
    433     template <class ObjectT>
    434     void runTestImp(Int<3>, ObjectT& object) {
    435         {
    436             static_assert((std::is_same<
    437                 decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
    438               , CallRet>::value), "");
    439             assert(ID::unchecked_call == false);
    440             CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
    441             assert(ID::checkCalled(ret));
    442         }
    443 #if TEST_STD_VER >= 11
    444         {
    445             static_assert((std::is_same<
    446                 decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
    447               , CallRet>::value), "");
    448             assert(ID::unchecked_call == false);
    449             CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
    450             assert(ID::checkCalled(ret));
    451         }
    452 #endif
    453     }
    454 };
    455 
    456 #endif // INVOKE_HELPERS_H
    457