From 4ff3e6509066e2832fdfe9987e7fd2f8719da93f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 4 Jan 2019 23:23:17 +0000 Subject: [PATCH] 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() 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. From-SVN: r267584 --- libstdc++-v3/ChangeLog | 22 +++++++++++++ libstdc++-v3/config/abi/pre/gnu.ver | 5 +++ libstdc++-v3/include/bits/basic_string.h | 31 +++++++++++++++++-- libstdc++-v3/include/bits/fs_path.h | 11 +------ .../basic_string/allocator/71964.cc | 13 ++++++-- .../21_strings/basic_string/cons/char/8.cc | 2 -- .../21_strings/basic_string/cons/wchar_t/8.cc | 2 -- 7 files changed, 67 insertions(+), 19 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0297d936919..226365d6d20 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,27 @@ 2019-01-04 Jonathan Wakely + * 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. + * testsuite/23_containers/list/61347.cc: Avoid spurious failure when -fno-inline added to test flags. 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 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 @@ // . // { dg-do run { target c++11 } } -// COW strings don't support C++11 allocators: -// { dg-require-effective-target cxx11-abi } #include #include @@ -47,6 +45,17 @@ template 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 struct rebind { using other = mv_allocator; }; + 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().max_size(); } +#endif }; template 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 -- 2.30.2