[v3, patch] Move std::list::_M_size closer to iterators

Marc Glisse marc.glisse@inria.fr
Sun Oct 12 19:41:00 GMT 2014


Hello,

this patch moves _M_size in std::list to a place where it should be easier 
(no offsetof) to access from an iterator (it doesn't matter when you 
access it from the main std::list object). It does not take advantage of 
it yet, that can be done at any time, whereas the layout will soon be 
fixed. This triggered one of the issues listed in PR 63345 (casting to a 
node* even for the sentinel), which I am fixing here.

Bootstrap+testsuite on x86_64-linux-gnu.

2014-10-13  Marc Glisse  <marc.glisse@inria.fr>

 	PR libstdc++/61347
 	PR libstdc++/63345
 	* include/bits/list.tcc (_List_base::_M_clear()): Delay cast so it
 	isn't done for the sentinel.
 	* include/bits/stl_list.h (_List_base::_M_size): Move...
 	(_List_base::_List_impl::_M_node): ... here.
 	(_List_base::_M_get_size(), _List_base::_M_set_size(size_t),
 	_List_base::_M_inc_size(size_t), _List_base::_M_dec_size(size_t),
 	_List_base::_M_node_count): Adapt to the move.
 	* 23_containers/list/requirements/dr438/assign_neg.cc: Update
 	line number.
 	* 23_containers/list/requirements/dr438/constructor_1_neg.cc: Likewise.
 	* 23_containers/list/requirements/dr438/constructor_2_neg.cc: Likewise.
 	* 23_containers/list/requirements/dr438/insert_neg.cc: Likewise.


-- 
Marc Glisse
-------------- next part --------------
Index: include/bits/list.tcc
===================================================================
--- include/bits/list.tcc	(revision 216116)
+++ include/bits/list.tcc	(working copy)
@@ -59,25 +59,25 @@
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   template<typename _Tp, typename _Alloc>
     void
     _List_base<_Tp, _Alloc>::
     _M_clear() _GLIBCXX_NOEXCEPT
     {
       typedef _List_node<_Tp>  _Node;
-      _Node* __cur = static_cast<_Node*>(_M_impl._M_node._M_next);
+      __detail::_List_node_base* __cur = _M_impl._M_node._M_next;
       while (__cur != &_M_impl._M_node)
 	{
-	  _Node* __tmp = __cur;
-	  __cur = static_cast<_Node*>(__cur->_M_next);
+	  _Node* __tmp = static_cast<_Node*>(__cur);
+	  __cur = __tmp->_M_next;
 #if __cplusplus >= 201103L
 	  _M_get_Node_allocator().destroy(__tmp);
 #else
 	  _M_get_Tp_allocator().destroy(std::__addressof(__tmp->_M_data));
 #endif
 	  _M_put_node(__tmp);
 	}
     }
 
 #if __cplusplus >= 201103L
Index: include/bits/stl_list.h
===================================================================
--- include/bits/stl_list.h	(revision 216116)
+++ include/bits/stl_list.h	(working copy)
@@ -325,57 +325,59 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  {
 	    __first = __first->_M_next;
 	    ++__n;
 	  }
 	return __n;
       }
 
       struct _List_impl
       : public _Node_alloc_type
       {
+#if _GLIBCXX_USE_CXX11_ABI
+	_List_node<size_t> _M_node;
+#else
 	__detail::_List_node_base _M_node;
+#endif
 
 	_List_impl()
 	: _Node_alloc_type(), _M_node()
 	{ }
 
 	_List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT
 	: _Node_alloc_type(__a), _M_node()
 	{ }
 
 #if __cplusplus >= 201103L
 	_List_impl(_Node_alloc_type&& __a) _GLIBCXX_NOEXCEPT
 	: _Node_alloc_type(std::move(__a)), _M_node()
 	{ }
 #endif
       };
 
       _List_impl _M_impl;
 
 #if _GLIBCXX_USE_CXX11_ABI
-      size_t	 _M_size;
-
-      size_t _M_get_size() const { return _M_size; }
+      size_t _M_get_size() const { return _M_impl._M_node._M_data; }
 
-      void _M_set_size(size_t __n) { _M_size = __n; }
+      void _M_set_size(size_t __n) { _M_impl._M_node._M_data = __n; }
 
-      void _M_inc_size(size_t __n) { _M_size += __n; }
+      void _M_inc_size(size_t __n) { _M_impl._M_node._M_data += __n; }
 
-      void _M_dec_size(size_t __n) { _M_size -= __n; }
+      void _M_dec_size(size_t __n) { _M_impl._M_node._M_data -= __n; }
 
       size_t
       _M_distance(const __detail::_List_node_base* __first,
 		  const __detail::_List_node_base* __last) const
       { return _S_distance(__first, __last); }
 
       // return the stored size
-      size_t _M_node_count() const { return _M_size; }
+      size_t _M_node_count() const { return _M_impl._M_node._M_data; }
 #else
       // dummy implementations used when the size is not stored
       size_t _M_get_size() const { return 0; }
       void _M_set_size(size_t) { }
       void _M_inc_size(size_t) { }
       void _M_dec_size(size_t) { }
       size_t _M_distance(const void*, const void*) const { return 0; }
 
       // count the number of nodes
       size_t _M_node_count() const
Index: testsuite/23_containers/list/requirements/dr438/assign_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/assign_neg.cc	(revision 216116)
+++ testsuite/23_containers/list/requirements/dr438/assign_neg.cc	(working copy)
@@ -11,21 +11,21 @@
 // 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
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1728 }
+// { dg-error "no matching" "" { target *-*-* } 1730 }
 
 #include <list>
 
 struct A
 {
   explicit A(int) { }
 };
 
 void f()
 {
Index: testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc	(revision 216116)
+++ testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc	(working copy)
@@ -11,19 +11,19 @@
 // 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
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1680 }
+// { dg-error "no matching" "" { target *-*-* } 1682 }
 
 #include <list>
 
 void f()
 {
   typedef std::list<std::list<int> > list_type;
   list_type l(10, 1);
 }
Index: testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc	(revision 216116)
+++ testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc	(working copy)
@@ -11,20 +11,20 @@
 // 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
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1680 }
+// { dg-error "no matching" "" { target *-*-* } 1682 }
 
 #include <list>
 #include <utility>
 
 void f()
 {
   typedef std::list<std::list<std::pair<char, char> > > list_type;
   list_type l('a', 'b');
 }
Index: testsuite/23_containers/list/requirements/dr438/insert_neg.cc
===================================================================
--- testsuite/23_containers/list/requirements/dr438/insert_neg.cc	(revision 216116)
+++ testsuite/23_containers/list/requirements/dr438/insert_neg.cc	(working copy)
@@ -11,21 +11,21 @@
 // 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
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1680 }
+// { dg-error "no matching" "" { target *-*-* } 1682 }
 
 #include <list>
 
 struct A
 {
   explicit A(int) { }
 };
 
 void f()
 {


More information about the Libstdc++ mailing list