Merge pull request #9 from Lastique/fix_placement_new_warnings

Fix gcc 6 warnings about invoking placement new on a buffer of insufficient size.  Tested with gcc-6.1.0 on RHEL, seems okay.
This commit is contained in:
Noel Belcourt
2016-07-11 16:24:49 -06:00
committed by GitHub
2 changed files with 169 additions and 162 deletions

View File

@ -41,7 +41,7 @@
# pragma warning( push ) # pragma warning( push )
# pragma warning( disable : 4793 ) // complaint about native code generation # pragma warning( disable : 4793 ) // complaint about native code generation
# pragma warning( disable : 4127 ) // "conditional expression is constant" # pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif #endif
#if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
# define BOOST_FUNCTION_TARGET_FIX(x) x # define BOOST_FUNCTION_TARGET_FIX(x) x
@ -65,10 +65,11 @@ namespace boost {
* object pointers, and a structure that resembles a bound * object pointers, and a structure that resembles a bound
* member function pointer. * member function pointer.
*/ */
union function_buffer union function_buffer_members
{ {
// For pointers to function objects // For pointers to function objects
mutable void* obj_ptr; typedef void* obj_ptr_t;
mutable obj_ptr_t obj_ptr;
// For pointers to std::type_info objects // For pointers to std::type_info objects
struct type_t { struct type_t {
@ -82,7 +83,8 @@ namespace boost {
} type; } type;
// For function pointers of all kinds // For function pointers of all kinds
mutable void (*func_ptr)(); typedef void (*func_ptr_t)();
mutable func_ptr_t func_ptr;
// For bound member pointers // For bound member pointers
struct bound_memfunc_ptr_t { struct bound_memfunc_ptr_t {
@ -97,9 +99,15 @@ namespace boost {
bool is_const_qualified; bool is_const_qualified;
bool is_volatile_qualified; bool is_volatile_qualified;
} obj_ref; } obj_ref;
};
union function_buffer
{
// Type-specific union members
mutable function_buffer_members members;
// To relax aliasing constraints // To relax aliasing constraints
mutable char data; mutable char data[sizeof(function_buffer_members)];
}; };
/** /**
@ -166,42 +174,42 @@ namespace boost {
struct reference_manager struct reference_manager
{ {
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
switch (op) { switch (op) {
case clone_functor_tag: case clone_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref; out_buffer.members.obj_ref = in_buffer.members.obj_ref;
return; return;
case move_functor_tag: case move_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref; out_buffer.members.obj_ref = in_buffer.members.obj_ref;
in_buffer.obj_ref.obj_ptr = 0; in_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case destroy_functor_tag: case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0; out_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case check_functor_type_tag: case check_functor_type_tag:
{ {
// Check whether we have the same type. We can add // Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away. // cv-qualifiers, but we can't take them away.
if (*out_buffer.type.type == boost::typeindex::type_id<F>() if (*out_buffer.members.type.type == boost::typeindex::type_id<F>()
&& (!in_buffer.obj_ref.is_const_qualified && (!in_buffer.members.obj_ref.is_const_qualified
|| out_buffer.type.const_qualified) || out_buffer.members.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified && (!in_buffer.members.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified)) || out_buffer.members.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} }
return; return;
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<F>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info();
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified; out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified; out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
return; return;
} }
} }
@ -215,9 +223,9 @@ namespace boost {
struct function_allows_small_object_optimization struct function_allows_small_object_optimization
{ {
BOOST_STATIC_CONSTANT BOOST_STATIC_CONSTANT
(bool, (bool,
value = ((sizeof(F) <= sizeof(function_buffer) && value = ((sizeof(F) <= sizeof(function_buffer) &&
(alignment_of<function_buffer>::value (alignment_of<function_buffer>::value
% alignment_of<F>::value == 0)))); % alignment_of<F>::value == 0))));
}; };
@ -229,7 +237,7 @@ namespace boost {
A(a) A(a)
{ {
} }
functor_wrapper(const functor_wrapper& f) : functor_wrapper(const functor_wrapper& f) :
F(static_cast<const F&>(f)), F(static_cast<const F&>(f)),
A(static_cast<const A&>(f)) A(static_cast<const A&>(f))
@ -248,57 +256,57 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.members.func_ptr = in_buffer.members.func_ptr;
else if (op == move_functor_tag) { else if (op == move_functor_tag) {
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.members.func_ptr = in_buffer.members.func_ptr;
in_buffer.func_ptr = 0; in_buffer.members.func_ptr = 0;
} else if (op == destroy_functor_tag) } else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0; out_buffer.members.func_ptr = 0;
else if (op == check_functor_type_tag) { else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = &in_buffer.func_ptr; out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag || op == move_functor_tag) { if (op == clone_functor_tag || op == move_functor_tag) {
const functor_type* in_functor = const functor_type* in_functor =
reinterpret_cast<const functor_type*>(&in_buffer.data); reinterpret_cast<const functor_type*>(in_buffer.data);
new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor); new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
if (op == move_functor_tag) { if (op == move_functor_tag) {
functor_type* f = reinterpret_cast<functor_type*>(&in_buffer.data); functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); f->~Functor();
} }
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
functor_type* f = reinterpret_cast<functor_type*>(&out_buffer.data); functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); f->~Functor();
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = &in_buffer.data; out_buffer.members.obj_ptr = in_buffer.data;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
}; };
@ -311,7 +319,7 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag) functor_manager_operation_type op, function_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
@ -319,15 +327,15 @@ namespace boost {
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_) functor_manager_operation_type op, mpl::true_)
{ {
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
} }
// Function objects that require heap allocation // Function objects that require heap allocation
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_) functor_manager_operation_type op, mpl::false_)
{ {
if (op == clone_functor_tag) { if (op == clone_functor_tag) {
@ -337,27 +345,27 @@ namespace boost {
// jewillco: Changing this to static_cast because GCC 2.95.3 is // jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete. // obsolete.
const functor_type* f = const functor_type* f =
static_cast<const functor_type*>(in_buffer.obj_ptr); static_cast<const functor_type*>(in_buffer.members.obj_ptr);
functor_type* new_f = new functor_type(*f); functor_type* new_f = new functor_type(*f);
out_buffer.obj_ptr = new_f; out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.obj_ptr = 0; in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */ /* Cast from the void pointer to the functor pointer type */
functor_type* f = functor_type* f =
static_cast<functor_type*>(out_buffer.obj_ptr); static_cast<functor_type*>(out_buffer.members.obj_ptr);
delete f; delete f;
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -365,7 +373,7 @@ namespace boost {
// object can use the small-object optimization buffer or // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap. // whether we need to allocate it on the heap.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag) functor_manager_operation_type op, function_obj_tag)
{ {
manager(in_buffer, out_buffer, op, manager(in_buffer, out_buffer, op,
@ -374,7 +382,7 @@ namespace boost {
// For member pointers, we use the small-object optimization buffer. // For member pointers, we use the small-object optimization buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, member_ptr_tag) functor_manager_operation_type op, member_ptr_tag)
{ {
manager(in_buffer, out_buffer, op, mpl::true_()); manager(in_buffer, out_buffer, op, mpl::true_());
@ -384,15 +392,15 @@ namespace boost {
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -410,7 +418,7 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag) functor_manager_operation_type op, function_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
@ -418,15 +426,15 @@ namespace boost {
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_) functor_manager_operation_type op, mpl::true_)
{ {
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
} }
// Function objects that require heap allocation // Function objects that require heap allocation
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_) functor_manager_operation_type op, mpl::false_)
{ {
typedef functor_wrapper<Functor,Allocator> functor_wrapper_type; typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
@ -439,34 +447,34 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
const functor_wrapper_type* f = const functor_wrapper_type* f =
static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr); static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f); wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type // Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
out_buffer.obj_ptr = new_f; out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.obj_ptr = 0; in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor_wrapper_type */ /* Cast from the void pointer to the functor_wrapper_type */
functor_wrapper_type* victim = functor_wrapper_type* victim =
static_cast<functor_wrapper_type*>(in_buffer.obj_ptr); static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
wrapper_allocator.destroy(victim); wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1); wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -474,7 +482,7 @@ namespace boost {
// object can use the small-object optimization buffer or // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap. // whether we need to allocate it on the heap.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag) functor_manager_operation_type op, function_obj_tag)
{ {
manager(in_buffer, out_buffer, op, manager(in_buffer, out_buffer, op,
@ -485,15 +493,15 @@ namespace boost {
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -571,8 +579,8 @@ namespace boost {
*/ */
struct vtable_base struct vtable_base
{ {
void (*manager)(const function_buffer& in_buffer, void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer, function_buffer& out_buffer,
functor_manager_operation_type op); functor_manager_operation_type op);
}; };
} // end namespace function } // end namespace function
@ -600,7 +608,7 @@ public:
detail::function::function_buffer type; detail::function::function_buffer type;
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag); get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
return *type.type.type; return *type.members.type.type;
} }
template<typename Functor> template<typename Functor>
@ -609,12 +617,12 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = is_const<Functor>::value; type_result.members.type.const_qualified = is_const<Functor>::value;
type_result.type.volatile_qualified = is_volatile<Functor>::value; type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr); return static_cast<Functor*>(type_result.members.obj_ptr);
} }
template<typename Functor> template<typename Functor>
@ -623,14 +631,14 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = true; type_result.members.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value; type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
return static_cast<const Functor*>(type_result.obj_ptr); return static_cast<const Functor*>(type_result.members.obj_ptr);
} }
template<typename F> template<typename F>
@ -853,6 +861,6 @@ namespace detail {
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( pop ) # pragma warning( pop )
#endif #endif
#endif // BOOST_FUNCTION_BASE_HEADER #endif // BOOST_FUNCTION_BASE_HEADER

View File

@ -16,7 +16,7 @@
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( push ) # pragma warning( push )
# pragma warning( disable : 4127 ) // "conditional expression is constant" # pragma warning( disable : 4127 ) // "conditional expression is constant"
#endif #endif
#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
@ -97,7 +97,7 @@ namespace boost {
static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
return f(BOOST_FUNCTION_ARGS); return f(BOOST_FUNCTION_ARGS);
} }
}; };
@ -114,7 +114,7 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
} }
}; };
@ -132,9 +132,9 @@ namespace boost {
{ {
FunctionObj* f; FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -153,9 +153,9 @@ namespace boost {
{ {
FunctionObj* f; FunctionObj* f;
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -171,8 +171,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -189,8 +189,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -208,8 +208,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data); reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -226,8 +226,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(&function_obj_ptr.data); reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -322,7 +322,7 @@ namespace boost {
/* Given the tag returned by get_function_tag, retrieve the /* Given the tag returned by get_function_tag, retrieve the
actual invoker that will be used for the given function actual invoker that will be used for the given function
object. object.
Each specialization contains an "apply" nested class template Each specialization contains an "apply" nested class template
that accepts the function object, return type, function that accepts the function object, return type, function
@ -513,21 +513,21 @@ namespace boost {
private: private:
// Function pointers // Function pointers
template<typename FunctionPtr> template<typename FunctionPtr>
bool bool
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
{ {
this->clear(functor); this->clear(functor);
if (f) { if (f) {
// should be a reinterpret cast, but some compilers insist // should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions // on giving cv-qualifiers to free functions
functor.func_ptr = reinterpret_cast<void (*)()>(f); functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
return true; return true;
} else { } else {
return false; return false;
} }
} }
template<typename FunctionPtr,typename Allocator> template<typename FunctionPtr,typename Allocator>
bool bool
assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
{ {
return assign_to(f,functor,function_ptr_tag()); return assign_to(f,functor,function_ptr_tag());
@ -566,13 +566,13 @@ namespace boost {
// Function objects // Function objects
// Assign to a function object using the small object optimization // Assign to a function object using the small object optimization
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
{ {
new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f); new (reinterpret_cast<void*>(functor.data)) FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
{ {
assign_functor(f,functor,mpl::true_()); assign_functor(f,functor,mpl::true_());
@ -580,13 +580,13 @@ namespace boost {
// Assign to a function object allocated on the heap. // Assign to a function object allocated on the heap.
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
{ {
functor.obj_ptr = new FunctionObj(f); functor.members.obj_ptr = new FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
{ {
typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
@ -597,15 +597,15 @@ namespace boost {
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
functor.obj_ptr = new_f; functor.members.obj_ptr = new_f;
} }
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor(f, functor, assign_functor(f, functor,
mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
return true; return true;
} else { } else {
@ -613,7 +613,7 @@ namespace boost {
} }
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
@ -627,18 +627,18 @@ namespace boost {
// Reference to a function object // Reference to a function object
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(const reference_wrapper<FunctionObj>& f, assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag) const function_buffer& functor, function_obj_ref_tag) const
{ {
functor.obj_ref.obj_ptr = (void *)(f.get_pointer()); functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value; functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true; return true;
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(const reference_wrapper<FunctionObj>& f, assign_to_a(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, Allocator, function_obj_ref_tag) const function_buffer& functor, Allocator, function_obj_ref_tag) const
{ {
return assign_to(f,functor,function_obj_ref_tag()); return assign_to(f,functor,function_obj_ref_tag());
@ -752,14 +752,14 @@ namespace boost {
{ {
this->assign_to_own(f); this->assign_to_own(f);
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base() BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
{ {
this->move_assign(f); this->move_assign(f);
} }
#endif #endif
~BOOST_FUNCTION_FUNCTION() { clear(); } ~BOOST_FUNCTION_FUNCTION() { clear(); }
result_type operator()(BOOST_FUNCTION_PARMS) const result_type operator()(BOOST_FUNCTION_PARMS) const
@ -840,12 +840,11 @@ namespace boost {
BOOST_CATCH_END BOOST_CATCH_END
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
// Move assignment from another BOOST_FUNCTION_FUNCTION // Move assignment from another BOOST_FUNCTION_FUNCTION
BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f) BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
{ {
if (&f == this) if (&f == this)
return *this; return *this;
@ -922,10 +921,10 @@ namespace boost {
typedef typename boost::detail::function::get_function_tag<Functor>::type tag; typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply<Functor, R BOOST_FUNCTION_COMMA template apply<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS> BOOST_FUNCTION_TEMPLATE_ARGS>
handler_type; handler_type;
typedef typename handler_type::invoker_type invoker_type; typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type; typedef typename handler_type::manager_type manager_type;
@ -933,7 +932,7 @@ namespace boost {
// static initialization. Otherwise, we will have a race // static initialization. Otherwise, we will have a race
// condition here in multi-threaded code. See // condition here in multi-threaded code. See
// http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
static const vtable_type stored_vtable = static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke }; { { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) { if (stored_vtable.assign_to(f, functor)) {
@ -944,7 +943,7 @@ namespace boost {
boost::detail::function::function_allows_small_object_optimization<Functor>::value) boost::detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
@ -956,11 +955,11 @@ namespace boost {
typedef typename boost::detail::function::get_function_tag<Functor>::type tag; typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply_a<Functor, R BOOST_FUNCTION_COMMA template apply_a<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS, BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator> Allocator>
handler_type; handler_type;
typedef typename handler_type::invoker_type invoker_type; typedef typename handler_type::invoker_type invoker_type;
typedef typename handler_type::manager_type manager_type; typedef typename handler_type::manager_type manager_type;
@ -971,7 +970,7 @@ namespace boost {
static const vtable_type stored_vtable = static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke }; { { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) { if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
// coverity[pointless_expression]: suppress coverity warnings on apparant if(const). // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
if (boost::has_trivial_copy_constructor<Functor>::value && if (boost::has_trivial_copy_constructor<Functor>::value &&
@ -979,15 +978,15 @@ namespace boost {
boost::detail::function::function_allows_small_object_optimization<Functor>::value) boost::detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
// Moves the value from the specified argument to *this. If the argument // Moves the value from the specified argument to *this. If the argument
// has its function object allocated on the heap, move_assign will pass // has its function object allocated on the heap, move_assign will pass
// its buffer to *this, and set the argument's buffer pointer to NULL. // its buffer to *this, and set the argument's buffer pointer to NULL.
void move_assign(BOOST_FUNCTION_FUNCTION& f) void move_assign(BOOST_FUNCTION_FUNCTION& f)
{ {
if (&f == this) if (&f == this)
return; return;
@ -1098,7 +1097,7 @@ public:
function(self_type&& f): base_type(static_cast<base_type&&>(f)){} function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
function(base_type&& f): base_type(static_cast<base_type&&>(f)){} function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
#endif #endif
self_type& operator=(const self_type& f) self_type& operator=(const self_type& f)
{ {
self_type(f).swap(*this); self_type(f).swap(*this);
@ -1111,7 +1110,7 @@ public:
self_type(static_cast<self_type&&>(f)).swap(*this); self_type(static_cast<self_type&&>(f)).swap(*this);
return *this; return *this;
} }
#endif #endif
template<typename Functor> template<typename Functor>
#ifndef BOOST_NO_SFINAE #ifndef BOOST_NO_SFINAE
@ -1140,14 +1139,14 @@ public:
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
self_type& operator=(base_type&& f) self_type& operator=(base_type&& f)
{ {
self_type(static_cast<base_type&&>(f)).swap(*this); self_type(static_cast<base_type&&>(f)).swap(*this);
return *this; return *this;
} }
#endif #endif
}; };
#undef BOOST_FUNCTION_PARTIAL_SPEC #undef BOOST_FUNCTION_PARTIAL_SPEC
@ -1187,4 +1186,4 @@ public:
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
# pragma warning( pop ) # pragma warning( pop )
#endif #endif