File indexing completed on 2024-09-22 04:53:11

0001 #ifndef __MOCKITOPP_PROXY_VFUNCTION_HPP__
0002 #define __MOCKITOPP_PROXY_VFUNCTION_HPP__
0003 
0004 #include <mockitopp/detail/stubbing/dynamic_vfunction.hpp>
0005 #include <mockitopp/detail/util/horrible_cast.hpp>
0006 #include <mockitopp/detail/util/remove_member_function_pointer_cv.hpp>
0007 
0008 include(`mockitopp/detail/m4/ENUM_BINARY_PARAMS.m4')dnl
0009 include(`mockitopp/detail/m4/ENUM_PARAMS.m4')dnl
0010 include(`mockitopp/detail/m4/ENUM_TRAILING_PARAMS.m4')dnl
0011 include(`mockitopp/detail/m4/REPEAT.m4')dnl
0012 namespace mockitopp
0013 {
0014    namespace detail
0015    {
0016       template <int OFFSET, typename T> struct proxy_vfunction;
0017 
0018 define(`DEFINE_PROXY_VFUNCTION',
0019 `     template <int OFFSET, typename R, typename C M4_ENUM_TRAILING_PARAMS($1, typename A)>
0020       struct proxy_vfunction<OFFSET, R (C::*)(M4_ENUM_PARAMS($1, A))>
0021       {
0022          void* __PAD_FOR_MOCK_vptr;
0023          dynamic_vfunction<R (C::*)(M4_ENUM_PARAMS($1, A))>*
0024             __PAD_FOR_MOCK_spys[MOCKITOPP_MAX_VIRTUAL_FUNCTIONS];
0025 
0026          R invoke(M4_ENUM_BINARY_PARAMS($1, A, a))
0027             { return __PAD_FOR_MOCK_spys[OFFSET]->invoke(M4_ENUM_PARAMS($1, a)); }
0028       };
0029 
0030 ')dnl
0031 dnl add one to max arity so we generate 0 argument case
0032 M4_REPEAT(eval(MOCKITOPP_MAX_VIRTUAL_FUNCTION_ARITY + 1), `DEFINE_PROXY_VFUNCTION')dnl
0033 
0034       template <typename M>
0035       struct proxy_vfunction_factory
0036       {
0037          static void* get(M ptr2member)
0038          {
0039             proxy_vfunction_factory s;
0040 #pragma GCC diagnostic push
0041 #pragma GCC diagnostic ignored "-Wcast-function-type"
0042             return (s.*reinterpret_cast<void* (proxy_vfunction_factory::*)()>(ptr2member))();
0043 #pragma GCC diagnostic pop
0044          }
0045 
0046 define(`DEFINE_PROXY_VFUNCTION_FACTORY_OFFSET_FUNCTION', `        virtual void* offset$1() { return horrible_cast<void*>(&proxy_vfunction<$1, typename remove_member_function_pointer_cv<M>::type>::invoke); }
0047 ')dnl
0048 M4_REPEAT(MOCKITOPP_MAX_VIRTUAL_FUNCTIONS, `DEFINE_PROXY_VFUNCTION_FACTORY_OFFSET_FUNCTION')dnl
0049 
0050          virtual ~proxy_vfunction_factory() {}
0051       };
0052    } // namespace detail
0053 } // namespace mockitopp
0054 
0055 #endif //__MOCKITOPP_PROXY_VFUNCTION_HPP__