This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] PR libstdc++/58265 implement LWG 2063 for COW strings


On 05/07/18 16:55 +0100, Jonathan Wakely wrote:
For COW strings the default constructor does not allocate when
_GLIBCXX_FULLY_DYNAMIC_STRING == 0, so can be noexcept. The move
constructor and swap do not allocate when the allocators are equal, so
add conditional noexcept using allocator_traits::is_always_equal.

	PR libstdc++/58265
	* include/bits/basic_string.h [!_GLIBCXX_USE_CXX11_ABI]
	[_GLIBCXX_FULLY_DYNAMIC_STRING==0] (basic_string::basic_string()):
	Add GLIBCXX_NOEXCEPT.
	(basic_string::operator=(basic_string&&)): Add _GLIBCXX_NOEXCEPT_IF
	to depend on the allocator's is_always_equal property (LWG 2063).
	(basic_string::swap(basic_string&)): Likewise.
	* include/bits/basic_string.tcc [!_GLIBCXX_USE_CXX11_ABI]
	(basic_string::swap(basic_string&)): Likewise.
	* testsuite/21_strings/basic_string/allocator/char/move_assign.cc:
	Check is_nothrow_move_assignable.
	* testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc:
	Check is_nothrow_move_assignable.
	* testsuite/21_strings/basic_string/cons/char/
	noexcept_move_construct.cc: Likewise.
	* testsuite/21_strings/basic_string/cons/wchar_t/
	noexcept_move_construct.cc: Likewise.

I missed a bit, finished by this patch. With these changes the SSO and
COW strings are slightly closer in behaviour, although the COW one is
still missing lots of C++11 features (like passing const_iterator
instead of iterator) and C++17 features (deduction guides).

Tested powerpc64le-linux, committed to trunk.


commit 265fc27e34d7fb8fb80653e3f9782c56c70a7ce4
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jul 5 17:08:54 2018 +0100

    PR libstdc++/58265 add noexcept to basic_string::assign(basic_string&&)
    
            PR libstdc++/58265
            * include/bits/basic_string.h [!_GLIBCXX_USE_CXX11_ABI]
            (basic_string::assign(basic_string&&)): Add conditional noexcept
            depending on the allocator's is_always_equal property (LWG 2063).
            * testsuite/21_strings/basic_string/modifiers/assign/char/
            move_assign.cc: Check for non-throwing exception specification.
            * testsuite/21_strings/basic_string/modifiers/assign/wchar_t/
            move_assign.cc: Likewise.

diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index baad58682b6..2d1b9dc6c29 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -725,7 +725,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        *  The contents of @a str are moved into this string (without copying).
        *  @a str is a valid, but unspecified string.
        **/
-      // PR 58265, this should be noexcept.
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 2063. Contradictory requirements for string move assignment
       basic_string&
@@ -4275,9 +4274,9 @@ _GLIBCXX_END_NAMESPACE_CXX11
        *  This function sets this string to the exact contents of @a __str.
        *  @a __str is a valid, but unspecified string.
        */
-      // PR 58265, this should be noexcept.
       basic_string&
       assign(basic_string&& __str)
+      noexcept(allocator_traits<_Alloc>::is_always_equal::value)
       {
 	this->swap(__str);
 	return *this;
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/move_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/move_assign.cc
index e9116b9c0e0..7089fea04c2 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/move_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/move_assign.cc
@@ -32,6 +32,9 @@ void test01()
   a.push_back('1');
   b.assign(std::move(a));
   VERIFY( b.size() == 1 && b[0] == '1' && a.size() == 0 );
+
+  // True for std::allocator because is_always_equal, but not true in general:
+  static_assert(noexcept(a.assign(std::move(b))), "lwg 2063");
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/move_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/move_assign.cc
index 74e342a8ef4..8d394602a9f 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/move_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/move_assign.cc
@@ -32,6 +32,9 @@ void test01()
   a.push_back(L'1');
   b.assign(std::move(a));
   VERIFY( b.size() == 1 && b[0] == '1' && a.size() == 0 );
+
+  // True for std::allocator because is_always_equal, but not true in general:
+  static_assert(noexcept(a.assign(std::move(b))), "lwg 2063");
 }
 
 int main()

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]