brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.1 KiB · bebb9f4 Raw
359 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef INVOKE_HELPERS_H10#define INVOKE_HELPERS_H11 12#include <type_traits>13#include <cassert>14#include <functional>15 16#include "test_macros.h"17 18template <int I>19struct Int : public std::integral_constant<int, I> {};20 21template <bool P>22struct Bool : public std::integral_constant<bool, P> {};23 24struct Q_None {25    template <class T>26    struct apply { typedef T type; };27};28 29struct Q_Const {30    template <class T>31    struct apply { typedef T const type; };32};33 34struct Q_Volatile {35    template <class T>36    struct apply { typedef T volatile type; };37};38 39struct Q_CV {40    template <class T>41    struct apply { typedef T const volatile type; };42};43 44// Caster - A functor object that performs cv-qualifier and value category45//   conversions.46//   QualTag - A metafunction type that applies cv-qualifiers to its argument.47//   RValue - True if the resulting object should be an RValue reference.48//            False otherwise.49template <class QualTag, bool RValue = false>50struct Caster {51    template <class T>52    struct apply {53        typedef typename std::remove_reference<T>::type RawType;54        typedef typename QualTag::template apply<RawType>::type CVType;55        typedef CVType& type;56    };57 58    template <class T>59    typename apply<T>::type60    operator()(T& obj) const {61        typedef typename apply<T>::type OutType;62        return static_cast<OutType>(obj);63    }64};65 66typedef Caster<Q_None>           LValueCaster;67typedef Caster<Q_Const>          ConstCaster;68typedef Caster<Q_Volatile>       VolatileCaster;69typedef Caster<Q_CV>             CVCaster;70typedef Caster<Q_None,     true> MoveCaster;71typedef Caster<Q_Const,    true> MoveConstCaster;72typedef Caster<Q_Volatile, true> MoveVolatileCaster;73typedef Caster<Q_CV,       true> MoveCVCaster;74 75 76template <class Tp>77Tp const& makeConst(Tp& ref) { return ref; }78 79template <class Tp>80Tp const* makeConst(Tp* ptr) { return ptr; }81 82template <class Tp>83std::reference_wrapper<const Tp> makeConst(std::reference_wrapper<Tp>& ref) {84    return std::reference_wrapper<const Tp>(ref.get());85}86 87template <class Tp>88Tp volatile& makeVolatile(Tp& ref) { return ref; }89 90template <class Tp>91Tp volatile* makeVolatile(Tp* ptr) { return ptr; }92 93template <class Tp>94std::reference_wrapper<volatile Tp> makeVolatile(std::reference_wrapper<Tp>& ref) {95    return std::reference_wrapper<volatile Tp>(ref.get());96}97 98template <class Tp>99Tp const volatile& makeCV(Tp& ref) { return ref; }100 101template <class Tp>102Tp const volatile* makeCV(Tp* ptr) { return ptr; }103 104template <class Tp>105std::reference_wrapper<const volatile Tp> makeCV(std::reference_wrapper<Tp>& ref) {106    return std::reference_wrapper<const volatile Tp>(ref.get());107}108 109// A shorter name for 'static_cast'110template <class QualType, class Tp>111QualType C_(Tp& v) { return static_cast<QualType>(v); };112 113//==============================================================================114// ArgType - A non-copyable type intended to be used as a dummy argument type115//   to test functions.116struct ArgType {117    int value;118    explicit ArgType(int val = 0) : value(val) {}119private:120    ArgType(ArgType const&);121    ArgType& operator=(ArgType const&);122};123 124//==============================================================================125// DerivedFromBase - A type that derives from its template argument 'Base'126template <class Base>127struct DerivedFromType : public Base {128    DerivedFromType() : Base() {}129    template <class Tp>130    explicit DerivedFromType(Tp const& t) : Base(t) {}131};132 133//==============================================================================134// DerefToType - A type that dereferences to its template argument 'To'.135//   The cv-ref qualifiers of the 'DerefToType' object do not propagate136//   to the resulting 'To' object.137template <class To>138struct DerefToType {139    To object;140 141    DerefToType() {}142 143    template <class Up>144    explicit DerefToType(Up const& val) : object(val) {}145 146    To& operator*() const volatile { return const_cast<To&>(object); }147};148 149//==============================================================================150// DerefPropToType - A type that dereferences to its template argument 'To'.151//   The cv-ref qualifiers of the 'DerefPropToType' object propagate152//   to the resulting 'To' object.153template <class To>154struct DerefPropType {155    To object;156 157    DerefPropType() {}158 159    template <class Up>160    explicit DerefPropType(Up const& val) : object(val) {}161 162    To& operator*() { return object; }163    To const& operator*() const { return object; }164    To volatile& operator*() volatile  { return object; }165    To const volatile& operator*() const volatile { return object; }166};167 168//==============================================================================169// MethodID - A type that uniquely identifies a member function for a class.170//   This type is used to communicate between the member functions being tested171//   and the tests invoking them.172// - Test methods should call 'setUncheckedCall()' whenever they are invoked.173// - Tests consume the unchecked call using checkCall(<return-value>)` to assert174//   that the method has been called and that the return value of `__invoke`175//   matches what the method actually returned.176template <class T>177struct MethodID {178    typedef void* IDType;179 180    static int dummy; // A dummy memory location.181    static void* id; // The "ID" is the value of this pointer.182    static bool unchecked_call; // Has a call happened that has not been checked.183 184    static void*& setUncheckedCall() {185        assert(unchecked_call == false);186        unchecked_call = true;187        return id;188    }189 190    static bool checkCalled(void*& return_value) {191        bool old = unchecked_call;192        unchecked_call = false;193        return old && id == return_value && &id == &return_value;194    }195};196 197template <class T> int   MethodID<T>::dummy = 0;198template <class T> void* MethodID<T>::id = (void*)&MethodID<T>::dummy;199template <class T> bool  MethodID<T>::unchecked_call = false;200 201 202//==============================================================================203// FunctionPtrID - Like MethodID but for free function pointers.204template <class T, T*>205struct FunctionPtrID {206    static int dummy; // A dummy memory location.207    static void* id; // The "ID" is the value of this pointer.208    static bool unchecked_call; // Has a call happened that has not been checked.209 210    static void*& setUncheckedCall() {211        assert(unchecked_call == false);212        unchecked_call = true;213        return id;214    }215 216    static bool checkCalled(void*& return_value) {217        bool old = unchecked_call;218        unchecked_call = false;219        return old && id == return_value && &id == &return_value;220    }221};222 223template <class T, T* Ptr> int   FunctionPtrID<T, Ptr>::dummy = 0;224template <class T, T* Ptr> void* FunctionPtrID<T, Ptr>::id = (void*)&FunctionPtrID<T, Ptr>::dummy;225template <class T, T* Ptr> bool  FunctionPtrID<T, Ptr>::unchecked_call = false;226 227//==============================================================================228// BasicTest - The basic test structure for everything except229// member object pointers.230// ID - The "Function Identifier" type used either MethodID or FunctionPtrID.231// Arity - The Arity of the call signature.232// ObjectCaster - The object transformation functor type.233// ArgCaster - The extra argument transformation functor type.234template <class ID, int Arity, class ObjectCaster = LValueCaster,235                               class ArgCaster    = LValueCaster>236struct BasicTest {237    template <class ObjectT>238    void runTest(ObjectT& object) {239        Int<Arity> A;240        runTestImp(A, object);241    }242 243    template <class MethodPtr, class ObjectT>244    void runTest(MethodPtr ptr, ObjectT& object) {245        Int<Arity> A;246        runTestImp(A, ptr, object);247    }248 249private:250    typedef void*& CallRet;251    ObjectCaster object_cast;252    ArgCaster arg_cast;253    ArgType a0, a1, a2;254 255    //==========================================================================256    //                       BULLET 1, 2 AND 3 TEST METHODS257    //==========================================================================258    template <class MethodPtr, class ObjectT>259    void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {260        {261            static_assert((std::is_same<262                decltype(std::__invoke(ptr, object_cast(object)))263              , CallRet>::value), "");264            assert(ID::unchecked_call == false);265            CallRet ret = std::__invoke(ptr, object_cast(object));266            assert(ID::checkCalled(ret));267        }268    }269 270    template <class MethodPtr, class ObjectT>271    void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {272        {273            static_assert((std::is_same<274                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))275              , CallRet>::value), "");276            assert(ID::unchecked_call == false);277            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));278            assert(ID::checkCalled(ret));279        }280    }281 282    template <class MethodPtr, class ObjectT>283    void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {284        {285            static_assert((std::is_same<286                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))287              , CallRet>::value), "");288            assert(ID::unchecked_call == false);289            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));290            assert(ID::checkCalled(ret));291        }292    }293 294    template <class MethodPtr, class ObjectT>295    void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {296        {297            static_assert((std::is_same<298                decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))299              , CallRet>::value), "");300            assert(ID::unchecked_call == false);301            CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));302            assert(ID::checkCalled(ret));303        }304    }305 306    //==========================================================================307    //                       BULLET 7 TEST METHODS308    //==========================================================================309    template <class ObjectT>310    void runTestImp(Int<0>, ObjectT& object) {311        {312            static_assert((std::is_same<313                decltype(std::__invoke(object_cast(object)))314              , CallRet>::value), "");315            assert(ID::unchecked_call == false);316            CallRet ret = std::__invoke(object_cast(object));317            assert(ID::checkCalled(ret));318        }319    }320 321    template <class ObjectT>322    void runTestImp(Int<1>, ObjectT& object) {323        {324            static_assert((std::is_same<325                decltype(std::__invoke(object_cast(object), arg_cast(a0)))326              , CallRet>::value), "");327            assert(ID::unchecked_call == false);328            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));329            assert(ID::checkCalled(ret));330        }331    }332 333    template <class ObjectT>334    void runTestImp(Int<2>, ObjectT& object) {335        {336            static_assert((std::is_same<337                decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))338              , CallRet>::value), "");339            assert(ID::unchecked_call == false);340            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));341            assert(ID::checkCalled(ret));342        }343    }344 345    template <class ObjectT>346    void runTestImp(Int<3>, ObjectT& object) {347        {348            static_assert((std::is_same<349                decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))350              , CallRet>::value), "");351            assert(ID::unchecked_call == false);352            CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));353            assert(ID::checkCalled(ret));354        }355    }356};357 358#endif // INVOKE_HELPERS_H359