mirror of
https://github.com/boostorg/move.git
synced 2025-08-02 05:44:25 +02:00
Added check for types with no virtual destructor when using default_delete and non-array types
This commit is contained in:
@@ -128,7 +128,11 @@ struct default_delete
|
||||
default_delete(const default_delete<U>&
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_def_del<U BOOST_MOVE_I T>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
{}
|
||||
{
|
||||
//If T is not an array type, U derives from T
|
||||
//and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Constructs a default_delete object from another <tt>default_delete<U></tt> object.
|
||||
//!
|
||||
@@ -139,7 +143,12 @@ struct default_delete
|
||||
BOOST_MOVE_DOC1ST(default_delete&,
|
||||
typename bmupd::enable_def_del<U BOOST_MOVE_I T BOOST_MOVE_I default_delete &>::type)
|
||||
operator=(const default_delete<U>&) BOOST_NOEXCEPT
|
||||
{ return *this; }
|
||||
{
|
||||
//If T is not an array type, U derives from T
|
||||
//and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: if T is not an array type, calls <tt>delete</tt> on static_cast<T*>(ptr),
|
||||
//! otherwise calls <tt>delete[]</tt> on static_cast<remove_extent<T>::type*>(ptr).
|
||||
@@ -155,6 +164,9 @@ struct default_delete
|
||||
{
|
||||
//U must be a complete type
|
||||
BOOST_STATIC_ASSERT(sizeof(U) > 0);
|
||||
//If T is not an array type, U derives from T
|
||||
//and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor<default_delete, U>::value ));
|
||||
element_type * const p = static_cast<element_type*>(ptr);
|
||||
bmupmu::is_array<T>::value ? delete [] p : delete p;
|
||||
}
|
||||
|
@@ -20,6 +20,13 @@
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace movelib {
|
||||
|
||||
template <class T>
|
||||
struct default_delete;
|
||||
|
||||
} //namespace movelib {
|
||||
|
||||
#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
//Forward declare boost::rv
|
||||
template <class T> class rv;
|
||||
@@ -423,7 +430,7 @@ class is_convertible
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////
|
||||
// is_unary_function
|
||||
// is_unary_function
|
||||
//////////////////////////////////////
|
||||
#if defined(BOOST_MSVC) || defined(__BORLANDC_)
|
||||
#define BOOST_MOVE_TT_DECL __cdecl
|
||||
@@ -517,6 +524,66 @@ template<typename T>
|
||||
struct is_unary_function
|
||||
{ static const bool value = is_unary_function_impl<T>::value; };
|
||||
|
||||
//////////////////////////////////////
|
||||
// has_virtual_destructor
|
||||
//////////////////////////////////////
|
||||
#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
|
||||
|| (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
|
||||
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
|
||||
#elif defined(BOOST_CLANG) && defined(__has_feature)
|
||||
# if __has_feature(has_virtual_destructor)
|
||||
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
|
||||
# endif
|
||||
#elif defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
|
||||
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
|
||||
#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
|
||||
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
|
||||
#elif defined(__CODEGEARC__)
|
||||
# define BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR
|
||||
template<class T>
|
||||
struct has_virtual_destructor{ static const bool value = BOOST_MOVEUP_HAS_VIRTUAL_DESTRUCTOR(T); };
|
||||
#else
|
||||
//If no intrinsic is available you trust the programmer knows what is doing
|
||||
template<class T>
|
||||
struct has_virtual_destructor{ static const bool value = true; };
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////
|
||||
// missing_virtual_destructor
|
||||
//////////////////////////////////////
|
||||
|
||||
template< class T, class U
|
||||
, bool enable = is_convertible< typename remove_cv<U>::type*
|
||||
, typename remove_cv<T>::type*>::value &&
|
||||
!is_array<T>::value &&
|
||||
!is_same<typename remove_cv<T>::type, void>::value &&
|
||||
!is_same<typename remove_cv<U>::type, typename remove_cv<T>::type>::value
|
||||
>
|
||||
struct missing_virtual_destructor_default_delete
|
||||
{
|
||||
static const bool value = !has_virtual_destructor<T>::value;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct missing_virtual_destructor_default_delete<T, U, false>
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class Deleter, class U>
|
||||
struct missing_virtual_destructor
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
struct missing_virtual_destructor< ::boost::movelib::default_delete<T>, U >
|
||||
: missing_virtual_destructor_default_delete<T, U>
|
||||
{};
|
||||
|
||||
} //namespace move_upmu {
|
||||
} //namespace boost {
|
||||
|
||||
|
@@ -411,6 +411,10 @@ class unique_ptr
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(p)
|
||||
{
|
||||
//If T is not an array type, element_type_t<Pointer> derives from T
|
||||
//it uses the default deleter and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
|
||||
<D, typename bmupd::get_element_type<Pointer>::type>::value ));
|
||||
//If this constructor is instantiated with a pointer type or reference type
|
||||
//for the template argument D, the program is ill-formed.
|
||||
BOOST_STATIC_ASSERT(!bmupmu::is_pointer<D>::value);
|
||||
@@ -444,7 +448,12 @@ class unique_ptr
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(p, d1)
|
||||
{}
|
||||
{
|
||||
//If T is not an array type, element_type_t<Pointer> derives from T
|
||||
//it uses the default deleter and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
|
||||
<D, typename bmupd::get_element_type<Pointer>::type>::value ));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type1 d1)</tt>
|
||||
//! and additionally <tt>get() == nullptr</tt>
|
||||
@@ -477,7 +486,12 @@ class unique_ptr
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(p, ::boost::move(d2))
|
||||
{}
|
||||
{
|
||||
//If T is not an array type, element_type_t<Pointer> derives from T
|
||||
//it uses the default deleter and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
|
||||
<D, typename bmupd::get_element_type<Pointer>::type>::value ));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Same effects as <tt>template<class Pointer> unique_ptr(Pointer p, deleter_arg_type2 d2)</tt>
|
||||
//! and additionally <tt>get() == nullptr</tt>
|
||||
@@ -519,7 +533,12 @@ class unique_ptr
|
||||
BOOST_MOVE_DOCIGN(BOOST_MOVE_I typename bmupd::enable_up_moveconv_constr<T BOOST_MOVE_I D BOOST_MOVE_I U BOOST_MOVE_I E>::type* =0)
|
||||
) BOOST_NOEXCEPT
|
||||
: m_data(u.release(), ::boost::move_if_not_lvalue_reference<E>(u.get_deleter()))
|
||||
{}
|
||||
{
|
||||
//If T is not an array type, U derives from T
|
||||
//it uses the default deleter and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
|
||||
<D, typename unique_ptr<U, E>::pointer>::value ));
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: The expression <tt>get_deleter()(get())</tt> shall be well formed, shall have well-defined behavior,
|
||||
//! and shall not throw exceptions.
|
||||
@@ -673,6 +692,10 @@ class unique_ptr
|
||||
BOOST_MOVE_DOC1ST(void, typename bmupd::enable_up_ptr<T BOOST_MOVE_I Pointer BOOST_MOVE_I pointer BOOST_MOVE_I void>::type)
|
||||
reset(Pointer p) BOOST_NOEXCEPT
|
||||
{
|
||||
//If T is not an array type, element_type_t<Pointer> derives from T
|
||||
//it uses the default deleter and T has no virtual destructor, then you have a problem
|
||||
BOOST_STATIC_ASSERT(( !::boost::move_upmu::missing_virtual_destructor
|
||||
<D, typename bmupd::get_element_type<Pointer>::type>::value ));
|
||||
pointer tmp = m_data.m_p;
|
||||
m_data.m_p = p;
|
||||
if(tmp) m_data.deleter()(tmp);
|
||||
|
@@ -231,6 +231,7 @@ Global
|
||||
..\..\..\..\boost\move\detail\move_helpers.hpp = ..\..\..\..\boost\move\detail\move_helpers.hpp
|
||||
..\..\..\..\boost\move\traits.hpp = ..\..\..\..\boost\move\traits.hpp
|
||||
..\..\..\..\boost\move\unique_ptr.hpp = ..\..\..\..\boost\move\unique_ptr.hpp
|
||||
..\..\..\..\boost\move\detail\unique_ptr_meta_utils.hpp = ..\..\..\..\boost\move\detail\unique_ptr_meta_utils.hpp
|
||||
..\..\test\unique_ptr_test_utils_beg.hpp = ..\..\test\unique_ptr_test_utils_beg.hpp
|
||||
..\..\test\unique_ptr_test_utils_end.hpp = ..\..\test\unique_ptr_test_utils_end.hpp
|
||||
..\..\..\..\boost\move\utility.hpp = ..\..\..\..\boost\move\utility.hpp
|
||||
|
Reference in New Issue
Block a user