diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp index a9092a1..04ca447 100644 --- a/include/boost/container/detail/node_alloc_holder.hpp +++ b/include/boost/container/detail/node_alloc_holder.hpp @@ -227,14 +227,18 @@ struct node_alloc_holder NodePtr create_node(Args &&...args) { NodePtr p = this->allocate_one(); - Deallocator node_deallocator(p, this->node_alloc()); - allocator_traits::construct - ( this->node_alloc() - , dtl::addressof(p->m_data), boost::forward(args)...); - node_deallocator.release(); - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type; + BOOST_TRY{ + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node; + allocator_traits::construct + (this->node_alloc() + , p->get_real_data_ptr(), boost::forward(args)...); + } + BOOST_CATCH(...) { + p->destroy_header(); + this->node_alloc().deallocate(p, 1); + BOOST_RETHROW + } + BOOST_CATCH_END return (p); } @@ -245,14 +249,19 @@ struct node_alloc_holder NodePtr create_node(BOOST_MOVE_UREF##N)\ {\ NodePtr p = this->allocate_one();\ - Deallocator node_deallocator(p, this->node_alloc());\ - allocator_traits::construct\ - ( this->node_alloc()\ - , dtl::addressof(p->m_data)\ - BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ - node_deallocator.release();\ - typedef typename Node::hook_type hook_type;\ - ::new(static_cast(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;\ + BOOST_TRY{\ + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node;\ + allocator_traits::construct\ + ( this->node_alloc()\ + , p->get_real_data_ptr()\ + BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + BOOST_CATCH(...) {\ + p->destroy_header();\ + this->node_alloc().deallocate(p, 1);\ + BOOST_RETHROW\ + }\ + BOOST_CATCH_END\ return (p);\ }\ // @@ -265,12 +274,16 @@ struct node_alloc_holder NodePtr create_node_from_it(const It &it) { NodePtr p = this->allocate_one(); - Deallocator node_deallocator(p, this->node_alloc()); - ::boost::container::construct_in_place(this->node_alloc(), dtl::addressof(p->m_data), it); - node_deallocator.release(); - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type; + BOOST_TRY{ + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node; + ::boost::container::construct_in_place(this->node_alloc(), p->get_real_data_ptr(), it); + } + BOOST_CATCH(...) { + p->destroy_header(); + this->node_alloc().deallocate(p, 1); + BOOST_RETHROW + } + BOOST_CATCH_END return (p); } @@ -278,22 +291,26 @@ struct node_alloc_holder NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key) { NodePtr p = this->allocate_one(); - NodeAlloc &na = this->node_alloc(); - Deallocator node_deallocator(p, this->node_alloc()); - node_allocator_traits_type::construct - (na, dtl::addressof(p->m_data.first), boost::forward(key)); BOOST_TRY{ - node_allocator_traits_type::construct(na, dtl::addressof(p->m_data.second)); + ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) Node; + NodeAlloc &na = this->node_alloc(); + node_allocator_traits_type::construct + (na, dtl::addressof(p->get_real_data().first), boost::forward(key)); + BOOST_TRY{ + node_allocator_traits_type::construct(na, dtl::addressof(p->get_real_data().second)); + } + BOOST_CATCH(...){ + node_allocator_traits_type::destroy(na, dtl::addressof(p->get_real_data().first)); + BOOST_RETHROW; + } + BOOST_CATCH_END } - BOOST_CATCH(...){ - node_allocator_traits_type::destroy(na, dtl::addressof(p->m_data.first)); - BOOST_RETHROW; + BOOST_CATCH(...) { + p->destroy_header(); + this->node_alloc().deallocate(p, 1); + BOOST_RETHROW } BOOST_CATCH_END - node_deallocator.release(); - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type; return (p); } @@ -315,30 +332,31 @@ struct node_alloc_holder (FwdIterator beg, difference_type n, Inserter inserter) { if(n){ - typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain; + typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain_t; //Try to allocate memory in a single block - typedef typename multiallocation_chain::iterator multialloc_iterator; - multiallocation_chain mem; + typedef typename multiallocation_chain_t::iterator multialloc_iterator_t; + multiallocation_chain_t chain; NodeAlloc &nalloc = this->node_alloc(); - node_allocator_version_traits_type::allocate_individual(nalloc, n, mem); - multialloc_iterator itbeg(mem.begin()), itlast(mem.last()); - mem.clear(); + node_allocator_version_traits_type::allocate_individual(nalloc, n, chain); + multialloc_iterator_t itbeg = chain.begin(); + multialloc_iterator_t itlast = chain.last(); + chain.clear(); + Node *p = 0; - BOOST_TRY{ + BOOST_TRY{ Deallocator node_deallocator(NodePtr(), nalloc); dtl::scoped_destructor sdestructor(nalloc, 0); - while(n--){ - p = boost::movelib::iterator_to_raw_pointer(itbeg); + while(n){ + --n; + //This does not throw + p = ::new(boost::movelib::iterator_to_raw_pointer(itbeg), boost_container_new_t()) Node; node_deallocator.set(p); ++itbeg; //This can throw - boost::container::construct_in_place(nalloc, dtl::addressof(p->m_data), beg); + boost::container::construct_in_place(nalloc, p->get_real_data_ptr(), beg); sdestructor.set(p); ++beg; - //This does not throw - typedef typename Node::hook_type hook_type; - ::new(static_cast(p), boost_container_new_t()) hook_type; //This can throw in some containers (predicate might throw). //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception) inserter(*p); @@ -348,8 +366,9 @@ struct node_alloc_holder node_deallocator.release(); } BOOST_CATCH(...){ - mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n); - node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem); + p->destroy_header(); + chain.incorporate_after(chain.last(), &*itbeg, &*itlast, n); + node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), chain); BOOST_RETHROW } BOOST_CATCH_END @@ -402,7 +421,7 @@ struct node_alloc_holder {} NodePtr operator()(const Node &other) const - { return m_holder.create_node(other.m_data); } + { return m_holder.create_node(other.get_real_data()); } node_alloc_holder &m_holder; }; @@ -414,8 +433,8 @@ struct node_alloc_holder {} NodePtr operator()(Node &other) - { //Use m_data instead of get_data to allow moving const key in [multi]map - return m_holder.create_node(::boost::move(other.m_data)); + { //Use get_real_data() instead of get_real_data to allow moving const key in [multi]map + return m_holder.create_node(::boost::move(other.get_real_data())); } node_alloc_holder &m_holder; diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp index 193a286..498fc73 100644 --- a/include/boost/container/detail/tree.hpp +++ b/include/boost/container/detail/tree.hpp @@ -125,10 +125,6 @@ template ::type { - private: - //BOOST_COPYABLE_AND_MOVABLE(tree_node) - tree_node(); - public: typedef typename intrusive_tree_hook ::type hook_type; @@ -138,55 +134,86 @@ struct tree_node typedef tree_node< T, VoidPointer , tree_type_value, OptimizeSize> node_t; + typedef typename boost::container::dtl::aligned_storage + ::value>::type storage_t; + storage_t m_storage; + + #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + BOOST_CONTAINER_FORCEINLINE T &get_data() - { - T* ptr = reinterpret_cast(&this->m_data); - return *ptr; - } + { return *reinterpret_cast(this->m_storage.data); } BOOST_CONTAINER_FORCEINLINE const T &get_data() const - { - const T* ptr = reinterpret_cast(&this->m_data); - return *ptr; - } + { return *reinterpret_cast(this->m_storage.data); } - internal_type m_data; + BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE ~tree_node() + { reinterpret_cast(this->m_storage.data)->~internal_type(); } + + #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) + #pragma GCC diagnostic pop + #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + + BOOST_CONTAINER_FORCEINLINE void destroy_header() + { static_cast(this)->~hook_type(); } template BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair &p) { - const_cast(m_data.first) = p.first; - m_data.second = p.second; + const_cast(this->get_real_data().first) = p.first; + this->get_real_data().second = p.second; } template BOOST_CONTAINER_FORCEINLINE void do_assign(const pair &p) { - const_cast(m_data.first) = p.first; - m_data.second = p.second; + const_cast(this->get_real_data().first) = p.first; + this->get_real_data().second = p.second; } template BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v) - { m_data = v; } + { this->get_real_data() = v; } template BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair &p) { - const_cast(m_data.first) = ::boost::move(p.first); - m_data.second = ::boost::move(p.second); + const_cast(this->get_real_data().first) = ::boost::move(p.first); + this->get_real_data().second = ::boost::move(p.second); } template BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair &p) { - const_cast(m_data.first) = ::boost::move(p.first); - m_data.second = ::boost::move(p.second); + const_cast(this->get_real_data().first) = ::boost::move(p.first); + this->get_real_data().second = ::boost::move(p.second); } template BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v) - { m_data = ::boost::move(v); } + { this->get_real_data() = ::boost::move(v); } }; template @@ -361,10 +388,10 @@ class RecyclingCloner {} BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_) - { p->do_move_assign(const_cast(other).m_data); } + { p->do_move_assign(const_cast(other).get_real_data()); } BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_) - { p->do_assign(other.m_data); } + { p->do_assign(other.get_real_data()); } node_ptr_type operator()(const node_t &other) const { @@ -386,7 +413,7 @@ class RecyclingCloner BOOST_CATCH_END } else{ - return m_holder.create_node(other.m_data); + return m_holder.create_node(other.get_real_data()); } } diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp index 68892bc..2e512f9 100644 --- a/include/boost/container/list.hpp +++ b/include/boost/container/list.hpp @@ -71,20 +71,54 @@ template struct list_node : public list_hook::type { - private: - list_node(); - public: typedef T value_type; + typedef T internal_type; typedef typename list_hook::type hook_type; - T m_data; + typedef typename aligned_storage::value>::type storage_t; + storage_t m_storage; - T &get_data() - { return this->m_data; } + #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif - const T &get_data() const - { return this->m_data; } + BOOST_CONTAINER_FORCEINLINE T &get_data() + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T &get_data() const + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE ~list_node() + { reinterpret_cast(this->m_storage.data)->~T(); } + + #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) + #pragma GCC diagnostic pop + #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + + BOOST_CONTAINER_FORCEINLINE void destroy_header() + { static_cast(this)->~hook_type(); } }; template diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp index 2769070..2bdf843 100644 --- a/include/boost/container/slist.hpp +++ b/include/boost/container/slist.hpp @@ -71,26 +71,62 @@ struct slist_hook , dtl::bi::link_mode >::type type; }; + template struct slist_node : public slist_hook::type { - private: - slist_node(); - public: typedef T value_type; + typedef T internal_type; typedef typename slist_hook::type hook_type; - T m_data; + typedef typename aligned_storage::value>::type storage_t; + storage_t m_storage; - T &get_data() - { return this->m_data; } + #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif - const T &get_data() const - { return this->m_data; } + BOOST_CONTAINER_FORCEINLINE T &get_data() + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T &get_data() const + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type &get_real_data() + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type &get_real_data() const + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE internal_type *get_real_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const internal_type *get_real_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE ~slist_node() + { reinterpret_cast(this->m_storage.data)->~T(); } + + #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) + #pragma GCC diagnostic pop + #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + + BOOST_CONTAINER_FORCEINLINE void destroy_header() + { static_cast(this)->~hook_type(); } }; + template struct iiterator_node_value_type< slist_node > { typedef T type; diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp index 41f45df..e0a39f0 100644 --- a/include/boost/container/stable_vector.hpp +++ b/include/boost/container/stable_vector.hpp @@ -114,12 +114,14 @@ struct node_base typedef typename void_ptr_traits:: template rebind_pointer ::type node_base_ptr; + + public: typedef typename void_ptr_traits:: template rebind_pointer ::type node_base_ptr_ptr; public: - node_base(const node_base_ptr_ptr &n) + explicit node_base(const node_base_ptr_ptr &n) : up(n) {} @@ -130,6 +132,7 @@ struct node_base node_base_ptr_ptr up; }; + template struct node : public node_base @@ -137,11 +140,52 @@ struct node rebind_pointer::type > { - private: - node(); - public: - typename ::boost::intrusive::pointer_traits::element_type value; + typedef typename ::boost::intrusive::pointer_traits::element_type T; + typedef node_base + ::template + rebind_pointer::type + > hook_type; + + typedef typename boost::container::dtl::aligned_storage + ::value>::type storage_t; + storage_t m_storage; + + BOOST_CONTAINER_FORCEINLINE explicit node(const typename hook_type::node_base_ptr_ptr &n) + : hook_type(n) + {} + + BOOST_CONTAINER_FORCEINLINE node() + {} + + #if defined(BOOST_GCC) && (BOOST_GCC >= 40600) && (BOOST_GCC < 80000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #define BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + + BOOST_CONTAINER_FORCEINLINE T &get_data() + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T &get_data() const + { return *reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE T *get_data_ptr() + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE const T *get_data_ptr() const + { return reinterpret_cast(this->m_storage.data); } + + BOOST_CONTAINER_FORCEINLINE ~node() + { reinterpret_cast(this->m_storage.data)->~T(); } + + #if defined(BOOST_CONTAINER_DISABLE_ALIASING_WARNING) + #pragma GCC diagnostic pop + #undef BOOST_CONTAINER_DISABLE_ALIASING_WARNING + # endif + + BOOST_CONTAINER_FORCEINLINE void destroy_header() + { static_cast(this)->~hook_type(); } }; template @@ -290,7 +334,7 @@ class stable_vector_iterator public: //Pointer like operators reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW - { return node_pointer()->value; } + { return node_pointer()->get_data(); } pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW { return ptr_traits::pointer_to(this->operator*()); } @@ -317,7 +361,7 @@ class stable_vector_iterator { stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); } reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW - { return node_ptr_traits::static_cast_from(this->m_pn->up[off])->value; } + { return node_ptr_traits::static_cast_from(this->m_pn->up[off])->get_data(); } stable_vector_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { @@ -1198,7 +1242,7 @@ class stable_vector reference front() BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(!this->empty()); - return static_cast(*this->index.front()).value; + return static_cast(*this->index.front()).get_data(); } //! Requires: !empty() @@ -1212,7 +1256,7 @@ class stable_vector const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(!this->empty()); - return static_cast(*this->index.front()).value; + return static_cast(*this->index.front()).get_data(); } //! Requires: !empty() @@ -1226,7 +1270,7 @@ class stable_vector reference back() BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(!this->empty()); - return static_cast(*this->index[this->size()-1u]).value; + return static_cast(*this->index[this->size()-1u]).get_data(); } //! Requires: !empty() @@ -1240,7 +1284,7 @@ class stable_vector const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(!this->empty()); - return static_cast(*this->index[this->size()-1u]).value; + return static_cast(*this->index[this->size()-1u]).get_data(); } //! Requires: size() > n. @@ -1254,7 +1298,7 @@ class stable_vector reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->size() > n); - return static_cast(*this->index[n]).value; + return static_cast(*this->index[n]).get_data(); } //! Requires: size() > n. @@ -1268,7 +1312,7 @@ class stable_vector const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->size() > n); - return static_cast(*this->index[n]).value; + return static_cast(*this->index[n]).get_data(); } //! Requires: size() >= n. @@ -1956,8 +2000,7 @@ class stable_vector void priv_destroy_node(const node_type &n) { allocator_traits:: - destroy(this->priv_node_alloc(), dtl::addressof(n.value)); - static_cast(&n)->~node_base_type(); + destroy(this->priv_node_alloc(), &n); } void priv_delete_node(const node_ptr &n) @@ -1969,26 +2012,40 @@ class stable_vector template void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it) { - //This can throw - boost::container::construct_in_place - ( this->priv_node_alloc() - , dtl::addressof(p->value) - , it); - //This does not throw - ::new(static_cast(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) - node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index)); + node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) + node_type(index_traits_type::ptr_to_node_base_ptr(*up_index)); + BOOST_TRY{ + //This can throw + boost::container::construct_in_place + ( this->priv_node_alloc() + , praw->get_data_ptr() + , it); + } + BOOST_CATCH(...) { + praw->destroy_header(); + this->priv_node_alloc().deallocate(p, 1); + BOOST_RETHROW + } + BOOST_CATCH_END } template void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible) { - //This can throw - boost::container::allocator_traits::construct - ( this->priv_node_alloc() - , dtl::addressof(p->value) - , ::boost::forward(value_convertible)); - //This does not throw - ::new(static_cast(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) node_base_type; + node_type *praw = ::new(boost::movelib::iterator_to_raw_pointer(p), boost_container_new_t()) node_type; + BOOST_TRY{ + //This can throw + boost::container::allocator_traits::construct + ( this->priv_node_alloc() + , p->get_data_ptr() + , ::boost::forward(value_convertible)); + } + BOOST_CATCH(...) { + praw->destroy_header(); + this->priv_node_alloc().deallocate(p, 1); + BOOST_RETHROW + } + BOOST_CATCH_END } void priv_swap_members(stable_vector &x) diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 46d9e7a..8b863ab 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -1352,7 +1352,11 @@ class vector //! //! Complexity: Constant. BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW - { return iterator(this->m_holder.start() + this->m_holder.m_size); } + { + pointer const bg = this->m_holder.start(); + size_type const sz = this->m_holder.m_size; + return iterator(BOOST_LIKELY(sz) ? bg + sz : bg); //Avoid UB on null-pointer arithmetic + } //! Effects: Returns a const_iterator to the end of the vector. //! @@ -1412,7 +1416,12 @@ class vector //! //! Complexity: Constant. BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW - { return const_iterator(this->m_holder.start() + this->m_holder.m_size); } + { + pointer const bg = this->m_holder.start(); + size_type const sz = this->m_holder.m_size; + return const_iterator(BOOST_LIKELY(sz) ? bg + sz : bg); //Avoid UB on null-pointer arithmetic + } + //{ return const_iterator(this->m_holder.start() + this->m_holder.m_size); } //! Effects: Returns a const_reverse_iterator pointing to the beginning //! of the reversed vector. @@ -2037,9 +2046,10 @@ class vector //! plus linear to the elements between pos and the last element. iterator erase(const_iterator first, const_iterator last) { - BOOST_ASSERT(first == last || - (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last))); if (first != last){ + BOOST_ASSERT(this->priv_in_range(first)); + BOOST_ASSERT(this->priv_in_range_or_end(last)); + BOOST_ASSERT(first < last); T* const old_end_ptr = this->priv_raw_end(); T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first)); T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));