forked from boostorg/container
Remove UB in flat_map implementation when the implementation has a movable std::pair
This commit is contained in:
1 parent
429024ca4e
commit
20ad12f20e
4 files changed
+241
-134
No files matched your search
@@ -48,6 +48,11 @@
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
#define BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
@@ -58,21 +63,37 @@ class flat_multimap;
|
||||
|
||||
namespace dtl{
|
||||
|
||||
#if defined(BOOST_CONTAINER_STD_PAIR_IS_MOVABLE)
|
||||
template<class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
|
||||
{ return *move_detail::force_ptr<D*>(&s); }
|
||||
{ return s; }
|
||||
|
||||
template<class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
|
||||
{ return *move_detail::force_ptr<const D*>(&s); }
|
||||
{ return s; }
|
||||
|
||||
template<class D>
|
||||
BOOST_CONTAINER_FORCEINLINE static D force_copy(D s)
|
||||
{ return s; }
|
||||
|
||||
#else //!BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
template<class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
|
||||
{ return *move_detail::launder_cast<D*>(&s); }
|
||||
|
||||
template<class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
|
||||
{ return *move_detail::launder_cast<const D*>(&s); }
|
||||
|
||||
template<class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
|
||||
{
|
||||
const D *const vp = move_detail::force_ptr<const D *>(&s);
|
||||
const D *const vp = move_detail::launder_cast<const D *>(&s);
|
||||
D ret_val(*vp);
|
||||
return ret_val;
|
||||
}
|
||||
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
} //namespace dtl{
|
||||
|
||||
@@ -118,18 +139,27 @@ class flat_map
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(flat_map)
|
||||
//This is the tree that we should store if pair was movable
|
||||
typedef std::pair<Key, T> std_pair_t;
|
||||
typedef dtl::flat_tree<
|
||||
std::pair<Key, T>,
|
||||
std_pair_t,
|
||||
dtl::select1st<Key>,
|
||||
Compare,
|
||||
AllocatorOrContainer> tree_t;
|
||||
|
||||
//This is the real tree stored here. It's based on a movable pair
|
||||
typedef dtl::pair<Key, T> dtl_pair_t;
|
||||
|
||||
#ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
|
||||
typedef std_pair_t impl_pair_t;
|
||||
#else
|
||||
typedef dtl_pair_t impl_pair_t;
|
||||
#endif
|
||||
|
||||
typedef dtl::flat_tree<
|
||||
dtl::pair<Key, T>,
|
||||
impl_pair_t,
|
||||
dtl::select1st<Key>,
|
||||
Compare,
|
||||
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
|
||||
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
|
||||
> impl_tree_t;
|
||||
impl_tree_t m_flat_tree; // flat tree representing flat_map
|
||||
|
||||
@@ -851,7 +881,7 @@ class flat_map
|
||||
//! @copydoc ::boost::container::flat_set::nth(size_type) const
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
|
||||
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.nth(n)); }
|
||||
|
||||
//! @copydoc ::boost::container::flat_set::index_of(iterator)
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
|
||||
@@ -1099,7 +1129,7 @@ class flat_map
|
||||
template <class Pair>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( std::pair<iterator BOOST_MOVE_I bool>
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
|
||||
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
|
||||
insert(BOOST_FWD_REF(Pair) x)
|
||||
{
|
||||
@@ -1153,7 +1183,7 @@ class flat_map
|
||||
template <class Pair>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( iterator
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
|
||||
BOOST_MOVE_I iterator>::type)
|
||||
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
|
||||
{
|
||||
@@ -1777,17 +1807,24 @@ class flat_multimap
|
||||
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
|
||||
typedef std::pair<Key, T> std_pair_t;
|
||||
typedef dtl::flat_tree<
|
||||
std::pair<Key, T>,
|
||||
std_pair_t,
|
||||
dtl::select1st<Key>,
|
||||
Compare,
|
||||
AllocatorOrContainer> tree_t;
|
||||
//This is the real tree stored here. It's based on a movable pair
|
||||
typedef dtl::pair<Key, T> dtl_pair_t;
|
||||
#ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
|
||||
typedef std_pair_t impl_pair_t;
|
||||
#else
|
||||
typedef dtl_pair_t impl_pair_t;
|
||||
#endif
|
||||
typedef dtl::flat_tree<
|
||||
dtl::pair<Key, T>,
|
||||
impl_pair_t,
|
||||
dtl::select1st<Key>,
|
||||
Compare,
|
||||
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
|
||||
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
|
||||
> impl_tree_t;
|
||||
impl_tree_t m_flat_tree; // flat tree representing flat_map
|
||||
|
||||
@@ -2388,7 +2425,7 @@ class flat_multimap
|
||||
//! @copydoc ::boost::container::flat_set::nth(size_type) const
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
|
||||
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
|
||||
{ return dtl::force_copy<const_iterator>(m_flat_tree.nth(n)); }
|
||||
|
||||
//! @copydoc ::boost::container::flat_set::index_of(iterator)
|
||||
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
|
||||
@@ -2477,7 +2514,7 @@ class flat_multimap
|
||||
template<class Pair>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( iterator
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
|
||||
BOOST_MOVE_I iterator >::type)
|
||||
insert(BOOST_FWD_REF(Pair) x)
|
||||
{ return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Pair>(x))); }
|
||||
@@ -2514,7 +2551,7 @@ class flat_multimap
|
||||
template<class Pair>
|
||||
inline BOOST_CONTAINER_DOC1ST
|
||||
( iterator
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
|
||||
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
|
||||
BOOST_MOVE_I iterator>::type)
|
||||
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user