diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-07-05 16:56:06 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-07-05 16:56:06 +0100 |
commit | d8d9b83b33dd13d81a1e107ce4d1e075a30e6f21 (patch) | |
tree | 0a88c59686cedaf90660aa6b1ff706abecd71692 | |
parent | 245471c67f3ad27a85dce999933cec1ff298be02 (diff) | |
download | gcc-d8d9b83b33dd13d81a1e107ce4d1e075a30e6f21.zip gcc-d8d9b83b33dd13d81a1e107ce4d1e075a30e6f21.tar.gz gcc-d8d9b83b33dd13d81a1e107ce4d1e075a30e6f21.tar.bz2 |
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
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 <jwakely@redhat.com> + + 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 <jwakely@redhat.com> 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<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 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<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 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<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 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<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"); |