diff mbox series

Add allocator-extended copy/move ctors to COW string

Message ID 20190104232331.GA21282@redhat.com
State New
Headers show
Series Add allocator-extended copy/move ctors to COW string | expand

Commit Message

Jonathan Wakely Jan. 4, 2019, 11:23 p.m. UTC
Add these constructors from C++11 which were missing from the COW
basic_string. Additionally simplify the definitions of the
basic_string::reference and basic_string::const_reference types as
required by C++11.

This allows filesystem::path::string<Allocator>() to be simplified, so
that the same code is used for both basic_string implementations.

	* config/abi/pre/gnu.ver (GLIBCXX_3.4.26): Export allocator-extended
	copy/move constructors for old std::basic_string.
	* include/bits/basic_string.h [!_GLIBCXX_USE_CXX11_ABI]
	(basic_string::reference, basic_string::const_reference): Define
	as plain references for C++11 and later.
	(basic_string::basic_string()): Put constructor body outside
	preprocessor conditional groups.
	(basic_string::basic_string(basic_string&&)): Move _Alloc_hider
	instead of copying it.
	(basic_string::basic_string(const basic_string&, const _Alloc&)):
	Define.
	(basic_string::basic_string(basic_string&&, const _Alloc&)):
	Define.
	* include/bits/fs_path.h [!_GLIBCXX_USE_CXX11_ABI]: Remove special
	cases for old basic_string.
	* testsuite/21_strings/basic_string/cons/char/8.cc: Test
	allocator-extended constructors unconditionally. Add extra members to
	allocator type when using old string ABI.
	* testsuite/21_strings/basic_string/allocator/71964.cc: Enable test
	for old string ABI.
	* testsuite/21_strings/basic_string/cons/wchar_t/8.cc: Likewise.

Tested powerpc64-linux, committed to trunk.

There are still more new symbols that I plan to add to the library, so
don't regenerate baseline_symbols.txt files yet.
commit d8b09a24301736d69db0d041b4fb313b185c635d
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 25 22:39:53 2018 +0100

    Add allocator-extended copy/move ctors to COW string
    
    Add these constructors from C++11 which were missing from the COW
    basic_string. Additionally simplify the definitions of the
    basic_string::reference and basic_string::const_reference types as
    required by C++11.
    
    This allows filesystem::path::string<Allocator>() to be simplified, so
    that the same code is used for both basic_string implementations.
    
            * config/abi/pre/gnu.ver (GLIBCXX_3.4.26): Export allocator-extended
            copy/move constructors for old std::basic_string.
            * include/bits/basic_string.h [!_GLIBCXX_USE_CXX11_ABI]
            (basic_string::reference, basic_string::const_reference): Define
            as plain references for C++11 and later.
            (basic_string::basic_string()): Put constructor body outside
            preprocessor conditional groups.
            (basic_string::basic_string(basic_string&&)): Move _Alloc_hider
            instead of copying it.
            (basic_string::basic_string(const basic_string&, const _Alloc&)):
            Define.
            (basic_string::basic_string(basic_string&&, const _Alloc&)):
            Define.
            * include/bits/fs_path.h [!_GLIBCXX_USE_CXX11_ABI]: Remove special
            cases for old basic_string.
            * testsuite/21_strings/basic_string/cons/char/8.cc: Test
            allocator-extended constructors unconditionally. Add extra members to
            allocator type when using old string ABI.
            * testsuite/21_strings/basic_string/allocator/71964.cc: Enable test
            for old string ABI.
            * testsuite/21_strings/basic_string/cons/wchar_t/8.cc: Likewise.
diff mbox series

Patch

diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index de3c87abf15..1d157288fcf 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -2072,6 +2072,11 @@  GLIBCXX_3.4.26 {
     _ZNSt14collate_bynameI[cw]EC[12]ERKSs[jmy];
     _ZNKSt8time_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE3getES3_S3_RSt8ios_baseRSt12_Ios_IostateP2tmcc;
 
+    _ZNSsC[12]ERKSsRKSaIcE;
+    _ZNSsC[12]EOSsRKSaIcE;
+    _ZNSbIwSt11char_traitsIwESaIwEEC[12]ERKS2_RKS1_;
+    _ZNSbIwSt11char_traitsIwESaIwEEC[12]EOS2_RKS1_;
+
 } GLIBCXX_3.4.25;
 
 # Symbols in the support library (libsupc++) have their own tag.
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index e96d93fca34..43460df5d1f 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -3145,8 +3145,13 @@  _GLIBCXX_END_NAMESPACE_CXX11
       typedef _Alloc					    allocator_type;
       typedef typename _CharT_alloc_type::size_type	    size_type;
       typedef typename _CharT_alloc_type::difference_type   difference_type;
+#if __cplusplus < 201103L
       typedef typename _CharT_alloc_type::reference	    reference;
       typedef typename _CharT_alloc_type::const_reference   const_reference;
+#else
+      typedef value_type&				    reference;
+      typedef const value_type&				    const_reference;
+#endif
       typedef typename _CharT_alloc_type::pointer	    pointer;
       typedef typename _CharT_alloc_type::const_pointer	    const_pointer;
       typedef __gnu_cxx::__normal_iterator<pointer, basic_string>  iterator;
@@ -3526,10 +3531,11 @@  _GLIBCXX_END_NAMESPACE_CXX11
       basic_string()
 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
       _GLIBCXX_NOEXCEPT
-      : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
+      : _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc())
 #else
-      : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()){ }
+      : _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc())
 #endif
+      { }
 
       /**
        *  @brief  Construct an empty string using allocator @a a.
@@ -3610,7 +3616,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
       noexcept // FIXME C++11: should always be noexcept.
 #endif
-      : _M_dataplus(__str._M_dataplus)
+      : _M_dataplus(std::move(__str._M_dataplus))
       {
 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
 	__str._M_data(_S_empty_rep()._M_refdata());
@@ -3625,6 +3631,25 @@  _GLIBCXX_END_NAMESPACE_CXX11
        *  @param  __a  Allocator to use (default is default allocator).
        */
       basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc());
+
+      basic_string(const basic_string& __str, const _Alloc& __a)
+      : _M_dataplus(__str._M_rep()->_M_grab(__a, __str.get_allocator()), __a)
+      { }
+
+      basic_string(basic_string&& __str, const _Alloc& __a)
+      : _M_dataplus(__str._M_data(), __a)
+      {
+	if (__a == __str.get_allocator())
+	  {
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
+	    __str._M_data(_S_empty_rep()._M_refdata());
+#else
+	    __str._M_data(_S_construct(size_type(), _CharT(), __a));
+#endif
+	  }
+	else
+	  _M_dataplus._M_p = _S_construct(__str.begin(), __str.end(), __a);
+      }
 #endif // C++11
 
       /**
diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h
index 34a5d324ce0..37dcfc16703 100644
--- a/libstdc++-v3/include/bits/fs_path.h
+++ b/libstdc++-v3/include/bits/fs_path.h
@@ -965,16 +965,7 @@  _GLIBCXX_BEGIN_NAMESPACE_CXX11
     path::string(const _Allocator& __a) const
     {
       if constexpr (is_same_v<_CharT, value_type>)
-	{
-#if _GLIBCXX_USE_CXX11_ABI
-	  return { _M_pathname, __a };
-#else
-	  if constexpr (is_same_v<_Allocator, string_type::allocator_type>)
-	    return _M_pathname;
-	  else
-	    return { _M_pathname, string_type::size_type(0), __a };
-#endif
-	}
+	return { _M_pathname, __a };
       else
 	return _S_str_convert<_CharT, _Traits>(_M_pathname, __a);
     }
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc
index 1d52738cfc2..2bebb232d41 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/71964.cc
@@ -16,8 +16,6 @@ 
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do run { target c++11 } }
-// COW strings don't support C++11 allocators:
-// { dg-require-effective-target cxx11-abi }
 
 #include <string>
 #include <testsuite_hooks.h>
@@ -47,6 +45,17 @@  template<typename T>
 
     bool moved_to;
     bool moved_from;
+
+#if ! _GLIBCXX_USE_CXX11_ABI
+    // COW string doesn't use allocator_traits, requires C++03 allocator API.
+    using pointer = T*;
+    using const_pointer = const T*;
+    using difference_type = int;
+    template<typename U> struct rebind { using other = mv_allocator<U>; };
+    void construct(pointer p, const T& val) { ::new(p) T(val); }
+    void destroy(pointer p) { p->~T(); }
+    size_type max_size() const { return std::allocator<T>().max_size(); }
+#endif
   };
 
 template<typename T, typename U>
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/8.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/8.cc
index 28cdb938624..d99fb732722 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/8.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/8.cc
@@ -70,10 +70,8 @@  test01()
   VERIFY( construct( lvalue.begin(), lvalue.end(), alloc ) == 6 );
   VERIFY( construct( list{ 'l' , 'i' , 's', 't' } ) == 4 );
   VERIFY( construct( list{ 'l', 'i', 's', 't' }, alloc ) == 4 );
-#if _GLIBCXX_USE_CXX11_ABI
   VERIFY( construct( lvalue, alloc ) == 6 );
   VERIFY( construct( string{"rvalue"}, alloc ) == 6 );
-#endif
 }
 
 int
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/8.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/8.cc
index f5fc9d6af78..8c330e38aea 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/8.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/8.cc
@@ -70,10 +70,8 @@  test01()
   VERIFY( construct( lvalue.begin(), lvalue.end(), alloc ) == 6 );
   VERIFY( construct( list{ L'l' , L'i' , L's', L't' } ) == 4 );
   VERIFY( construct( list{ L'l', L'i', L's', L't' }, alloc ) == 4 );
-#if _GLIBCXX_USE_CXX11_ABI
   VERIFY( construct( lvalue, alloc ) == 6 );
   VERIFY( construct( string{L"rvalue"}, alloc ) == 6 );
-#endif
 }
 
 int