public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Use abi_tag attribute on std::list
@ 2014-10-03 13:04 Jonathan Wakely
  2014-10-03 14:25 ` Marc Glisse
  0 siblings, 1 reply; 6+ messages in thread
From: Jonathan Wakely @ 2014-10-03 13:04 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1615 bytes --]

This is the patch I intend to commit to make std::list::size() O(1) as
required by C++11.

This is an ABI change, so std::list will get tagged with
abi_tag("cxx11") so that it mangles differently.

I took a different approach to the way O(1) size() was implemented
(and then reverted) for GCC 4.7.0, because I didn't like updating the
size when node are (de)allocated. Instead this patch adjusts the size
when nodes are added or removed from the list, rather then when
they're allocated.

Instead of littering the code with #if checks I added new
_M_xxx_size() members that can be called unconditionally when
modifying the list, but they do nothing when there's no size member.
This means there's only a single #if condition added to std::list by
this patch.

There will be another patch coming soon to add C++11 allocator support
to std::list, and another to add a non-COW std::string using abi_tag.

I don't yet know what we should do about the
--enable-symvers=gnu-versioned-namespace configuration, maybe we
should move the soname for that option to libstdc++.so.8 and have
_GLIBCXX_USE_CXX11_ABI=1 and _GLIBCXX_DEFAULT_ABI_TAG= set always,
so that the versioned-namespace configuration always gets the new ABI
and doesn't need to use the tag (because using that configuration
already implies you're not interested in ABI compatibility). I'd
prefer not to have versioned-namespace-with-new-abi and
versioned-namespace-without-new-abi configurations, given that we don't
know if anyone's even using versioned namespaces for anything serious.

Tested x86_64-linux, with --disable-libstdcxx-cxx11-abi and without.

[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 15447 bytes --]

commit 160dfb8b15ca20581634c235c75293712072f622
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 7 01:13:17 2014 +0100

    	* acinclude.m4 (GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI): Define.
    	* configure.ac: Use GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI.
    	* configure: Regenerate.
    	* include/Makefile.am (stamp-cxx11-abi): New target.
    	(c++config.h): Set _GLIBCXX_USE_CXX11_ABI macro.
    	* include/Makefile.in: Regenerate.
    	* include/bits/c++config: Add _GLIBCXX_USE_CXX11_ABI placeholder and
    	define _GLIBCXX_DEFAULT_ABI_TAG.
    	* include/bits/list.tcc (list::emplace(const_iterator, _Args&...)):
    	Increment size.
    	(list::emplace(const_iterator, const value_type&)): Likewise.
    	(list::merge(list&), list::merge(list&, _StrictWeakOrdering)): Adjust
    	list sizes.
    	* include/bits/stl_list.h (_List_base, list): Add ABI tag macro.
    	(_List_base::_M_size): New data member in cxx11 ABI mode.
    	(_List_base::_S_distance(_List_node_base*, _List_node_base*)): New
    	function.
    	(_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_distance, _List_base::_M_node_count): New functions for
    	accessing list size correctly for the ABI mode.
    	(_List_base::_List_base(_List_base&&)): Copy size and reset source.
    	(_List_base::_M_init()): Initialize size member.
    	(list::size()): Use _List_base::_M_node_count.
    	(list::swap(list&)): Swap sizes.
    	(list::splice(iterator, list&)): Update sizes.
    	(list::splice(iterator, list&, iterator)): Likewise.
    	(list::insert(iterator, const value_type&)): Update size.
    	(list::insert(iterator, _Args&&...)): Likewise.
    	(list::_M_erase(iterator)): Likewise.
    	* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
    	Adjust.
    	* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
    	Adjust.
    	* testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc:
    	Adjust.
    	* testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc:
    	Adjust.
    	* testsuite/ext/profile/mutex_extensions_neg.cc: Adjust.

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 2650a5a..0229609 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -3831,6 +3831,25 @@ AC_DEFUN([GLIBCXX_CHECK_SDT_H], [
   AC_MSG_RESULT($glibcxx_cv_sys_sdt_h)
 ])
 
+dnl
+dnl Check if the user wants the new C++11-conforming ABI.
+dnl
+dnl --disable-libstdcxx-cxx11-abi will use old ABI for all types.
+dnl
+dnl Defines:
+dnl  _GLIBCXX_USE_ABI_TAG (always defined, either to 1 or 0)
+dnl
+AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI], [
+  AC_ARG_ENABLE([libstdcxx-cxx11-abi],
+    AC_HELP_STRING([--disable-libstdcxx-cxx11-abi],
+		   [disable the C++11-conforming ABI]),,
+		   [enable_libstdcxx_cxx11_abi=yes])
+  if test x"$enable_libstdcxx_cxx11_abi" != xyes; then
+    AC_MSG_NOTICE([C++11-conforming ABI is disabled])
+  fi
+  GLIBCXX_CONDITIONAL(ENABLE_CXX11_ABI, test $enable_libstdcxx_cxx11_abi = yes)
+])
+
 # Macros from the top-level gcc directory.
 m4_include([../config/gc++filt.m4])
 m4_include([../config/tls.m4])
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 1de0f6c..eb826e4 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -365,6 +365,8 @@ AC_SUBST(libtool_VERSION)
 
 GLIBCXX_ENABLE_LIBSTDCXX_VISIBILITY([yes])
 
+GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI([yes])
+
 ac_ldbl_compat=no
 case "$target" in
   powerpc*-*-linux* | \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 5476a37..f3658a1 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1121,6 +1121,14 @@ stamp-visibility:
 	echo 0 > stamp-visibility
 endif
 
+if ENABLE_CXX11_ABI
+stamp-cxx11-abi:
+	echo 1 > stamp-cxx11-abi
+else
+stamp-cxx11-abi:
+	echo 0 > stamp-cxx11-abi
+endif
+
 # NB: The non-empty default ldbl_compat works around an AIX sed
 # oddity, see libstdc++/31957 for details.
 ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
@@ -1129,11 +1137,13 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 			      ${toplevel_srcdir}/gcc/DATESTAMP \
 			      stamp-namespace-version \
 			      stamp-visibility \
-			      stamp-extern-template
+			      stamp-extern-template \
+			      stamp-cxx11-abi
 	@date=`cat ${toplevel_srcdir}/gcc/DATESTAMP` ;\
 	ns_version=`cat stamp-namespace-version` ;\
 	visibility=`cat stamp-visibility` ;\
 	externtemplate=`cat stamp-extern-template` ;\
+	cxx11abi=`cat stamp-cxx11-abi` ;\
 	ldbl_compat='s,g,g,' ;\
 	grep "^[	 ]*#[	 ]*define[	 ][	 ]*_GLIBCXX_LONG_DOUBLE_COMPAT[	 ][	 ]*1[	 ]*$$" \
 	${CONFIG_HEADER} > /dev/null 2>&1 \
@@ -1142,6 +1152,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	-e "s,define _GLIBCXX_INLINE_VERSION, define _GLIBCXX_INLINE_VERSION $$ns_version," \
 	-e "s,define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY, define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY $$visibility," \
 	-e "s,define _GLIBCXX_EXTERN_TEMPLATE$$, define _GLIBCXX_EXTERN_TEMPLATE $$externtemplate," \
+	-e "s,define _GLIBCXX_USE_CXX11_ABI, define _GLIBCXX_USE_CXX11_ABI $$cxx11abi," \
 	-e "$$ldbl_compat" \
 	    < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
 	sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index ff6afc8..bb58a9b 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -193,6 +193,17 @@ namespace std
 #endif
 }
 
+// Use abi_tag("cxx11")
+#ifndef _GLIBCXX_USE_CXX11_ABI
+#define _GLIBCXX_USE_CXX11_ABI
+#endif
+
+#if _GLIBCXX_USE_CXX11_ABI
+# define _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_ABI_TAG_CXX11
+#else
+# define _GLIBCXX_DEFAULT_ABI_TAG
+#endif
+
 
 // Defined if inline namespaces are used for versioning.
 #define _GLIBCXX_INLINE_VERSION 
diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc
index 42855a4..f99ec54 100644
--- a/libstdc++-v3/include/bits/list.tcc
+++ b/libstdc++-v3/include/bits/list.tcc
@@ -89,6 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	_Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
 	__tmp->_M_hook(__position._M_const_cast()._M_node);
+	this->_M_inc_size(1);
 	return iterator(__tmp);
       }
 #endif
@@ -104,6 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     {
       _Node* __tmp = _M_create_node(__x);
       __tmp->_M_hook(__position._M_const_cast()._M_node);
+      this->_M_inc_size(1);
       return iterator(__tmp);
     }
 
@@ -353,6 +355,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	      ++__first1;
 	  if (__first2 != __last2)
 	    _M_transfer(__last1, __first2, __last2);
+
+	  this->_M_inc_size(__x._M_get_size());
+	  __x._M_set_size(0);
 	}
     }
 
@@ -387,6 +392,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		++__first1;
 	    if (__first2 != __last2)
 	      _M_transfer(__last1, __first2, __last2);
+
+	    this->_M_inc_size(__x._M_get_size());
+	    __x._M_set_size(0);
 	  }
       }
 
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index dd9bba7..3a56daf 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -295,7 +295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   /// See bits/stl_deque.h's _Deque_base for an explanation.
   template<typename _Tp, typename _Alloc>
-    class _List_base
+    class _GLIBCXX_DEFAULT_ABI_TAG _List_base
     {
     protected:
       // NOTA BENE
@@ -316,11 +316,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
 
+      static size_t
+      _S_distance(const __detail::_List_node_base* __first,
+		  const __detail::_List_node_base* __last)
+      {
+	size_t __n = 0;
+	while (__first != __last)
+	  {
+	    __first = __first->_M_next;
+	    ++__n;
+	  }
+	return __n;
+      }
+
       struct _List_impl
       : public _Node_alloc_type
       {
 	__detail::_List_node_base _M_node;
-
 	_List_impl()
 	: _Node_alloc_type(), _M_node()
 	{ }
@@ -338,6 +350,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       _List_impl _M_impl;
 
+#if _GLIBCXX_USE_CXX11_ABI
+      size_t	 _M_size;
+
+      size_t _M_get_size() const { return _M_size; }
+
+      void _M_set_size(size_t __n) { _M_size = __n; }
+
+      void _M_inc_size(size_t __n) { _M_size += __n; }
+
+      void _M_dec_size(size_t __n) { _M_size -= __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; }
+#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
+      {
+	return _S_distance(_M_impl._M_node._M_next,
+			   std::__addressof(_M_impl._M_node));
+      }
+#endif
+
       _List_node<_Tp>*
       _M_get_node()
       { return _M_impl._Node_alloc_type::allocate(1); }
@@ -386,7 +432,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    __node->_M_next = __xnode->_M_next;
 	    __node->_M_prev = __xnode->_M_prev;
 	    __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
-	    __xnode->_M_next = __xnode->_M_prev = __xnode;
+	    _M_set_size(__x._M_get_size());
+	    __x._M_init();
 	  }
       }
 #endif
@@ -403,6 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
         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);
       }
     };
 
@@ -453,7 +501,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
    *  %empty. 
   */
   template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
-    class list : protected _List_base<_Tp, _Alloc>
+    class _GLIBCXX_DEFAULT_ABI_TAG list : protected _List_base<_Tp, _Alloc>
     {
       // concept requirements
       typedef typename _Alloc::value_type                _Alloc_value_type;
@@ -893,7 +941,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /**  Returns the number of elements in the %list.  */
       size_type
       size() const _GLIBCXX_NOEXCEPT
-      { return std::distance(begin(), end()); }
+      { return this->_M_node_count(); }
 
       /**  Returns the size() of the largest possible %list.  */
       size_type
@@ -1295,6 +1343,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	__detail::_List_node_base::swap(this->_M_impl._M_node, 
 					__x._M_impl._M_node);
 
+	size_t __xsize = __x._M_get_size();
+	__x._M_set_size(this->_M_get_size());
+	this->_M_set_size(__xsize);
+
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 431. Swapping containers with unequal allocators.
 	std::__alloc_swap<typename _Base::_Node_alloc_type>::
@@ -1339,6 +1391,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 	    this->_M_transfer(__position._M_const_cast(),
 			      __x.begin(), __x.end());
+
+	    this->_M_inc_size(__x._M_get_size());
+	    __x._M_set_size(0);
 	  }
       }
 
@@ -1385,6 +1440,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 	this->_M_transfer(__position._M_const_cast(),
 			  __i._M_const_cast(), __j);
+
+	this->_M_inc_size(1);
+	__x._M_dec_size(1);
       }
 
 #if __cplusplus >= 201103L
@@ -1443,6 +1501,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    if (this != &__x)
 	      _M_check_equal_allocators(__x);
 
+	    size_t __n = this->_M_distance(__first._M_node, __last._M_node);
+	    this->_M_inc_size(__n);
+	    __x._M_dec_size(__n);
+
 	    this->_M_transfer(__position._M_const_cast(),
 			      __first._M_const_cast(),
 			      __last._M_const_cast());
@@ -1688,6 +1750,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
         _Node* __tmp = _M_create_node(__x);
         __tmp->_M_hook(__position._M_node);
+	this->_M_inc_size(1);
       }
 #else
      template<typename... _Args>
@@ -1696,6 +1759,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        {
 	 _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
 	 __tmp->_M_hook(__position._M_node);
+	 this->_M_inc_size(1);
        }
 #endif
 
@@ -1703,6 +1767,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       _M_erase(iterator __position) _GLIBCXX_NOEXCEPT
       {
+	this->_M_dec_size(1);
         __position._M_node->_M_unhook();
         _Node* __n = static_cast<_Node*>(__position._M_node);
 #if __cplusplus >= 201103L
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
index 885e753..f8a9c3e 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1665 }
+// { dg-error "no matching" "" { target *-*-* } 1727 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
index ccd9d17..7b64ea9 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1617 }
+// { dg-error "no matching" "" { target *-*-* } 1679 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
index 04966dc..d2184a6 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1617 }
+// { dg-error "no matching" "" { target *-*-* } 1679 }
 
 #include <list>
 #include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
index 759dad6..3615dfe 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1617 }
+// { dg-error "no matching" "" { target *-*-* } 1679 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
index 17df71a..5597c57 100644
--- a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
+++ b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
@@ -25,4 +25,4 @@
 
 #include <vector>
 
-// { dg-error "multiple inlined namespaces" "" { target *-*-* } 279 }
+// { dg-error "multiple inlined namespaces" "" { target *-*-* } 290 }

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch] Use abi_tag attribute on std::list
  2014-10-03 13:04 [patch] Use abi_tag attribute on std::list Jonathan Wakely
@ 2014-10-03 14:25 ` Marc Glisse
  2014-10-03 14:50   ` Jonathan Wakely
  0 siblings, 1 reply; 6+ messages in thread
From: Marc Glisse @ 2014-10-03 14:25 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Fri, 3 Oct 2014, Jonathan Wakely wrote:

> This is the patch I intend to commit to make std::list::size() O(1) as
> required by C++11.
>
> This is an ABI change, so std::list will get tagged with
> abi_tag("cxx11") so that it mangles differently.

Assuming a future where we have both _GLIBCXX_ABI_TAG_CXX11 and 
_GLIBCXX_ABI_TAG_CXX17, I don't really see how _GLIBCXX_DEFAULT_ABI_TAG
is supposed to work. We don't want to define _GLIBCXX_DEFAULT_ABI_TAG to 
_GLIBCXX_ABI_TAG_CXX17 and suddenly have std::list change mangling. Should 
it be called _GLIBCXX_DEFAULT_ABI_TAG_CXX11, meaning 
_GLIBCXX_ABI_TAG_CXX11_IF_ENABLED_AND_NOTHING_OTHERWISE?

Defining a dummy _M_distance in the old abi case is a bit strange (we 
could protect the single use with #if _GLIBCXX_USE_CXX11_ABI), but why 
not...

Do you mind if I move (in a future patch once yours is committed) _M_size 
into _M_impl::_M_node as suggested in PR 61347?

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch] Use abi_tag attribute on std::list
  2014-10-03 14:25 ` Marc Glisse
@ 2014-10-03 14:50   ` Jonathan Wakely
  2014-10-03 15:24     ` Jonathan Wakely
  2014-10-10 15:47     ` Jonathan Wakely
  0 siblings, 2 replies; 6+ messages in thread
From: Jonathan Wakely @ 2014-10-03 14:50 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

On 03/10/14 16:25 +0200, Marc Glisse wrote:
>On Fri, 3 Oct 2014, Jonathan Wakely wrote:
>
>>This is the patch I intend to commit to make std::list::size() O(1) as
>>required by C++11.
>>
>>This is an ABI change, so std::list will get tagged with
>>abi_tag("cxx11") so that it mangles differently.
>
>Assuming a future where we have both _GLIBCXX_ABI_TAG_CXX11 and 
>_GLIBCXX_ABI_TAG_CXX17, I don't really see how 
>_GLIBCXX_DEFAULT_ABI_TAG
>is supposed to work. We don't want to define _GLIBCXX_DEFAULT_ABI_TAG 
>to _GLIBCXX_ABI_TAG_CXX17 and suddenly have std::list change mangling. 

True.

>Should it be called _GLIBCXX_DEFAULT_ABI_TAG_CXX11, meaning 
>_GLIBCXX_ABI_TAG_CXX11_IF_ENABLED_AND_NOTHING_OTHERWISE?

I suppose so ... or _GLIBCXX_MAYBE_ABI_TAG_CXX11 ?

>Defining a dummy _M_distance in the old abi case is a bit strange (we 
>could protect the single use with #if _GLIBCXX_USE_CXX11_ABI), but why 
>not...

Yeah, I was trying to minimise the preprocessor conditionals, but
maybe that's one step too far.

>Do you mind if I move (in a future patch once yours is committed) 
>_M_size into _M_impl::_M_node as suggested in PR 61347?

Gah, that's where I had it until earlier this week, and I looked at it
and wondered why it was in the _List_impl class (because you only need
one member in there to benefit from the empty base-class
optimisation).

I will move it back there, since I already have that code on another
branch, so there's no point making you change the code to match
something I've already got!

Thanks for your useful comments (as always).

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch] Use abi_tag attribute on std::list
  2014-10-03 14:50   ` Jonathan Wakely
@ 2014-10-03 15:24     ` Jonathan Wakely
  2014-10-03 15:33       ` Marc Glisse
  2014-10-10 15:47     ` Jonathan Wakely
  1 sibling, 1 reply; 6+ messages in thread
From: Jonathan Wakely @ 2014-10-03 15:24 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 794 bytes --]

On 03/10/14 15:49 +0100, Jonathan Wakely wrote:
>On 03/10/14 16:25 +0200, Marc Glisse wrote:
>>Do you mind if I move (in a future patch once yours is committed) 
>>_M_size into _M_impl::_M_node as suggested in PR 61347?
>
>Gah, that's where I had it until earlier this week, and I looked at it
>and wondered why it was in the _List_impl class (because you only need
>one member in there to benefit from the empty base-class
>optimisation).
>
>I will move it back there, since I already have that code on another
>branch, so there's no point making you change the code to match
>something I've already got!

Marc, this is the relative diff to go back to what I had earlier, with
the size in the _List_impl in case you want to aply it locally (the
dg-error tests are off-by-one with this patch)


[-- Attachment #2: list.txt --]
[-- Type: text/plain, Size: 2967 bytes --]

diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 3a56daf..4dbdaf0 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -333,6 +333,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       : public _Node_alloc_type
       {
 	__detail::_List_node_base _M_node;
+#if _GLIBCXX_USE_CXX11_ABI
+	size_t			  _M_size;
+
+	// return the stored size
+	size_t _M_node_count() const { return _M_size; }
+#else
+	// count the number of nodes
+	size_t _M_node_count() const
+	{ return _S_distance(_M_node._M_next, std::__addressof(_M_node)); }
+#endif
+
 	_List_impl()
 	: _Node_alloc_type(), _M_node()
 	{ }
@@ -350,24 +361,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       _List_impl _M_impl;
 
-#if _GLIBCXX_USE_CXX11_ABI
-      size_t	 _M_size;
+      _List_node<_Tp>*
+      _M_get_node()
+      { return _M_impl._Node_alloc_type::allocate(1); }
+
+      void
+      _M_put_node(_List_node<_Tp>* __p) _GLIBCXX_NOEXCEPT
+      { _M_impl._Node_alloc_type::deallocate(__p, 1); }
 
-      size_t _M_get_size() const { return _M_size; }
+#if _GLIBCXX_USE_CXX11_ABI
+      size_t _M_get_size() const { return _M_impl._M_size; }
 
-      void _M_set_size(size_t __n) { _M_size = __n; }
+      void _M_set_size(size_t __n) { _M_impl._M_size = __n; }
 
-      void _M_inc_size(size_t __n) { _M_size += __n; }
+      void _M_inc_size(size_t __n) { _M_impl._M_size += __n; }
 
-      void _M_dec_size(size_t __n) { _M_size -= __n; }
+      void _M_dec_size(size_t __n) { _M_impl._M_size -= __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; }
 #else
       // dummy implementations used when the size is not stored
       size_t _M_get_size() const { return 0; }
@@ -375,23 +389,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       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
-      {
-	return _S_distance(_M_impl._M_node._M_next,
-			   std::__addressof(_M_impl._M_node));
-      }
 #endif
 
-      _List_node<_Tp>*
-      _M_get_node()
-      { return _M_impl._Node_alloc_type::allocate(1); }
-
-      void
-      _M_put_node(_List_node<_Tp>* __p) _GLIBCXX_NOEXCEPT
-      { _M_impl._Node_alloc_type::deallocate(__p, 1); }
-
   public:
       typedef _Alloc allocator_type;
 
@@ -941,7 +940,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /**  Returns the number of elements in the %list.  */
       size_type
       size() const _GLIBCXX_NOEXCEPT
-      { return this->_M_node_count(); }
+      { return this->_M_impl._M_node_count(); }
 
       /**  Returns the size() of the largest possible %list.  */
       size_type

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch] Use abi_tag attribute on std::list
  2014-10-03 15:24     ` Jonathan Wakely
@ 2014-10-03 15:33       ` Marc Glisse
  0 siblings, 0 replies; 6+ messages in thread
From: Marc Glisse @ 2014-10-03 15:33 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On Fri, 3 Oct 2014, Jonathan Wakely wrote:

> Marc, this is the relative diff to go back to what I had earlier, with
> the size in the _List_impl in case you want to aply it locally (the
> dg-error tests are off-by-one with this patch)

Thanks. For PR 61347, to avoid offsetof, I will actually need to 
change:

- __detail::_List_node_base _M_node;
- size_t _M_size;
+ _List_node<size_t> _M_node;

and store the size in _M_node._M_data. Since I will have to touch it 
anyway, don't feel forced to move it to _M_impl.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [patch] Use abi_tag attribute on std::list
  2014-10-03 14:50   ` Jonathan Wakely
  2014-10-03 15:24     ` Jonathan Wakely
@ 2014-10-10 15:47     ` Jonathan Wakely
  1 sibling, 0 replies; 6+ messages in thread
From: Jonathan Wakely @ 2014-10-10 15:47 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2122 bytes --]

On 03/10/14 15:49 +0100, Jonathan Wakely wrote:
>On 03/10/14 16:25 +0200, Marc Glisse wrote:
>>On Fri, 3 Oct 2014, Jonathan Wakely wrote:
>>
>>>This is the patch I intend to commit to make std::list::size() O(1) as
>>>required by C++11.
>>>
>>>This is an ABI change, so std::list will get tagged with
>>>abi_tag("cxx11") so that it mangles differently.
>>
>>Assuming a future where we have both _GLIBCXX_ABI_TAG_CXX11 and 
>>_GLIBCXX_ABI_TAG_CXX17, I don't really see how 
>>_GLIBCXX_DEFAULT_ABI_TAG
>>is supposed to work. We don't want to define 
>>_GLIBCXX_DEFAULT_ABI_TAG to _GLIBCXX_ABI_TAG_CXX17 and suddenly have 
>>std::list change mangling.
>
>True.
>
>>Should it be called _GLIBCXX_DEFAULT_ABI_TAG_CXX11, meaning 
>>_GLIBCXX_ABI_TAG_CXX11_IF_ENABLED_AND_NOTHING_OTHERWISE?
>
>I suppose so ... or _GLIBCXX_MAYBE_ABI_TAG_CXX11 ?
>
>>Defining a dummy _M_distance in the old abi case is a bit strange 
>>(we could protect the single use with #if _GLIBCXX_USE_CXX11_ABI), 
>>but why not...
>
>Yeah, I was trying to minimise the preprocessor conditionals, but
>maybe that's one step too far.
>
>>Do you mind if I move (in a future patch once yours is committed) 
>>_M_size into _M_impl::_M_node as suggested in PR 61347?
>
>Gah, that's where I had it until earlier this week, and I looked at it
>and wondered why it was in the _List_impl class (because you only need
>one member in there to benefit from the empty base-class
>optimisation).
>
>I will move it back there, since I already have that code on another
>branch, so there's no point making you change the code to match
>something I've already got!
>
>Thanks for your useful comments (as always).

I've committed the attached patch, which I think is the same as the
one I posted a week ago.

Marc, I agree with your comments, but chose to ignore them ;-) For
now, anyway. I want to get something committed, we can improve it in
stage 3, or when we need to worry about a C++17 ABI change.

Tested x86_64-linux, committed to trunk.

Documentation for the abi_tag("cxx11") changes will follow ASAP, but
probably during stage 3, once all the changes are committed.

[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 15376 bytes --]

commit 3ac61312eb285d125da8af4c6cdaad1b1ce7d235
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 7 01:13:17 2014 +0100

    	PR libstdc++/49561
    	* acinclude.m4 (GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI): Define.
    	* configure.ac: Use GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI.
    	* configure: Regenerate.
    	* include/Makefile.am (stamp-cxx11-abi): New target.
    	(c++config.h): Set _GLIBCXX_USE_CXX11_ABI macro.
    	* include/Makefile.in: Regenerate.
    	* include/bits/c++config: Add _GLIBCXX_USE_CXX11_ABI placeholder and
    	define _GLIBCXX_DEFAULT_ABI_TAG.
    	* include/bits/list.tcc (list::emplace(const_iterator, _Args&...)):
    	Increment size.
    	(list::emplace(const_iterator, const value_type&)): Likewise.
    	(list::merge(list&), list::merge(list&, _StrictWeakOrdering)): Adjust
    	list sizes.
    	* include/bits/stl_list.h (_List_base, list): Add ABI tag macro.
    	(_List_base::_M_size): New data member in cxx11 ABI mode.
    	(_List_base::_S_distance(_List_node_base*, _List_node_base*)): New
    	function.
    	(_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_distance, _List_base::_M_node_count): New functions for
    	accessing list size correctly for the ABI mode.
    	(_List_base::_List_base(_List_base&&)): Copy size and reset source.
    	(_List_base::_M_init()): Initialize size member.
    	(list::size()): Use _List_base::_M_node_count.
    	(list::swap(list&)): Swap sizes.
    	(list::splice(iterator, list&)): Update sizes.
    	(list::splice(iterator, list&, iterator)): Likewise.
    	(list::insert(iterator, const value_type&)): Update size.
    	(list::insert(iterator, _Args&&...)): Likewise.
    	(list::_M_erase(iterator)): Likewise.
    	* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
    	Adjust.
    	* testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc:
    	Adjust.
    	* testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc:
    	Adjust.
    	* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
    	Adjust.
    	* testsuite/ext/profile/mutex_extensions_neg.cc: Adjust.

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 2650a5a..0229609 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -3831,6 +3831,25 @@ AC_DEFUN([GLIBCXX_CHECK_SDT_H], [
   AC_MSG_RESULT($glibcxx_cv_sys_sdt_h)
 ])
 
+dnl
+dnl Check if the user wants the new C++11-conforming ABI.
+dnl
+dnl --disable-libstdcxx-cxx11-abi will use old ABI for all types.
+dnl
+dnl Defines:
+dnl  _GLIBCXX_USE_ABI_TAG (always defined, either to 1 or 0)
+dnl
+AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI], [
+  AC_ARG_ENABLE([libstdcxx-cxx11-abi],
+    AC_HELP_STRING([--disable-libstdcxx-cxx11-abi],
+		   [disable the C++11-conforming ABI]),,
+		   [enable_libstdcxx_cxx11_abi=yes])
+  if test x"$enable_libstdcxx_cxx11_abi" != xyes; then
+    AC_MSG_NOTICE([C++11-conforming ABI is disabled])
+  fi
+  GLIBCXX_CONDITIONAL(ENABLE_CXX11_ABI, test $enable_libstdcxx_cxx11_abi = yes)
+])
+
 # Macros from the top-level gcc directory.
 m4_include([../config/gc++filt.m4])
 m4_include([../config/tls.m4])
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 1de0f6c..eb826e4 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -365,6 +365,8 @@ AC_SUBST(libtool_VERSION)
 
 GLIBCXX_ENABLE_LIBSTDCXX_VISIBILITY([yes])
 
+GLIBCXX_ENABLE_LIBSTDCXX_CXX11_ABI([yes])
+
 ac_ldbl_compat=no
 case "$target" in
   powerpc*-*-linux* | \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index dee4a3f..e3aed84 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1122,6 +1122,14 @@ stamp-visibility:
 	echo 0 > stamp-visibility
 endif
 
+if ENABLE_CXX11_ABI
+stamp-cxx11-abi:
+	echo 1 > stamp-cxx11-abi
+else
+stamp-cxx11-abi:
+	echo 0 > stamp-cxx11-abi
+endif
+
 # NB: The non-empty default ldbl_compat works around an AIX sed
 # oddity, see libstdc++/31957 for details.
 ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
@@ -1130,11 +1138,13 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 			      ${toplevel_srcdir}/gcc/DATESTAMP \
 			      stamp-namespace-version \
 			      stamp-visibility \
-			      stamp-extern-template
+			      stamp-extern-template \
+			      stamp-cxx11-abi
 	@date=`cat ${toplevel_srcdir}/gcc/DATESTAMP` ;\
 	ns_version=`cat stamp-namespace-version` ;\
 	visibility=`cat stamp-visibility` ;\
 	externtemplate=`cat stamp-extern-template` ;\
+	cxx11abi=`cat stamp-cxx11-abi` ;\
 	ldbl_compat='s,g,g,' ;\
 	grep "^[	 ]*#[	 ]*define[	 ][	 ]*_GLIBCXX_LONG_DOUBLE_COMPAT[	 ][	 ]*1[	 ]*$$" \
 	${CONFIG_HEADER} > /dev/null 2>&1 \
@@ -1143,6 +1153,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
 	-e "s,define _GLIBCXX_INLINE_VERSION, define _GLIBCXX_INLINE_VERSION $$ns_version," \
 	-e "s,define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY, define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY $$visibility," \
 	-e "s,define _GLIBCXX_EXTERN_TEMPLATE$$, define _GLIBCXX_EXTERN_TEMPLATE $$externtemplate," \
+	-e "s,define _GLIBCXX_USE_CXX11_ABI, define _GLIBCXX_USE_CXX11_ABI $$cxx11abi," \
 	-e "$$ldbl_compat" \
 	    < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
 	sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index ff6afc8..bb58a9b 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -193,6 +193,17 @@ namespace std
 #endif
 }
 
+// Use abi_tag("cxx11")
+#ifndef _GLIBCXX_USE_CXX11_ABI
+#define _GLIBCXX_USE_CXX11_ABI
+#endif
+
+#if _GLIBCXX_USE_CXX11_ABI
+# define _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_ABI_TAG_CXX11
+#else
+# define _GLIBCXX_DEFAULT_ABI_TAG
+#endif
+
 
 // Defined if inline namespaces are used for versioning.
 #define _GLIBCXX_INLINE_VERSION 
diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc
index 42855a4..f99ec54 100644
--- a/libstdc++-v3/include/bits/list.tcc
+++ b/libstdc++-v3/include/bits/list.tcc
@@ -89,6 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
 	_Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
 	__tmp->_M_hook(__position._M_const_cast()._M_node);
+	this->_M_inc_size(1);
 	return iterator(__tmp);
       }
 #endif
@@ -104,6 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     {
       _Node* __tmp = _M_create_node(__x);
       __tmp->_M_hook(__position._M_const_cast()._M_node);
+      this->_M_inc_size(1);
       return iterator(__tmp);
     }
 
@@ -353,6 +355,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	      ++__first1;
 	  if (__first2 != __last2)
 	    _M_transfer(__last1, __first2, __last2);
+
+	  this->_M_inc_size(__x._M_get_size());
+	  __x._M_set_size(0);
 	}
     }
 
@@ -387,6 +392,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		++__first1;
 	    if (__first2 != __last2)
 	      _M_transfer(__last1, __first2, __last2);
+
+	    this->_M_inc_size(__x._M_get_size());
+	    __x._M_set_size(0);
 	  }
       }
 
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index dd9bba7..8e6567c 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -295,7 +295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
   /// See bits/stl_deque.h's _Deque_base for an explanation.
   template<typename _Tp, typename _Alloc>
-    class _List_base
+    class _GLIBCXX_DEFAULT_ABI_TAG _List_base
     {
     protected:
       // NOTA BENE
@@ -316,6 +316,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
 
+      static size_t
+      _S_distance(const __detail::_List_node_base* __first,
+		  const __detail::_List_node_base* __last)
+      {
+	size_t __n = 0;
+	while (__first != __last)
+	  {
+	    __first = __first->_M_next;
+	    ++__n;
+	  }
+	return __n;
+      }
+
       struct _List_impl
       : public _Node_alloc_type
       {
@@ -338,6 +351,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       _List_impl _M_impl;
 
+#if _GLIBCXX_USE_CXX11_ABI
+      size_t	 _M_size;
+
+      size_t _M_get_size() const { return _M_size; }
+
+      void _M_set_size(size_t __n) { _M_size = __n; }
+
+      void _M_inc_size(size_t __n) { _M_size += __n; }
+
+      void _M_dec_size(size_t __n) { _M_size -= __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; }
+#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
+      {
+	return _S_distance(_M_impl._M_node._M_next,
+			   std::__addressof(_M_impl._M_node));
+      }
+#endif
+
       _List_node<_Tp>*
       _M_get_node()
       { return _M_impl._Node_alloc_type::allocate(1); }
@@ -386,7 +433,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    __node->_M_next = __xnode->_M_next;
 	    __node->_M_prev = __xnode->_M_prev;
 	    __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node;
-	    __xnode->_M_next = __xnode->_M_prev = __xnode;
+	    _M_set_size(__x._M_get_size());
+	    __x._M_init();
 	  }
       }
 #endif
@@ -403,6 +451,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
         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);
       }
     };
 
@@ -453,7 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
    *  %empty. 
   */
   template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
-    class list : protected _List_base<_Tp, _Alloc>
+    class _GLIBCXX_DEFAULT_ABI_TAG list : protected _List_base<_Tp, _Alloc>
     {
       // concept requirements
       typedef typename _Alloc::value_type                _Alloc_value_type;
@@ -893,7 +942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       /**  Returns the number of elements in the %list.  */
       size_type
       size() const _GLIBCXX_NOEXCEPT
-      { return std::distance(begin(), end()); }
+      { return this->_M_node_count(); }
 
       /**  Returns the size() of the largest possible %list.  */
       size_type
@@ -1295,6 +1344,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	__detail::_List_node_base::swap(this->_M_impl._M_node, 
 					__x._M_impl._M_node);
 
+	size_t __xsize = __x._M_get_size();
+	__x._M_set_size(this->_M_get_size());
+	this->_M_set_size(__xsize);
+
 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
 	// 431. Swapping containers with unequal allocators.
 	std::__alloc_swap<typename _Base::_Node_alloc_type>::
@@ -1339,6 +1392,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 	    this->_M_transfer(__position._M_const_cast(),
 			      __x.begin(), __x.end());
+
+	    this->_M_inc_size(__x._M_get_size());
+	    __x._M_set_size(0);
 	  }
       }
 
@@ -1385,6 +1441,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 	this->_M_transfer(__position._M_const_cast(),
 			  __i._M_const_cast(), __j);
+
+	this->_M_inc_size(1);
+	__x._M_dec_size(1);
       }
 
 #if __cplusplus >= 201103L
@@ -1443,6 +1502,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	    if (this != &__x)
 	      _M_check_equal_allocators(__x);
 
+	    size_t __n = this->_M_distance(__first._M_node, __last._M_node);
+	    this->_M_inc_size(__n);
+	    __x._M_dec_size(__n);
+
 	    this->_M_transfer(__position._M_const_cast(),
 			      __first._M_const_cast(),
 			      __last._M_const_cast());
@@ -1688,6 +1751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       {
         _Node* __tmp = _M_create_node(__x);
         __tmp->_M_hook(__position._M_node);
+	this->_M_inc_size(1);
       }
 #else
      template<typename... _Args>
@@ -1696,6 +1760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        {
 	 _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
 	 __tmp->_M_hook(__position._M_node);
+	 this->_M_inc_size(1);
        }
 #endif
 
@@ -1703,6 +1768,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       _M_erase(iterator __position) _GLIBCXX_NOEXCEPT
       {
+	this->_M_dec_size(1);
         __position._M_node->_M_unhook();
         _Node* __n = static_cast<_Node*>(__position._M_node);
 #if __cplusplus >= 201103L
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
index 885e753..183753d 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1665 }
+// { dg-error "no matching" "" { target *-*-* } 1728 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
index ccd9d17..e81ff98 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1617 }
+// { dg-error "no matching" "" { target *-*-* } 1680 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
index 04966dc..c98aa0f 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1617 }
+// { dg-error "no matching" "" { target *-*-* } 1680 }
 
 #include <list>
 #include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
index 759dad6..1397796 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1617 }
+// { dg-error "no matching" "" { target *-*-* } 1680 }
 
 #include <list>
 
diff --git a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
index 17df71a..5597c57 100644
--- a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
+++ b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
@@ -25,4 +25,4 @@
 
 #include <vector>
 
-// { dg-error "multiple inlined namespaces" "" { target *-*-* } 279 }
+// { dg-error "multiple inlined namespaces" "" { target *-*-* } 290 }

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-10-10 15:40 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-03 13:04 [patch] Use abi_tag attribute on std::list Jonathan Wakely
2014-10-03 14:25 ` Marc Glisse
2014-10-03 14:50   ` Jonathan Wakely
2014-10-03 15:24     ` Jonathan Wakely
2014-10-03 15:33       ` Marc Glisse
2014-10-10 15:47     ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).