From 6f1becb66055c351fb9a44563ce7153dbf6487aa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Dumont?= Date: Fri, 17 May 2019 16:27:54 +0000 Subject: [PATCH] =?utf8?q?2019-05-17=20=20Fran=C3=A7ois=20Dumont=20=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * include/bits/stl_deque.h (_Deque_iterator<>::__ptr_to): Remove, use std::__ptr_rebind. (_Deque_base(_Deque_base&&, const allocator_type&)): New. (_Deque_base::_Deque_impl_data): New. (_Deque_base::_Deque_impl): Inherit latter. (_Deque_base::_Deque_impl::_M_swap_data): Move... (_Deque_base::_Deque_impl_data::_M_swap_data): ... here. (_Deque_base::_Deque_impl()): Add noexcept qualification. (_Deque_base::_Deque_impl(_Deque_impl&&, _Tp_alloc_type&&)): New. (_Deque_base::_Deque_impl::_M_get_Tp_allocator()): Remove static_cast. (deque<>::deque()): Default. (deque<>::deque(deque&&)): Default. (deque<>::deque(deque&&, const allocator_type&, false_type)): New. (deque<>::deque(deque&&, const allocator_type&, true_type)): New. (deque<>::deque(deque&&, const allocator_type&)): Delegate to latters. (deque<>::deque<_It>(_It, _It, const allocator_type&)): Use _M_range_initialize. (deque<>::assign<_It>(_It, _It)): Use _M_assign_aux. (deque<>::resize(size_type, const value_type&)): Share a single implementation. (deque<>::insert<_It>(const_iterator, _It, _It)): Use _M_range_insert_aux. [__cplusplus >= 201103L](_M_initialize_dispatch): Remove. [__cplusplus >= 201103L](_M_assign_dispatch): Remove. [__cplusplus >= 201103L](_M_insert_dispatch): Remove. * testsuite/23_containers/deque/allocator/default_init.cc: New. From-SVN: r271330 --- libstdc++-v3/ChangeLog | 29 +++ libstdc++-v3/include/bits/deque.tcc | 236 +++++++++--------- libstdc++-v3/include/bits/stl_deque.h | 181 ++++++++------ .../deque/allocator/default_init.cc | 67 +++++ 4 files changed, 320 insertions(+), 193 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d310cb0cc5c..dbf1a8865f6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,32 @@ +2019-05-17 François Dumont + + * include/bits/stl_deque.h + (_Deque_iterator<>::__ptr_to): Remove, use std::__ptr_rebind. + (_Deque_base(_Deque_base&&, const allocator_type&)): New. + (_Deque_base::_Deque_impl_data): New. + (_Deque_base::_Deque_impl): Inherit latter. + (_Deque_base::_Deque_impl::_M_swap_data): Move... + (_Deque_base::_Deque_impl_data::_M_swap_data): ... here. + (_Deque_base::_Deque_impl()): Add noexcept qualification. + (_Deque_base::_Deque_impl(_Deque_impl&&, _Tp_alloc_type&&)): New. + (_Deque_base::_Deque_impl::_M_get_Tp_allocator()): Remove static_cast. + (deque<>::deque()): Default. + (deque<>::deque(deque&&)): Default. + (deque<>::deque(deque&&, const allocator_type&, false_type)): New. + (deque<>::deque(deque&&, const allocator_type&, true_type)): New. + (deque<>::deque(deque&&, const allocator_type&)): Delegate to latters. + (deque<>::deque<_It>(_It, _It, const allocator_type&)): Use + _M_range_initialize. + (deque<>::assign<_It>(_It, _It)): Use _M_assign_aux. + (deque<>::resize(size_type, const value_type&)): Share a single + implementation. + (deque<>::insert<_It>(const_iterator, _It, _It)): Use + _M_range_insert_aux. + [__cplusplus >= 201103L](_M_initialize_dispatch): Remove. + [__cplusplus >= 201103L](_M_assign_dispatch): Remove. + [__cplusplus >= 201103L](_M_insert_dispatch): Remove. + * testsuite/23_containers/deque/allocator/default_init.cc: New. + 2019-05-17 Jonathan Wakely PR libstdc++/90246 diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index 9679ec09119..3f77b4f079c 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -69,22 +69,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Map_pointer __cur; __try - { - for (__cur = this->_M_impl._M_start._M_node; + { + for (__cur = this->_M_impl._M_start._M_node; __cur < this->_M_impl._M_finish._M_node; ++__cur) - std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(), + std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(), _M_get_Tp_allocator()); - std::__uninitialized_default_a(this->_M_impl._M_finish._M_first, + std::__uninitialized_default_a(this->_M_impl._M_finish._M_first, this->_M_impl._M_finish._M_cur, _M_get_Tp_allocator()); - } + } __catch(...) - { - std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), _M_get_Tp_allocator()); - __throw_exception_again; - } + __throw_exception_again; + } } #endif @@ -99,8 +99,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (_Alloc_traits::_S_propagate_on_copy_assign()) { if (!_Alloc_traits::_S_always_equal() - && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) - { + && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) + { // Replacement allocator cannot free existing storage, // so deallocate everything and take copy of __x's data. _M_replace_map(__x, __x.get_allocator()); @@ -141,8 +141,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) { _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_start._M_cur - 1, - std::forward<_Args>(__args)...); + this->_M_impl._M_start._M_cur - 1, + std::forward<_Args>(__args)...); --this->_M_impl._M_start._M_cur; } else @@ -166,8 +166,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER != this->_M_impl._M_finish._M_last - 1) { _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_finish._M_cur, - std::forward<_Args>(__args)...); + this->_M_impl._M_finish._M_cur, + std::forward<_Args>(__args)...); ++this->_M_impl._M_finish._M_cur; } else @@ -290,13 +290,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_assign_aux(_InputIterator __first, _InputIterator __last, std::input_iterator_tag) { - iterator __cur = begin(); - for (; __first != __last && __cur != end(); ++__cur, (void)++__first) - *__cur = *__first; - if (__first == __last) - _M_erase_at_end(__cur); - else - _M_range_insert_aux(end(), __first, __last, + iterator __cur = begin(); + for (; __first != __last && __cur != end(); ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + _M_range_insert_aux(end(), __first, __last, std::__iterator_category(__first)); } @@ -339,7 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } else - _M_insert_aux(__pos, __n, __x); + _M_insert_aux(__pos, __n, __x); } #if __cplusplus >= 201103L @@ -393,22 +393,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Map_pointer __cur; __try - { - for (__cur = this->_M_impl._M_start._M_node; + { + for (__cur = this->_M_impl._M_start._M_node; __cur < this->_M_impl._M_finish._M_node; ++__cur) - std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), + std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), __value, _M_get_Tp_allocator()); - std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, + std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, this->_M_impl._M_finish._M_cur, __value, _M_get_Tp_allocator()); - } + } __catch(...) - { - std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), _M_get_Tp_allocator()); - __throw_exception_again; - } + __throw_exception_again; + } } template @@ -416,23 +416,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void deque<_Tp, _Alloc>:: _M_range_initialize(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) + std::input_iterator_tag) { - this->_M_initialize_map(0); - __try - { - for (; __first != __last; ++__first) + this->_M_initialize_map(0); + __try + { + for (; __first != __last; ++__first) #if __cplusplus >= 201103L emplace_back(*__first); #else - push_back(*__first); + push_back(*__first); #endif - } - __catch(...) - { - clear(); - __throw_exception_again; - } + } + __catch(...) + { + clear(); + __throw_exception_again; + } } template @@ -440,17 +440,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void deque<_Tp, _Alloc>:: _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) + std::forward_iterator_tag) { - const size_type __n = std::distance(__first, __last); - this->_M_initialize_map(_S_check_init_len(__n, _M_get_Tp_allocator())); - - _Map_pointer __cur_node; - __try - { - for (__cur_node = this->_M_impl._M_start._M_node; - __cur_node < this->_M_impl._M_finish._M_node; - ++__cur_node) + const size_type __n = std::distance(__first, __last); + this->_M_initialize_map(_S_check_init_len(__n, _M_get_Tp_allocator())); + + _Map_pointer __cur_node; + __try + { + for (__cur_node = this->_M_impl._M_start._M_node; + __cur_node < this->_M_impl._M_finish._M_node; + ++__cur_node) { _ForwardIterator __mid = __first; std::advance(__mid, _S_buffer_size()); @@ -458,17 +458,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Tp_allocator()); __first = __mid; } - std::__uninitialized_copy_a(__first, __last, + std::__uninitialized_copy_a(__first, __last, this->_M_impl._M_finish._M_first, _M_get_Tp_allocator()); - } - __catch(...) - { - std::_Destroy(this->_M_impl._M_start, + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur_node, __cur_node), _M_get_Tp_allocator()); - __throw_exception_again; - } + __throw_exception_again; + } } // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1. @@ -494,8 +494,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { #if __cplusplus >= 201103L _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_finish._M_cur, - std::forward<_Args>(__args)...); + this->_M_impl._M_finish._M_cur, + std::forward<_Args>(__args)...); #else this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t); #endif @@ -536,8 +536,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1; #if __cplusplus >= 201103L _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_start._M_cur, - std::forward<_Args>(__args)...); + this->_M_impl._M_start._M_cur, + std::forward<_Args>(__args)...); #else this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t); #endif @@ -583,8 +583,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void deque<_Tp, _Alloc>:: _M_range_insert_aux(iterator __pos, - _InputIterator __first, _InputIterator __last, - std::input_iterator_tag) + _InputIterator __first, _InputIterator __last, + std::input_iterator_tag) { std::copy(__first, __last, std::inserter(*this, __pos)); } template @@ -592,11 +592,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void deque<_Tp, _Alloc>:: _M_range_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) + _ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) { - const size_type __n = std::distance(__first, __last); - if (__pos._M_cur == this->_M_impl._M_start._M_cur) + const size_type __n = std::distance(__first, __last); + if (__pos._M_cur == this->_M_impl._M_start._M_cur) { iterator __new_start = _M_reserve_elements_at_front(__n); __try @@ -612,7 +612,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __throw_exception_again; } } - else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) + else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) { iterator __new_finish = _M_reserve_elements_at_back(__n); __try @@ -629,8 +629,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __throw_exception_again; } } - else - _M_insert_aux(__pos, __first, __last, __n); + else + _M_insert_aux(__pos, __first, __last, __n); } template @@ -765,12 +765,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void deque<_Tp, _Alloc>:: _M_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - size_type __n) + _ForwardIterator __first, _ForwardIterator __last, + size_type __n) { - const difference_type __elemsbefore = __pos - this->_M_impl._M_start; - const size_type __length = size(); - if (static_cast(__elemsbefore) < __length / 2) + const difference_type __elemsbefore = __pos - this->_M_impl._M_start; + const size_type __length = size(); + if (static_cast(__elemsbefore) < __length / 2) { iterator __new_start = _M_reserve_elements_at_front(__n); iterator __old_start = this->_M_impl._M_start; @@ -807,16 +807,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __throw_exception_again; } } - else - { - iterator __new_finish = _M_reserve_elements_at_back(__n); - iterator __old_finish = this->_M_impl._M_finish; - const difference_type __elemsafter = - difference_type(__length) - __elemsbefore; - __pos = this->_M_impl._M_finish - __elemsafter; - __try - { - if (__elemsafter > difference_type(__n)) + else + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = this->_M_impl._M_finish; + const difference_type __elemsafter = + difference_type(__length) - __elemsbefore; + __pos = this->_M_impl._M_finish - __elemsafter; + __try + { + if (__elemsafter > difference_type(__n)) { iterator __finish_n = (this->_M_impl._M_finish - difference_type(__n)); @@ -828,7 +828,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); std::copy(__first, __last, __pos); } - else + else { _ForwardIterator __mid = __first; std::advance(__mid, __elemsafter); @@ -839,14 +839,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_finish = __new_finish; std::copy(__first, __mid, __pos); } - } - __catch(...) - { - _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, __new_finish._M_node + 1); - __throw_exception_again; - } - } + __throw_exception_again; + } + } } template @@ -884,16 +884,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_reserve_map_at_front(__new_nodes); size_type __i; __try - { - for (__i = 1; __i <= __new_nodes; ++__i) - *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node(); - } + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node(); + } __catch(...) - { - for (size_type __j = 1; __j < __i; ++__j) - _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j)); - __throw_exception_again; - } + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j)); + __throw_exception_again; + } } template @@ -909,16 +909,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_reserve_map_at_back(__new_nodes); size_type __i; __try - { - for (__i = 1; __i <= __new_nodes; ++__i) - *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node(); - } + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node(); + } __catch(...) - { - for (size_type __j = 1; __j < __i; ++__j) - _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j)); - __throw_exception_again; - } + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j)); + __throw_exception_again; + } } template @@ -935,7 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size - __new_num_nodes) / 2 - + (__add_at_front ? __nodes_to_add : 0); + + (__add_at_front ? __nodes_to_add : 0); if (__new_nstart < this->_M_impl._M_start._M_node) std::copy(this->_M_impl._M_start._M_node, this->_M_impl._M_finish._M_node + 1, @@ -948,12 +948,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER else { size_type __new_map_size = this->_M_impl._M_map_size - + std::max(this->_M_impl._M_map_size, + + std::max(this->_M_impl._M_map_size, __nodes_to_add) + 2; _Map_pointer __new_map = this->_M_allocate_map(__new_map_size); __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 - + (__add_at_front ? __nodes_to_add : 0); + + (__add_at_front ? __nodes_to_add : 0); std::copy(this->_M_impl._M_start._M_node, this->_M_impl._M_finish._M_node + 1, __new_nstart); diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index d0b46c671d3..7dcb53823c4 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -110,21 +110,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct _Deque_iterator { #if __cplusplus < 201103L - typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; - typedef _Tp* _Elt_pointer; - typedef _Tp** _Map_pointer; + typedef _Tp* _Elt_pointer; + typedef _Tp** _Map_pointer; #else private: - template - using __ptr_to = typename pointer_traits<_Ptr>::template rebind<_Up>; template - using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_to<_CvTp>>; + using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_rebind<_Ptr, _CvTp>>; public: - typedef __iter<_Tp> iterator; - typedef __iter const_iterator; - typedef __ptr_to<_Tp> _Elt_pointer; - typedef __ptr_to<_Elt_pointer> _Map_pointer; + typedef __iter<_Tp> iterator; + typedef __iter const_iterator; + typedef __ptr_rebind<_Ptr, _Tp> _Elt_pointer; + typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer; #endif static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT @@ -158,11 +156,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #else // Conversion from iterator to const_iterator. template, - is_same<_Iter, iterator>>> + typename = _Require, + is_same<_Iter, iterator>>> _Deque_iterator(const _Iter& __x) noexcept : _M_cur(__x._M_cur), _M_first(__x._M_first), - _M_last(__x._M_last), _M_node(__x._M_node) { } + _M_last(__x._M_last), _M_node(__x._M_node) { } _Deque_iterator(const _Deque_iterator&) = default; _Deque_iterator& operator=(const _Deque_iterator&) = default; @@ -473,7 +471,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Map_alloc_type; typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; - public: typedef _Alloc allocator_type; allocator_type @@ -508,6 +505,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_swap_data(__x._M_impl); } + _Deque_base(_Deque_base&& __x, const allocator_type& __a) + : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) + { __x._M_initialize_map(0); } + _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_t __n) : _M_impl(__a) { @@ -528,56 +529,73 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ~_Deque_base() _GLIBCXX_NOEXCEPT; - protected: typedef typename iterator::_Map_pointer _Map_pointer; - //This struct encapsulates the implementation of the std::deque - //standard container and at the same time makes use of the EBO - //for empty allocators. - struct _Deque_impl - : public _Tp_alloc_type + struct _Deque_impl_data { _Map_pointer _M_map; size_t _M_map_size; iterator _M_start; iterator _M_finish; - _Deque_impl() - : _Tp_alloc_type(), _M_map(), _M_map_size(0), - _M_start(), _M_finish() + _Deque_impl_data() _GLIBCXX_NOEXCEPT + : _M_map(), _M_map_size(), _M_start(), _M_finish() + { } + +#if __cplusplus >= 201103L + _Deque_impl_data(const _Deque_impl_data&) = default; + _Deque_impl_data& + operator=(const _Deque_impl_data&) = default; + + _Deque_impl_data(_Deque_impl_data&& __x) noexcept + : _Deque_impl_data(__x) + { __x = _Deque_impl_data(); } +#endif + + void + _M_swap_data(_Deque_impl_data& __x) _GLIBCXX_NOEXCEPT + { + // Do not use std::swap(_M_start, __x._M_start), etc as it loses + // information used by TBAA. + std::swap(*this, __x); + } + }; + + // This struct encapsulates the implementation of the std::deque + // standard container and at the same time makes use of the EBO + // for empty allocators. + struct _Deque_impl + : public _Tp_alloc_type, public _Deque_impl_data + { + _Deque_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Tp_alloc_type>::value) + : _Tp_alloc_type() { } _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _Tp_alloc_type(__a), _M_map(), _M_map_size(0), - _M_start(), _M_finish() + : _Tp_alloc_type(__a) { } #if __cplusplus >= 201103L _Deque_impl(_Deque_impl&&) = default; _Deque_impl(_Tp_alloc_type&& __a) noexcept - : _Tp_alloc_type(std::move(__a)), _M_map(), _M_map_size(0), - _M_start(), _M_finish() + : _Tp_alloc_type(std::move(__a)) { } -#endif - void _M_swap_data(_Deque_impl& __x) _GLIBCXX_NOEXCEPT - { - using std::swap; - swap(this->_M_start, __x._M_start); - swap(this->_M_finish, __x._M_finish); - swap(this->_M_map, __x._M_map); - swap(this->_M_map_size, __x._M_map_size); - } + _Deque_impl(_Deque_impl&& __d, _Tp_alloc_type&& __a) + : _Tp_alloc_type(std::move(__a)), _Deque_impl_data(std::move(__d)) + { } +#endif }; _Tp_alloc_type& _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT - { return *static_cast<_Tp_alloc_type*>(&this->_M_impl); } + { return this->_M_impl; } const _Tp_alloc_type& _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT - { return *static_cast(&this->_M_impl); } + { return this->_M_impl; } _Map_alloc_type _M_get_map_allocator() const _GLIBCXX_NOEXCEPT @@ -611,7 +629,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Map_alloc_traits::deallocate(__map_alloc, __p, __n); } - protected: void _M_initialize_map(size_t); void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish); void _M_destroy_nodes(_Map_pointer __nstart, @@ -646,7 +663,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Deque_base<_Tp, _Alloc>:: _M_initialize_map(size_t __num_elements) { - const size_t __num_nodes = (__num_elements/ __deque_buf_size(sizeof(_Tp)) + const size_t __num_nodes = (__num_elements / __deque_buf_size(sizeof(_Tp)) + 1); this->_M_impl._M_map_size = std::max((size_t) _S_initial_map_size, @@ -832,7 +849,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef ptrdiff_t difference_type; typedef _Alloc allocator_type; - protected: + private: static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT { return __deque_buf_size(sizeof(_Tp)); } @@ -859,7 +876,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Creates a %deque with no elements. */ - deque() : _Base() { } +#if __cplusplus >= 201103L + deque() = default; +#else + deque() { } +#endif /** * @brief Creates a %deque with no elements. @@ -928,13 +949,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L /** * @brief %Deque move constructor. - * @param __x A %deque of identical element and allocator types. * - * The newly-created %deque contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %deque. + * The newly-created %deque contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %deque. */ - deque(deque&& __x) - : _Base(std::move(__x)) { } + deque(deque&&) = default; /// Copy constructor with alternative allocator deque(const deque& __x, const allocator_type& __a) @@ -945,9 +966,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Move constructor with alternative allocator deque(deque&& __x, const allocator_type& __a) + : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) + { } + + private: + deque(deque&& __x, const allocator_type& __a, true_type) + : _Base(std::move(__x), __a) + { } + + deque(deque&& __x, const allocator_type& __a, false_type) : _Base(std::move(__x), __a, __x.size()) { - if (__x.get_allocator() != __a) + if (__x.get_allocator() != __a && !__x.empty()) { std::__uninitialized_move_a(__x.begin(), __x.end(), this->_M_impl._M_start, @@ -956,6 +986,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + public: /** * @brief Builds a %deque from an initializer list. * @param __l An initializer_list. @@ -997,7 +1028,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { _M_initialize_dispatch(__first, __last, __false_type()); } + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } #else template deque(_InputIterator __first, _InputIterator __last, @@ -1098,7 +1132,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typename = std::_RequireInputIter<_InputIterator>> void assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } #else template void @@ -1284,14 +1318,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void resize(size_type __new_size, const value_type& __x) - { - const size_type __len = size(); - if (__new_size > __len) - _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); - else if (__new_size < __len) - _M_erase_at_end(this->_M_impl._M_start - + difference_type(__new_size)); - } #else /** * @brief Resizes the %deque to the specified number of elements. @@ -1306,6 +1332,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void resize(size_type __new_size, value_type __x = value_type()) +#endif { const size_type __len = size(); if (__new_size > __len) @@ -1314,7 +1341,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_erase_at_end(this->_M_impl._M_start + difference_type(__new_size)); } -#endif #if __cplusplus >= 201103L /** A non-binding request to reduce memory use. */ @@ -1555,7 +1581,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_last - 1) { - _Alloc_traits::destroy(this->_M_impl, + _Alloc_traits::destroy(_M_get_Tp_allocator(), this->_M_impl._M_start._M_cur); ++this->_M_impl._M_start._M_cur; } @@ -1579,7 +1605,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER != this->_M_impl._M_finish._M_first) { --this->_M_impl._M_finish._M_cur; - _Alloc_traits::destroy(this->_M_impl, + _Alloc_traits::destroy(_M_get_Tp_allocator(), this->_M_impl._M_finish._M_cur); } else @@ -1643,6 +1669,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Inserts an initializer list into the %deque. * @param __p An iterator into the %deque. * @param __l An initializer_list. + * @return An iterator that points to the inserted data. * * This function will insert copies of the data in the * initializer_list @a __l into the %deque before the location @@ -1656,9 +1683,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::random_access_iterator_tag()); return begin() + __offset; } -#endif -#if __cplusplus >= 201103L /** * @brief Inserts a number of copies of given data into the %deque. * @param __position A const_iterator into the %deque. @@ -1710,8 +1735,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _InputIterator __last) { difference_type __offset = __position - cbegin(); - _M_insert_dispatch(__position._M_const_cast(), - __first, __last, __false_type()); + _M_range_insert_aux(__position._M_const_cast(), __first, __last, + std::__iterator_category(__first)); return begin() + __offset; } #else @@ -1817,6 +1842,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER protected: // Internal constructor functions follow. +#if __cplusplus < 201103L // called by the range constructor to implement [23.1.1]/9 // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1830,6 +1856,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_fill_initialize(__x); } + // called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#endif + static size_t _S_check_init_len(size_t __n, const allocator_type& __a) { @@ -1847,16 +1884,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return (std::min)(__diffmax, __allocmax); } - // called by the range constructor to implement [23.1.1]/9 - template - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { - _M_range_initialize(__first, __last, - std::__iterator_category(__first)); - } - // called by the second initialize_dispatch above //@{ /** @@ -1903,6 +1930,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Internal assign functions follow. The *_aux functions do the actual // assignment work for the range versions. +#if __cplusplus < 201103L // called by the range assign to implement [23.1.1]/9 // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1918,6 +1946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type) { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#endif // called by the second assign_dispatch above template @@ -1983,6 +2012,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Internal insert functions follow. The *_aux functions do the actual // insertion work when all shortcuts fail. +#if __cplusplus < 201103L // called by the range insert to implement [23.1.1]/9 // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -2003,6 +2033,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_range_insert_aux(__pos, __first, __last, std::__iterator_category(__first)); } +#endif // called by the second insert_dispatch above template diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc new file mode 100644 index 00000000000..f6cc61e1fb8 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } +// { dg-options "-O0" } +// { dg-xfail-run-if "PR c++/65816" { *-*-* } } + +#include +#include +#include + +#include + +using T = int; + +using __gnu_test::default_init_allocator; + +void test01() +{ + typedef default_init_allocator alloc_type; + typedef std::deque test_type; + + __gnu_cxx::__aligned_buffer buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type; + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +void test02() +{ + typedef default_init_allocator alloc_type; + typedef std::deque test_type; + + __gnu_cxx::__aligned_buffer buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type(); + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +int main() +{ + test01(); + test02(); + return 0; +} -- 2.30.2