From: François Dumont Date: Wed, 10 Jan 2018 16:59:02 +0000 (+0000) Subject: 2018-01-10 François Dumont X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=75ce74bbdd695ae793c03f93cfd55842806651e6;p=gcc.git 2018-01-10 François Dumont * include/bits/forward_list.h (_Fwd_list_node_base(_Fwd_list_node_base&&)): New. (_Fwd_list_node_base& operator=(_Fwd_list_node_base&&)): New. (_Fwd_list_node_base(const _Fwd_list_node_base&)): Explicit delete. (_Fwd_list_node_base& operator=(const _Fwd_list_node_base&)): Likewise. (_Fwd_list_impl()): Add noexcept qualification. (_Fwd_list_impl(const _Node_alloc_type&)): Delete. (_Fwd_list_impl(_Fwd_list_impl&&)): New, default. (_Fwd_list_impl(_Fwd_list_impl&&, _Node_alloc_type&&)): New. (_Fwd_list_base()): Default. (_Fwd_list_base(_Fwd_list_base&&, _Node_alloc_type&&, true_type)): New. (_Fwd_list_base(_Fwd_list_base&&)): Default. (forward_list<>()): Default. (forward_list<>(forward_list&&)): Default. (forward_list(forward_list&&, _Node_alloc_type&&, false_type)): New. (forward_list(forward_list&&, _Node_alloc_type&&, true_type)): New. (forward_list(forward_list&&, const _Alloc&)): Adapt to use latters. * include/bits/forward_list.tcc (_Fwd_list_base(_Fwd_list_base&&, _Node_alloc_type&&)): Adapt to use _M_impl._M_head move assignment. (forward_list<>::merge(forward_list<>&&, _Comp)): Likewise. * testsuite/23_containers/forward_list/allocator/default_init.cc: New. From-SVN: r256439 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6c5a2741ba8..46908d32ef6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,28 @@ +2018-01-10 François Dumont + + * include/bits/forward_list.h + (_Fwd_list_node_base(_Fwd_list_node_base&&)): New. + (_Fwd_list_node_base& operator=(_Fwd_list_node_base&&)): New. + (_Fwd_list_node_base(const _Fwd_list_node_base&)): Explicit delete. + (_Fwd_list_node_base& operator=(const _Fwd_list_node_base&)): Likewise. + (_Fwd_list_impl()): Add noexcept qualification. + (_Fwd_list_impl(const _Node_alloc_type&)): Delete. + (_Fwd_list_impl(_Fwd_list_impl&&)): New, default. + (_Fwd_list_impl(_Fwd_list_impl&&, _Node_alloc_type&&)): New. + (_Fwd_list_base()): Default. + (_Fwd_list_base(_Fwd_list_base&&, _Node_alloc_type&&, true_type)): New. + (_Fwd_list_base(_Fwd_list_base&&)): Default. + (forward_list<>()): Default. + (forward_list<>(forward_list&&)): Default. + (forward_list(forward_list&&, _Node_alloc_type&&, false_type)): New. + (forward_list(forward_list&&, _Node_alloc_type&&, true_type)): New. + (forward_list(forward_list&&, const _Alloc&)): Adapt to use latters. + * include/bits/forward_list.tcc + (_Fwd_list_base(_Fwd_list_base&&, _Node_alloc_type&&)): Adapt to use + _M_impl._M_head move assignment. + (forward_list<>::merge(forward_list<>&&, _Comp)): Likewise. + * testsuite/23_containers/forward_list/allocator/default_init.cc: New. + 2018-01-09 Jonathan Wakely PR libstdc++/80276 diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index 47fe3217839..b40256bd104 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -54,6 +54,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct _Fwd_list_node_base { _Fwd_list_node_base() = default; + _Fwd_list_node_base(_Fwd_list_node_base&& __x) noexcept + : _M_next(__x._M_next) + { __x._M_next = nullptr; } + + _Fwd_list_node_base(const _Fwd_list_node_base&) = delete; + _Fwd_list_node_base& operator=(const _Fwd_list_node_base&) = delete; + + _Fwd_list_node_base& + operator=(_Fwd_list_node_base&& __x) noexcept + { + _M_next = __x._M_next; + __x._M_next = nullptr; + return *this; + } _Fwd_list_node_base* _M_next = nullptr; @@ -68,7 +82,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __end->_M_next = _M_next; } else - __begin->_M_next = 0; + __begin->_M_next = nullptr; _M_next = __keep; return __end; } @@ -114,20 +128,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief A forward_list::iterator. - * + * * All the functions are op overloads. */ template struct _Fwd_list_iterator { - typedef _Fwd_list_iterator<_Tp> _Self; - typedef _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_iterator<_Tp> _Self; + typedef _Fwd_list_node<_Tp> _Node; - typedef _Tp value_type; - typedef _Tp* pointer; - typedef _Tp& reference; - typedef ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; _Fwd_list_iterator() noexcept : _M_node() { } @@ -147,16 +161,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Self& operator++() noexcept { - _M_node = _M_node->_M_next; - return *this; + _M_node = _M_node->_M_next; + return *this; } _Self operator++(int) noexcept { - _Self __tmp(*this); - _M_node = _M_node->_M_next; - return __tmp; + _Self __tmp(*this); + _M_node = _M_node->_M_next; + return __tmp; } bool @@ -170,10 +184,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Self _M_next() const noexcept { - if (_M_node) - return _Fwd_list_iterator(_M_node->_M_next); - else - return _Fwd_list_iterator(0); + if (_M_node) + return _Fwd_list_iterator(_M_node->_M_next); + else + return _Fwd_list_iterator(nullptr); } _Fwd_list_node_base* _M_node; @@ -181,21 +195,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief A forward_list::const_iterator. - * + * * All the functions are op overloads. */ template struct _Fwd_list_const_iterator { - typedef _Fwd_list_const_iterator<_Tp> _Self; - typedef const _Fwd_list_node<_Tp> _Node; - typedef _Fwd_list_iterator<_Tp> iterator; + typedef _Fwd_list_const_iterator<_Tp> _Self; + typedef const _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_iterator<_Tp> iterator; - typedef _Tp value_type; - typedef const _Tp* pointer; - typedef const _Tp& reference; - typedef ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; _Fwd_list_const_iterator() noexcept : _M_node() { } @@ -218,16 +232,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Self& operator++() noexcept { - _M_node = _M_node->_M_next; - return *this; + _M_node = _M_node->_M_next; + return *this; } _Self operator++(int) noexcept { - _Self __tmp(*this); - _M_node = _M_node->_M_next; - return __tmp; + _Self __tmp(*this); + _M_node = _M_node->_M_next; + return __tmp; } bool @@ -241,10 +255,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Self _M_next() const noexcept { - if (this->_M_node) - return _Fwd_list_const_iterator(_M_node->_M_next); - else - return _Fwd_list_const_iterator(0); + if (this->_M_node) + return _Fwd_list_const_iterator(_M_node->_M_next); + else + return _Fwd_list_const_iterator(nullptr); } const _Fwd_list_node_base* _M_node; @@ -256,7 +270,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template inline bool operator==(const _Fwd_list_iterator<_Tp>& __x, - const _Fwd_list_const_iterator<_Tp>& __y) noexcept + const _Fwd_list_const_iterator<_Tp>& __y) noexcept { return __x._M_node == __y._M_node; } /** @@ -265,7 +279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template inline bool operator!=(const _Fwd_list_iterator<_Tp>& __x, - const _Fwd_list_const_iterator<_Tp>& __y) noexcept + const _Fwd_list_const_iterator<_Tp>& __y) noexcept { return __x._M_node != __y._M_node; } /** @@ -279,30 +293,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef __alloc_rebind<_Alloc, _Fwd_list_node<_Tp>> _Node_alloc_type; typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; - struct _Fwd_list_impl + struct _Fwd_list_impl : public _Node_alloc_type { - _Fwd_list_node_base _M_head; + _Fwd_list_node_base _M_head; + + _Fwd_list_impl() + noexcept( noexcept(_Node_alloc_type()) ) + : _Node_alloc_type(), _M_head() + { } - _Fwd_list_impl() - : _Node_alloc_type(), _M_head() - { } + _Fwd_list_impl(_Fwd_list_impl&&) = default; - _Fwd_list_impl(const _Node_alloc_type& __a) - : _Node_alloc_type(__a), _M_head() - { } + _Fwd_list_impl(_Fwd_list_impl&& __fl, _Node_alloc_type&& __a) + : _Node_alloc_type(std::move(__a)), _M_head(std::move(__fl._M_head)) + { } - _Fwd_list_impl(_Node_alloc_type&& __a) + _Fwd_list_impl(_Node_alloc_type&& __a) : _Node_alloc_type(std::move(__a)), _M_head() - { } + { } }; _Fwd_list_impl _M_impl; public: - typedef _Fwd_list_iterator<_Tp> iterator; - typedef _Fwd_list_const_iterator<_Tp> const_iterator; - typedef _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_iterator<_Tp> iterator; + typedef _Fwd_list_const_iterator<_Tp> const_iterator; + typedef _Fwd_list_node<_Tp> _Node; _Node_alloc_type& _M_get_Node_allocator() noexcept @@ -312,26 +329,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Node_allocator() const noexcept { return this->_M_impl; } - _Fwd_list_base() - : _M_impl() { } + _Fwd_list_base() = default; _Fwd_list_base(_Node_alloc_type&& __a) : _M_impl(std::move(__a)) { } + // When allocators are always equal. + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a, + std::true_type) + : _M_impl(std::move(__lst._M_impl), std::move(__a)) + { } + + // When allocators are not always equal. _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a); - _Fwd_list_base(_Fwd_list_base&& __lst) - : _M_impl(std::move(__lst._M_get_Node_allocator())) - { - this->_M_impl._M_head._M_next = __lst._M_impl._M_head._M_next; - __lst._M_impl._M_head._M_next = 0; - } + _Fwd_list_base(_Fwd_list_base&&) = default; ~_Fwd_list_base() - { _M_erase_after(&_M_impl._M_head, 0); } + { _M_erase_after(&_M_impl._M_head, nullptr); } protected: - _Node* _M_get_node() { @@ -340,29 +357,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template - _Node* - _M_create_node(_Args&&... __args) - { - _Node* __node = this->_M_get_node(); - __try - { + _Node* + _M_create_node(_Args&&... __args) + { + _Node* __node = this->_M_get_node(); + __try + { _Tp_alloc_type __a(_M_get_Node_allocator()); typedef allocator_traits<_Tp_alloc_type> _Alloc_traits; ::new ((void*)__node) _Node; _Alloc_traits::construct(__a, __node->_M_valptr(), std::forward<_Args>(__args)...); - } - __catch(...) - { - this->_M_put_node(__node); - __throw_exception_again; - } - return __node; - } + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } template - _Fwd_list_node_base* - _M_insert_after(const_iterator __pos, _Args&&... __args); + _Fwd_list_node_base* + _M_insert_after(const_iterator __pos, _Args&&... __args); void _M_put_node(_Node* __p) @@ -376,8 +393,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_erase_after(_Fwd_list_node_base* __pos); _Fwd_list_node_base* - _M_erase_after(_Fwd_list_node_base* __pos, - _Fwd_list_node_base* __last); + _M_erase_after(_Fwd_list_node_base* __pos, + _Fwd_list_node_base* __last); }; /** @@ -417,37 +434,34 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif private: - typedef _Fwd_list_base<_Tp, _Alloc> _Base; - typedef _Fwd_list_node<_Tp> _Node; - typedef _Fwd_list_node_base _Node_base; - typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; - typedef typename _Base::_Node_alloc_type _Node_alloc_type; - typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; + typedef _Fwd_list_base<_Tp, _Alloc> _Base; + typedef _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_node_base _Node_base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef typename _Base::_Node_alloc_type _Node_alloc_type; + typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; public: // types: - typedef _Tp value_type; - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - - typedef _Fwd_list_iterator<_Tp> iterator; - typedef _Fwd_list_const_iterator<_Tp> const_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef _Alloc allocator_type; + typedef _Tp value_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef _Fwd_list_iterator<_Tp> iterator; + typedef _Fwd_list_const_iterator<_Tp> const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef _Alloc allocator_type; // 23.3.4.2 construct/copy/destroy: /** * @brief Creates a %forward_list with no elements. */ - forward_list() - noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value) - : _Base() - { } + forward_list() = default; /** * @brief Creates a %forward_list with no elements. @@ -458,7 +472,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _Base(_Node_alloc_type(__al)) { } - /** * @brief Copy constructor with allocator argument. * @param __list Input list to copy. @@ -468,14 +481,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _Base(_Node_alloc_type(__al)) { _M_range_initialize(__list.begin(), __list.end()); } - /** - * @brief Move constructor with allocator argument. - * @param __list Input list to move. - * @param __al An allocator object. - */ - forward_list(forward_list&& __list, const _Alloc& __al) - noexcept(_Node_alloc_traits::_S_always_equal()) - : _Base(std::move(__list), _Node_alloc_type(__al)) + private: + forward_list(forward_list&& __list, _Node_alloc_type&& __al, + false_type) + : _Base(std::move(__list), std::move(__al)) { // If __list is not empty it means its allocator is not equal to __a, // so we need to move from each element individually. @@ -484,6 +493,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::__make_move_if_noexcept_iterator(__list.end())); } + forward_list(forward_list&& __list, _Node_alloc_type&& __al, + true_type) + noexcept + : _Base(std::move(__list), _Node_alloc_type(__al), true_type{}) + { } + + public: + /** + * @brief Move constructor with allocator argument. + * @param __list Input list to move. + * @param __al An allocator object. + */ + forward_list(forward_list&& __list, const _Alloc& __al) + noexcept(_Node_alloc_traits::_S_always_equal()) + : forward_list(std::move(__list), _Node_alloc_type(__al), + typename _Node_alloc_traits::is_always_equal{}) + { } + /** * @brief Creates a %forward_list with default constructed elements. * @param __n The number of elements to initially create. @@ -507,7 +534,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @a __value. */ forward_list(size_type __n, const _Tp& __value, - const _Alloc& __al = _Alloc()) + const _Alloc& __al = _Alloc()) : _Base(_Node_alloc_type(__al)) { _M_fill_initialize(__n, __value); } @@ -523,10 +550,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template> - forward_list(_InputIterator __first, _InputIterator __last, - const _Alloc& __al = _Alloc()) + forward_list(_InputIterator __first, _InputIterator __last, + const _Alloc& __al = _Alloc()) : _Base(_Node_alloc_type(__al)) - { _M_range_initialize(__first, __last); } + { _M_range_initialize(__first, __last); } /** * @brief The %forward_list copy constructor. @@ -535,7 +562,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ forward_list(const forward_list& __list) : _Base(_Node_alloc_traits::_S_select_on_copy( - __list._M_get_Node_allocator())) + __list._M_get_Node_allocator())) { _M_range_initialize(__list.begin(), __list.end()); } /** @@ -543,12 +570,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __list A %forward_list of identical element and allocator * types. * - * The newly-created %forward_list contains the exact contents of @a - * __list. The contents of @a __list are a valid, but unspecified - * %forward_list. + * The newly-created %forward_list contains the exact contents of the + * moved instance. The contents of the moved instance are a valid, but + * unspecified %forward_list. */ - forward_list(forward_list&& __list) noexcept - : _Base(std::move(__list)) { } + forward_list(forward_list&&) = default; /** * @brief Builds a %forward_list from an initializer_list @@ -559,7 +585,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * in the initializer_list @a __il. This is linear in __il.size(). */ forward_list(std::initializer_list<_Tp> __il, - const _Alloc& __al = _Alloc()) + const _Alloc& __al = _Alloc()) : _Base(_Node_alloc_type(__al)) { _M_range_initialize(__il.begin(), __il.end()); } @@ -597,10 +623,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator=(forward_list&& __list) noexcept(_Node_alloc_traits::_S_nothrow_move()) { - constexpr bool __move_storage = - _Node_alloc_traits::_S_propagate_on_move_assign() - || _Node_alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__list), __bool_constant<__move_storage>()); + constexpr bool __move_storage = + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__list), __bool_constant<__move_storage>()); return *this; } @@ -615,8 +641,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER forward_list& operator=(std::initializer_list<_Tp> __il) { - assign(__il); - return *this; + assign(__il); + return *this; } /** @@ -634,8 +660,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template> void - assign(_InputIterator __first, _InputIterator __last) - { + assign(_InputIterator __first, _InputIterator __last) + { typedef is_assignable<_Tp, decltype(*__first)> __assignable; _M_assign(__first, __last, __assignable()); } @@ -714,7 +740,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator end() noexcept - { return iterator(0); } + { return iterator(nullptr); } /** * Returns a read-only iterator that points one past the last @@ -723,7 +749,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_iterator end() const noexcept - { return const_iterator(0); } + { return const_iterator(nullptr); } /** * Returns a read-only (constant) iterator that points to the @@ -750,7 +776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_iterator cend() const noexcept - { return const_iterator(0); } + { return const_iterator(nullptr); } /** * Returns true if the %forward_list is empty. (Thus begin() would @@ -758,7 +784,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ bool empty() const noexcept - { return this->_M_impl._M_head._M_next == 0; } + { return this->_M_impl._M_head._M_next == nullptr; } /** * Returns the largest possible number of elements of %forward_list. @@ -776,8 +802,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference front() { - _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); - return *__front->_M_valptr(); + _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); + return *__front->_M_valptr(); } /** @@ -787,8 +813,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const_reference front() const { - _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); - return *__front->_M_valptr(); + _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); + return *__front->_M_valptr(); } // 23.3.4.5 modifiers: @@ -806,14 +832,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template #if __cplusplus > 201402L - reference + reference #else void #endif - emplace_front(_Args&&... __args) - { + emplace_front(_Args&&... __args) + { this->_M_insert_after(cbefore_begin(), - std::forward<_Args>(__args)...); + std::forward<_Args>(__args)...); #if __cplusplus > 201402L return front(); #endif @@ -870,10 +896,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * and references. */ template - iterator - emplace_after(const_iterator __pos, _Args&&... __args) - { return iterator(this->_M_insert_after(__pos, - std::forward<_Args>(__args)...)); } + iterator + emplace_after(const_iterator __pos, _Args&&... __args) + { return iterator(this->_M_insert_after(__pos, + std::forward<_Args>(__args)...)); } /** * @brief Inserts given value into %forward_list after specified @@ -933,9 +959,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template> - iterator - insert_after(const_iterator __pos, - _InputIterator __first, _InputIterator __last); + iterator + insert_after(const_iterator __pos, + _InputIterator __first, _InputIterator __last); /** * @brief Inserts the contents of an initializer_list into @@ -1018,10 +1044,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void swap(forward_list& __list) noexcept { - std::swap(this->_M_impl._M_head._M_next, + std::swap(this->_M_impl._M_head._M_next, __list._M_impl._M_head._M_next); _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), - __list._M_get_Node_allocator()); + __list._M_get_Node_allocator()); } /** @@ -1063,7 +1089,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void clear() noexcept - { this->_M_erase_after(&this->_M_impl._M_head, 0); } + { this->_M_erase_after(&this->_M_impl._M_head, nullptr); } // 23.3.4.6 forward_list operations: @@ -1101,11 +1127,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void splice_after(const_iterator __pos, forward_list&& __list, - const_iterator __i) noexcept; + const_iterator __i) noexcept; void splice_after(const_iterator __pos, forward_list& __list, - const_iterator __i) noexcept + const_iterator __i) noexcept { splice_after(__pos, std::move(__list), __i); } /** @@ -1124,12 +1150,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void splice_after(const_iterator __pos, forward_list&&, - const_iterator __before, const_iterator __last) noexcept + const_iterator __before, const_iterator __last) noexcept { _M_splice_after(__pos, __before, __last); } void splice_after(const_iterator __pos, forward_list&, - const_iterator __before, const_iterator __last) noexcept + const_iterator __before, const_iterator __last) noexcept { _M_splice_after(__pos, __before, __last); } // @} @@ -1159,8 +1185,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * responsibility. */ template - void - remove_if(_Pred __pred); + void + remove_if(_Pred __pred); /** * @brief Remove consecutive duplicate elements. @@ -1189,8 +1215,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Managing the pointer is the user's responsibility. */ template - void - unique(_BinPred __binary_pred); + void + unique(_BinPred __binary_pred); /** * @brief Merge sorted lists. @@ -1221,13 +1247,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * according to comp(). */ template - void - merge(forward_list&& __list, _Comp __comp); + void + merge(forward_list&& __list, _Comp __comp); template - void - merge(forward_list& __list, _Comp __comp) - { merge(std::move(__list), __comp); } + void + merge(forward_list& __list, _Comp __comp) + { merge(std::move(__list), __comp); } /** * @brief Sort the elements of the list. @@ -1246,8 +1272,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * elements remain in list order. */ template - void - sort(_Comp __comp); + void + sort(_Comp __comp); /** * @brief Reverse the elements in list. @@ -1261,8 +1287,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER private: // Called by the range constructor to implement [23.3.4.2]/9 template - void - _M_range_initialize(_InputIterator __first, _InputIterator __last); + void + _M_range_initialize(_InputIterator __first, _InputIterator __last); // Called by forward_list(n,v,a), and the range constructor when it // turns out to be the same thing. @@ -1284,22 +1310,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by operator=(forward_list&&) void - _M_move_assign(forward_list&& __list, std::true_type) noexcept + _M_move_assign(forward_list&& __list, true_type) noexcept { - clear(); - this->_M_impl._M_head._M_next = __list._M_impl._M_head._M_next; - __list._M_impl._M_head._M_next = nullptr; - std::__alloc_on_move(this->_M_get_Node_allocator(), - __list._M_get_Node_allocator()); + clear(); + this->_M_impl._M_head._M_next = __list._M_impl._M_head._M_next; + __list._M_impl._M_head._M_next = nullptr; + std::__alloc_on_move(this->_M_get_Node_allocator(), + __list._M_get_Node_allocator()); } // Called by operator=(forward_list&&) void - _M_move_assign(forward_list&& __list, std::false_type) + _M_move_assign(forward_list&& __list, false_type) { - if (__list._M_get_Node_allocator() == this->_M_get_Node_allocator()) - _M_move_assign(std::move(__list), std::true_type()); - else + if (__list._M_get_Node_allocator() == this->_M_get_Node_allocator()) + _M_move_assign(std::move(__list), true_type()); + else // The rvalue's allocator cannot be moved, or is not equal, // so we need to individually move each element. this->assign(std::__make_move_if_noexcept_iterator(__list.begin()), @@ -1310,7 +1336,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // CopyAssignable. template void - _M_assign(_InputIterator __first, _InputIterator __last, true_type) + _M_assign(_InputIterator __first, _InputIterator __last, true_type) { auto __prev = before_begin(); auto __curr = begin(); @@ -1326,13 +1352,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert_after(__prev, __first, __last); else if (__curr != __end) erase_after(__prev, __end); - } + } // Called by assign(_InputIterator, _InputIterator) if _Tp is not // CopyAssignable. template void - _M_assign(_InputIterator __first, _InputIterator __last, false_type) + _M_assign(_InputIterator __first, _InputIterator __last, false_type) { clear(); insert_after(cbefore_begin(), __first, __last); @@ -1383,14 +1409,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __ly A %forward_list of the same type as @a __lx. * @return True iff the elements of the forward lists are equal. * - * This is an equivalence relation. It is linear in the number of + * This is an equivalence relation. It is linear in the number of * elements of the forward lists. Deques are considered equivalent * if corresponding elements compare equal. */ template bool operator==(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly); + const forward_list<_Tp, _Alloc>& __ly); /** * @brief Forward list ordering relation. @@ -1398,7 +1424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @param __ly A %forward_list of the same type as @a __lx. * @return True iff @a __lx is lexicographically less than @a __ly. * - * This is a total ordering relation. It is linear in the number of + * This is a total ordering relation. It is linear in the number of * elements of the forward lists. The elements must be comparable * with @c <. * @@ -1407,7 +1433,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template inline bool operator<(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) + const forward_list<_Tp, _Alloc>& __ly) { return std::lexicographical_compare(__lx.cbegin(), __lx.cend(), __ly.cbegin(), __ly.cend()); } @@ -1415,28 +1441,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template inline bool operator!=(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) + const forward_list<_Tp, _Alloc>& __ly) { return !(__lx == __ly); } /// Based on operator< template inline bool operator>(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) + const forward_list<_Tp, _Alloc>& __ly) { return (__ly < __lx); } /// Based on operator< template inline bool operator>=(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) + const forward_list<_Tp, _Alloc>& __ly) { return !(__lx < __ly); } /// Based on operator< template inline bool operator<=(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) + const forward_list<_Tp, _Alloc>& __ly) { return !(__ly < __lx); } /// See std::forward_list::swap(). diff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc index 8c303412845..3e12cd531d4 100644 --- a/libstdc++-v3/include/bits/forward_list.tcc +++ b/libstdc++-v3/include/bits/forward_list.tcc @@ -41,12 +41,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_impl(std::move(__a)) { if (__lst._M_get_Node_allocator() == _M_get_Node_allocator()) - { - this->_M_impl._M_head._M_next = __lst._M_impl._M_head._M_next; - __lst._M_impl._M_head._M_next = 0; - } - else - this->_M_impl._M_head._M_next = 0; + this->_M_impl._M_head = std::move(__lst._M_impl._M_head); } template @@ -55,12 +50,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Fwd_list_base<_Tp, _Alloc>:: _M_insert_after(const_iterator __pos, _Args&&... __args) { - _Fwd_list_node_base* __to + _Fwd_list_node_base* __to = const_cast<_Fwd_list_node_base*>(__pos._M_node); _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); - __thing->_M_next = __to->_M_next; - __to->_M_next = __thing; - return __to->_M_next; + __thing->_M_next = __to->_M_next; + __to->_M_next = __thing; + return __to->_M_next; } template @@ -80,19 +75,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template _Fwd_list_node_base* _Fwd_list_base<_Tp, _Alloc>:: - _M_erase_after(_Fwd_list_node_base* __pos, - _Fwd_list_node_base* __last) + _M_erase_after(_Fwd_list_node_base* __pos, + _Fwd_list_node_base* __last) { _Node* __curr = static_cast<_Node*>(__pos->_M_next); while (__curr != __last) - { - _Node* __temp = __curr; - __curr = static_cast<_Node*>(__curr->_M_next); + { + _Node* __temp = __curr; + __curr = static_cast<_Node*>(__curr->_M_next); _Tp_alloc_type __a(_M_get_Node_allocator()); allocator_traits<_Tp_alloc_type>::destroy(__a, __temp->_M_valptr()); __temp->~_Node(); - _M_put_node(__temp); - } + _M_put_node(__temp); + } __pos->_M_next = __last; return __last; } @@ -104,12 +99,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER forward_list<_Tp, _Alloc>:: _M_range_initialize(_InputIterator __first, _InputIterator __last) { - _Node_base* __to = &this->_M_impl._M_head; - for (; __first != __last; ++__first) - { - __to->_M_next = this->_M_create_node(*__first); - __to = __to->_M_next; - } + _Node_base* __to = &this->_M_impl._M_head; + for (; __first != __last; ++__first) + { + __to->_M_next = this->_M_create_node(*__first); + __to = __to->_M_next; + } } // Called by forward_list(n,v,a). @@ -120,10 +115,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Node_base* __to = &this->_M_impl._M_head; for (; __n; --__n) - { - __to->_M_next = this->_M_create_node(__value); - __to = __to->_M_next; - } + { + __to->_M_next = this->_M_create_node(__value); + __to = __to->_M_next; + } } template @@ -133,10 +128,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Node_base* __to = &this->_M_impl._M_head; for (; __n; --__n) - { - __to->_M_next = this->_M_create_node(); - __to = __to->_M_next; - } + { + __to->_M_next = this->_M_create_node(); + __to = __to->_M_next; + } } template @@ -145,21 +140,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator=(const forward_list& __list) { if (std::__addressof(__list) != this) - { + { if (_Node_alloc_traits::_S_propagate_on_copy_assign()) { - auto& __this_alloc = this->_M_get_Node_allocator(); - auto& __that_alloc = __list._M_get_Node_allocator(); - if (!_Node_alloc_traits::_S_always_equal() - && __this_alloc != __that_alloc) - { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __list._M_get_Node_allocator(); + if (!_Node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { // replacement allocator cannot free existing storage clear(); } std::__alloc_on_copy(__this_alloc, __that_alloc); - } + } assign(__list.cbegin(), __list.cend()); - } + } return *this; } @@ -190,12 +185,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER size_type __len = 0; while (__k._M_next() != end() && __len < __sz) - { - ++__k; - ++__len; - } + { + ++__k; + ++__len; + } if (__len == __sz) - erase_after(__k, end()); + erase_after(__k, end()); else _M_default_insert_after(__k, __sz - __len); } @@ -209,14 +204,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER size_type __len = 0; while (__k._M_next() != end() && __len < __sz) - { - ++__k; - ++__len; - } + { + ++__k; + ++__len; + } if (__len == __sz) - erase_after(__k, end()); + erase_after(__k, end()); else - insert_after(__k, __sz - __len, __val); + insert_after(__k, __sz - __len, __val); } template @@ -233,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __end = __end->_M_next; if (__b != __end) - return iterator(__tmp->_M_transfer_after(__b, __end)); + return iterator(__tmp->_M_transfer_after(__b, __end)); else return iterator(__tmp); } @@ -292,8 +287,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Node_base* __extra = nullptr; while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) - { - if (*__tmp->_M_valptr() == __val) + { + if (*__tmp->_M_valptr() == __val) { if (__tmp->_M_valptr() != std::__addressof(__val)) { @@ -304,7 +299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __extra = __curr; } __curr = __curr->_M_next; - } + } if (__extra) this->_M_erase_after(__extra); @@ -317,13 +312,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER remove_if(_Pred __pred) { _Node_base* __curr = &this->_M_impl._M_head; - while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) - { - if (__pred(*__tmp->_M_valptr())) - this->_M_erase_after(__curr); - else - __curr = __curr->_M_next; - } + while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) + { + if (__pred(*__tmp->_M_valptr())) + this->_M_erase_after(__curr); + else + __curr = __curr->_M_next; + } } template @@ -332,19 +327,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER forward_list<_Tp, _Alloc>:: unique(_BinPred __binary_pred) { - iterator __first = begin(); - iterator __last = end(); - if (__first == __last) - return; - iterator __next = __first; - while (++__next != __last) - { - if (__binary_pred(*__first, *__next)) - erase_after(__first); - else - __first = __next; - __next = __first; - } + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return; + iterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(*__first, *__next)) + erase_after(__first); + else + __first = __next; + __next = __first; + } } template @@ -353,44 +348,42 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER forward_list<_Tp, _Alloc>:: merge(forward_list&& __list, _Comp __comp) { - _Node_base* __node = &this->_M_impl._M_head; - while (__node->_M_next && __list._M_impl._M_head._M_next) - { - if (__comp(*static_cast<_Node*> - (__list._M_impl._M_head._M_next)->_M_valptr(), - *static_cast<_Node*> - (__node->_M_next)->_M_valptr())) - __node->_M_transfer_after(&__list._M_impl._M_head, - __list._M_impl._M_head._M_next); - __node = __node->_M_next; - } - if (__list._M_impl._M_head._M_next) - { - __node->_M_next = __list._M_impl._M_head._M_next; - __list._M_impl._M_head._M_next = 0; - } + _Node_base* __node = &this->_M_impl._M_head; + while (__node->_M_next && __list._M_impl._M_head._M_next) + { + if (__comp(*static_cast<_Node*> + (__list._M_impl._M_head._M_next)->_M_valptr(), + *static_cast<_Node*> + (__node->_M_next)->_M_valptr())) + __node->_M_transfer_after(&__list._M_impl._M_head, + __list._M_impl._M_head._M_next); + __node = __node->_M_next; + } + + if (__list._M_impl._M_head._M_next) + *__node = std::move(__list._M_impl._M_head); } template bool operator==(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) + const forward_list<_Tp, _Alloc>& __ly) { // We don't have size() so we need to walk through both lists // making sure both iterators are valid. auto __ix = __lx.cbegin(); auto __iy = __ly.cbegin(); while (__ix != __lx.cend() && __iy != __ly.cend()) - { - if (*__ix != *__iy) - return false; - ++__ix; - ++__iy; - } + { + if (*__ix != *__iy) + return false; + ++__ix; + ++__iy; + } if (__ix == __lx.cend() && __iy == __ly.cend()) - return true; + return true; else - return false; + return false; } template @@ -399,103 +392,102 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER forward_list<_Tp, _Alloc>:: sort(_Comp __comp) { - // If `next' is 0, return immediately. - _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next); - if (!__list) - return; - - unsigned long __insize = 1; - - while (1) - { - _Node* __p = __list; - __list = 0; - _Node* __tail = 0; - - // Count number of merges we do in this pass. - unsigned long __nmerges = 0; - - while (__p) - { - ++__nmerges; - // There exists a merge to be done. - // Step `insize' places along from p. - _Node* __q = __p; - unsigned long __psize = 0; - for (unsigned long __i = 0; __i < __insize; ++__i) - { - ++__psize; - __q = static_cast<_Node*>(__q->_M_next); - if (!__q) - break; - } - - // If q hasn't fallen off end, we have two lists to merge. - unsigned long __qsize = __insize; - - // Now we have two lists; merge them. - while (__psize > 0 || (__qsize > 0 && __q)) - { - // Decide whether next node of merge comes from p or q. - _Node* __e; - if (__psize == 0) - { - // p is empty; e must come from q. - __e = __q; - __q = static_cast<_Node*>(__q->_M_next); - --__qsize; - } - else if (__qsize == 0 || !__q) - { - // q is empty; e must come from p. - __e = __p; - __p = static_cast<_Node*>(__p->_M_next); - --__psize; - } - else if (__comp(*__p->_M_valptr(), *__q->_M_valptr())) - { - // First node of p is lower; e must come from p. - __e = __p; - __p = static_cast<_Node*>(__p->_M_next); - --__psize; - } - else - { - // First node of q is lower; e must come from q. - __e = __q; - __q = static_cast<_Node*>(__q->_M_next); - --__qsize; - } - - // Add the next node to the merged list. - if (__tail) - __tail->_M_next = __e; - else - __list = __e; - __tail = __e; - } - - // Now p has stepped `insize' places along, and q has too. - __p = __q; - } - __tail->_M_next = 0; - - // If we have done only one merge, we're finished. - // Allow for nmerges == 0, the empty list case. - if (__nmerges <= 1) - { - this->_M_impl._M_head._M_next = __list; - return; - } - - // Otherwise repeat, merging lists twice the size. - __insize *= 2; - } + // If `next' is nullptr, return immediately. + _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next); + if (!__list) + return; + + unsigned long __insize = 1; + + while (1) + { + _Node* __p = __list; + __list = nullptr; + _Node* __tail = nullptr; + + // Count number of merges we do in this pass. + unsigned long __nmerges = 0; + + while (__p) + { + ++__nmerges; + // There exists a merge to be done. + // Step `insize' places along from p. + _Node* __q = __p; + unsigned long __psize = 0; + for (unsigned long __i = 0; __i < __insize; ++__i) + { + ++__psize; + __q = static_cast<_Node*>(__q->_M_next); + if (!__q) + break; + } + + // If q hasn't fallen off end, we have two lists to merge. + unsigned long __qsize = __insize; + + // Now we have two lists; merge them. + while (__psize > 0 || (__qsize > 0 && __q)) + { + // Decide whether next node of merge comes from p or q. + _Node* __e; + if (__psize == 0) + { + // p is empty; e must come from q. + __e = __q; + __q = static_cast<_Node*>(__q->_M_next); + --__qsize; + } + else if (__qsize == 0 || !__q) + { + // q is empty; e must come from p. + __e = __p; + __p = static_cast<_Node*>(__p->_M_next); + --__psize; + } + else if (__comp(*__p->_M_valptr(), *__q->_M_valptr())) + { + // First node of p is lower; e must come from p. + __e = __p; + __p = static_cast<_Node*>(__p->_M_next); + --__psize; + } + else + { + // First node of q is lower; e must come from q. + __e = __q; + __q = static_cast<_Node*>(__q->_M_next); + --__qsize; + } + + // Add the next node to the merged list. + if (__tail) + __tail->_M_next = __e; + else + __list = __e; + __tail = __e; + } + + // Now p has stepped `insize' places along, and q has too. + __p = __q; + } + __tail->_M_next = nullptr; + + // If we have done only one merge, we're finished. + // Allow for nmerges == 0, the empty list case. + if (__nmerges <= 1) + { + this->_M_impl._M_head._M_next = __list; + return; + } + + // Otherwise repeat, merging lists twice the size. + __insize *= 2; + } } - + _GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif /* _FORWARD_LIST_TCC */ - diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/forward_list/allocator/default_init.cc new file mode 100644 index 00000000000..804ba339db6 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2018 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::forward_list 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::forward_list 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; +}