From d8d9b83b33dd13d81a1e107ce4d1e075a30e6f21 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 5 Jul 2018 16:56:06 +0100 Subject: [PATCH] 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. From-SVN: r262443 --- libstdc++-v3/ChangeLog | 20 ++++++++++++++++++++ libstdc++-v3/include/bits/basic_string.h | 9 +++++---- libstdc++-v3/include/bits/basic_string.tcc | 1 + .../basic_string/allocator/char/move_assign.cc | 3 +++ .../basic_string/allocator/wchar_t/move_assign.cc | 3 +++ .../cons/char/noexcept_move_construct.cc | 4 ++++ .../cons/wchar_t/noexcept_move_construct.cc | 4 ++++ 7 files changed, 40 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 68cb17c..39b9491 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,23 @@ +2018-07-05 Jonathan Wakely + + 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. + 2018-07-04 Jonathan Wakely P0646R1 Improving the Return Value of Erase-Like Algorithms I diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index a77074d..baad586 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 04b68ca..51bbb7b 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 1142586..b070780 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 alloc_type; typedef std::basic_string test_type; + static_assert(std::is_move_assignable::value, ""); + static_assert(!std::is_nothrow_move_assignable::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 4276fd6..df9be19 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 alloc_type; typedef std::basic_string test_type; + static_assert(std::is_move_assignable::value, ""); + static_assert(!std::is_nothrow_move_assignable::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 5d62c95..a068d5a 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::value, "Error"); + +// True for std::allocator because is_always_equal, but not true in general: +static_assert(std::is_nothrow_move_assignable::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 60df8cf..660ff7d 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::value, "Error"); + +// True for std::allocator because is_always_equal, but not true in general: +static_assert(std::is_nothrow_move_assignable::value, "lwg 2063"); -- 2.7.4