From 4f9e1f4d9ddb120ca1a3df8df2e29c94820d7fc2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Dumont?= Date: Tue, 18 Jul 2017 20:26:08 +0000 Subject: [PATCH] stl_list.h (struct _List_node_header): New. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 2017-07-18 François Dumont * include/bits/stl_list.h (struct _List_node_header): New. (_List_impl()): Fix noexcept qualification. (_List_impl(_List_impl&&)): New, default. (_List_base()): Default. (_List_base(_List_base&&)): Default. (_List_base::_M_move_nodes): Adapt to use _List_node_header._M_move_nodes. (_List_base::_M_init): Likewise. (list<>()): Default. (list<>(list&&)): Default. (list<>::_M_move_assign(list&&, true_type)): Use _M_move_nodes. (__distance(_List_const_iterator<>, _List_const_iterator<>, input_iterator_tag)): Adapt. * testsuite/23_containers/list/allocator/default_init.cc: New. From-SVN: r250320 --- libstdc++-v3/ChangeLog | 18 ++ libstdc++-v3/include/bits/stl_list.h | 156 +++++++++++------- .../list/allocator/default_init.cc | 71 ++++++++ 3 files changed, 181 insertions(+), 64 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 87b2f63d0ab..7af51ac01bc 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,21 @@ +2017-07-18 François Dumont + + * include/bits/stl_list.h + (struct _List_node_header): New. + (_List_impl()): Fix noexcept qualification. + (_List_impl(_List_impl&&)): New, default. + (_List_base()): Default. + (_List_base(_List_base&&)): Default. + (_List_base::_M_move_nodes): Adapt to use + _List_node_header._M_move_nodes. + (_List_base::_M_init): Likewise. + (list<>()): Default. + (list<>(list&&)): Default. + (list<>::_M_move_assign(list&&, true_type)): Use _M_move_nodes. + (__distance(_List_const_iterator<>, _List_const_iterator<>, + input_iterator_tag)): Adapt. + * testsuite/23_containers/list/allocator/default_init.cc: New. + 2017-07-15 Jonathan Wakely * include/std/mutex (scoped_lock): Reorder std::adopt_lock_t parameter diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 232885af79d..5da19b32eea 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -99,6 +99,65 @@ namespace std _GLIBCXX_VISIBILITY(default) _M_unhook() _GLIBCXX_USE_NOEXCEPT; }; + /// The %list node header. + struct _List_node_header : public _List_node_base + { +#if _GLIBCXX_USE_CXX11_ABI + std::size_t _M_size; +#endif + + _List_node_header() _GLIBCXX_NOEXCEPT + { _M_init(); } + +#if __cplusplus >= 201103L + _List_node_header(_List_node_header&& __x) noexcept + : _List_node_base{ __x._M_next, __x._M_prev } +# if _GLIBCXX_USE_CXX11_ABI + , _M_size(__x._M_size) +# endif + { + if (__x._M_base()->_M_next == __x._M_base()) + this->_M_next = this->_M_prev = this; + else + { + this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base(); + __x._M_init(); + } + } + + void + _M_move_nodes(_List_node_header&& __x) + { + _List_node_base* const __xnode = __x._M_base(); + if (__xnode->_M_next == __xnode) + _M_init(); + else + { + _List_node_base* const __node = this->_M_base(); + __node->_M_next = __xnode->_M_next; + __node->_M_prev = __xnode->_M_prev; + __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; +# if _GLIBCXX_USE_CXX11_ABI + _M_size = __x._M_size; +# endif + __x._M_init(); + } + } +#endif + + void + _M_init() _GLIBCXX_NOEXCEPT + { + this->_M_next = this->_M_prev = this; +#if _GLIBCXX_USE_CXX11_ABI + this->_M_size = 0; +#endif + } + + private: + _List_node_base* _M_base() { return this; } + }; + _GLIBCXX_END_NAMESPACE_VERSION } // namespace detail @@ -323,23 +382,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 struct _List_impl : public _Node_alloc_type { -#if _GLIBCXX_USE_CXX11_ABI - _List_node _M_node; -#else - __detail::_List_node_base _M_node; -#endif + __detail::_List_node_header _M_node; - _List_impl() _GLIBCXX_NOEXCEPT - : _Node_alloc_type(), _M_node() + _List_impl() _GLIBCXX_NOEXCEPT_IF( noexcept(_Node_alloc_type()) ) + : _Node_alloc_type() { } _List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _Node_alloc_type(__a), _M_node() + : _Node_alloc_type(__a) { } #if __cplusplus >= 201103L + _List_impl(_List_impl&&) = default; + _List_impl(_Node_alloc_type&& __a) noexcept - : _Node_alloc_type(std::move(__a)), _M_node() + : _Node_alloc_type(std::move(__a)) { } #endif }; @@ -347,13 +404,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _List_impl _M_impl; #if _GLIBCXX_USE_CXX11_ABI - size_t _M_get_size() const { return *_M_impl._M_node._M_valptr(); } + size_t _M_get_size() const { return _M_impl._M_node._M_size; } - void _M_set_size(size_t __n) { *_M_impl._M_node._M_valptr() = __n; } + void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; } - void _M_inc_size(size_t __n) { *_M_impl._M_node._M_valptr() += __n; } + void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; } - void _M_dec_size(size_t __n) { *_M_impl._M_node._M_valptr() -= __n; } + void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; } size_t _M_distance(const __detail::_List_node_base* __first, @@ -361,7 +418,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return _S_distance(__first, __last); } // return the stored size - size_t _M_node_count() const { return *_M_impl._M_node._M_valptr(); } + size_t _M_node_count() const { return _M_get_size(); } #else // dummy implementations used when the size is not stored size_t _M_get_size() const { return 0; } @@ -397,44 +454,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT { return _M_impl; } - _List_base() - : _M_impl() - { _M_init(); } +#if __cplusplus >= 201103L + _List_base() = default; +#else + _List_base() { } +#endif _List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT : _M_impl(__a) - { _M_init(); } + { } #if __cplusplus >= 201103L - _List_base(_List_base&& __x) noexcept - : _M_impl(std::move(__x._M_get_Node_allocator())) - { _M_move_nodes(std::move(__x)); } + _List_base(_List_base&&) = default; _List_base(_List_base&& __x, _Node_alloc_type&& __a) : _M_impl(std::move(__a)) { if (__x._M_get_Node_allocator() == _M_get_Node_allocator()) _M_move_nodes(std::move(__x)); - else - _M_init(); // Caller must move individual elements. + // else caller must move individual elements. } void _M_move_nodes(_List_base&& __x) - { - auto* const __xnode = std::__addressof(__x._M_impl._M_node); - if (__xnode->_M_next == __xnode) - _M_init(); - else - { - auto* const __node = std::__addressof(_M_impl._M_node); - __node->_M_next = __xnode->_M_next; - __node->_M_prev = __xnode->_M_prev; - __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; - _M_set_size(__x._M_get_size()); - __x._M_init(); - } - } + { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); } #endif // This is what actually destroys the list. @@ -446,11 +489,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void _M_init() _GLIBCXX_NOEXCEPT - { - this->_M_impl._M_node._M_next = &this->_M_impl._M_node; - this->_M_impl._M_node._M_prev = &this->_M_impl._M_node; - _M_set_size(0); - } + { this->_M_impl._M_node._M_init(); } }; /** @@ -586,11 +625,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Creates a %list with no elements. */ - list() #if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value) + list() = default; +#else + list() { } #endif - : _Base() { } /** * @brief Creates a %list with no elements. @@ -657,13 +696,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus >= 201103L /** * @brief %List move constructor. - * @param __x A %list of identical element and allocator types. * - * The newly-created %list contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %list. + * The newly-created %list contains the exact contents of the moved + * instance. The contents of the moved instance are a valid, but + * unspecified %list. */ - list(list&& __x) noexcept - : _Base(std::move(__x)) { } + list(list&&) = default; /** * @brief Builds a %list from an initializer_list @@ -1838,17 +1876,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _M_move_assign(list&& __x, true_type) noexcept { this->_M_clear(); - if (__x.empty()) - this->_M_init(); - else - { - this->_M_impl._M_node._M_next = __x._M_impl._M_node._M_next; - this->_M_impl._M_node._M_next->_M_prev = &this->_M_impl._M_node; - this->_M_impl._M_node._M_prev = __x._M_impl._M_node._M_prev; - this->_M_impl._M_node._M_prev->_M_next = &this->_M_impl._M_node; - this->_M_set_size(__x._M_get_size()); - __x._M_init(); - } + this->_M_move_nodes(std::move(__x)); std::__alloc_on_move(this->_M_get_Node_allocator(), __x._M_get_Node_allocator()); } @@ -1983,12 +2011,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_STD_C::_List_const_iterator<_Tp> __last, input_iterator_tag) { - typedef _GLIBCXX_STD_C::_List_node _Sentinel; + typedef __detail::_List_node_header _Sentinel; _GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last; ++__beyond; - bool __whole = __first == __beyond; + const bool __whole = __first == __beyond; if (__builtin_constant_p (__whole) && __whole) - return *static_cast(__last._M_node)->_M_valptr(); + return static_cast(__last._M_node)->_M_size; ptrdiff_t __n = 0; while (__first != __last) diff --git a/libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc new file mode 100644 index 00000000000..0604e067252 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/list/allocator/default_init.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2017 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::list test_type; + + __gnu_cxx::__aligned_buffer buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + VERIFY( buf._M_ptr()->get_allocator().state != 0 ); + + 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::list test_type; + + __gnu_cxx::__aligned_buffer buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + VERIFY( buf._M_ptr()->get_allocator().state != 0 ); + + 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