[PATCH] PR libstdc++/58265 implement LWG 2063 for COW strings
Jonathan Wakely
jwakely@redhat.com
Thu Jul 5 15:56:00 GMT 2018
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.
Tested powerpc64le-linux, committed to trunk.
-------------- next part --------------
commit 926b3b642595383cb4abfbeb3586eecc721c1935
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Thu Jul 5 15:12:06 2018 +0100
PR libstdc++/58265 implement LWG 2063 for COW strings
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.
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index a77074da249..baad58682b6 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -3486,6 +3486,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
*/
basic_string()
#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
+ _GLIBCXX_NOEXCEPT
: _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
#else
: _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()){ }
@@ -3642,7 +3643,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
* @param __str Source string.
*/
basic_string&
- operator=(const basic_string& __str)
+ operator=(const basic_string& __str)
{ return this->assign(__str); }
/**
@@ -3675,9 +3676,9 @@ _GLIBCXX_END_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.
basic_string&
operator=(basic_string&& __str)
+ _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)
{
// NB: DR 1204.
this->swap(__str);
@@ -5111,9 +5112,9 @@ _GLIBCXX_END_NAMESPACE_CXX11
* Exchanges the contents of this string with that of @a __s in constant
* time.
*/
- // PR 58265, this should be noexcept.
void
- swap(basic_string& __s);
+ swap(basic_string& __s)
+ _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value);
// String operations:
/**
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 04b68ca0202..51bbb7bd6a0 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -967,6 +967,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
basic_string<_CharT, _Traits, _Alloc>::
swap(basic_string& __s)
+ _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)
{
if (_M_rep()->_M_is_leaked())
_M_rep()->_M_set_sharable();
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc
index 1142586a6ea..b0707802971 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc
@@ -34,6 +34,9 @@ void test01()
typedef propagating_allocator<C, false> alloc_type;
typedef std::basic_string<C, traits, alloc_type> test_type;
+ static_assert(std::is_move_assignable<test_type>::value, "");
+ static_assert(!std::is_nothrow_move_assignable<test_type>::value, "");
+
test_type v1(alloc_type(1));
v1.assign(1, c);
test_type v2(alloc_type(2));
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc
index 4276fd69ff1..df9be1925ba 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc
@@ -34,6 +34,9 @@ void test01()
typedef propagating_allocator<C, false> alloc_type;
typedef std::basic_string<C, traits, alloc_type> test_type;
+ static_assert(std::is_move_assignable<test_type>::value, "");
+ static_assert(!std::is_nothrow_move_assignable<test_type>::value, "");
+
test_type v1(alloc_type(1));
v1.assign(1, c);
test_type v2(alloc_type(2));
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc
index 5d62c95b13c..a068d5afe62 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc
@@ -23,4 +23,8 @@
typedef std::string stype;
+// True except for COW strings with _GLIBCXX_FULLY_DYNAMIC_STRING:
static_assert(std::is_nothrow_move_constructible<stype>::value, "Error");
+
+// True for std::allocator because is_always_equal, but not true in general:
+static_assert(std::is_nothrow_move_assignable<stype>::value, "lwg 2063");
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/noexcept_move_construct.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/noexcept_move_construct.cc
index 60df8cfefa6..660ff7df579 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/noexcept_move_construct.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/noexcept_move_construct.cc
@@ -23,4 +23,8 @@
typedef std::wstring wstype;
+// True except for COW strings with _GLIBCXX_FULLY_DYNAMIC_STRING:
static_assert(std::is_nothrow_move_constructible<wstype>::value, "Error");
+
+// True for std::allocator because is_always_equal, but not true in general:
+static_assert(std::is_nothrow_move_assignable<wstype>::value, "lwg 2063");
More information about the Libstdc++
mailing list