PR libstdc++/58265 implement LWG 2063 for COW strings
authorJonathan Wakely <jwakely@redhat.com>
Thu, 5 Jul 2018 15:56:06 +0000 (16:56 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 5 Jul 2018 15:56:06 +0000 (16:56 +0100)
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
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/include/bits/basic_string.tcc
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/move_assign.cc
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc
libstdc++-v3/testsuite/21_strings/basic_string/cons/char/noexcept_move_construct.cc
libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/noexcept_move_construct.cc

index 68cb17cd3d936e81df3854f94f4ea0e6f865fc5e..39b94917a2e722a9b40ba2f76f123e1cd0939289 100644 (file)
@@ -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
index a77074da249c4e7f80e924bda870f1f54890843e..baad58682b6df9f0270eae7b2a793f79e44bf649 100644 (file)
@@ -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:
       /**
index 04b68ca0202622577252e8691f7006938f4cc437..51bbb7bd6a0603d6ce529960674282648e0772d2 100644 (file)
@@ -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();
index 1142586a6eaab25648387fbfa3430758cb6a92c0..b07078029717be498f4fe6807f65eb17ef16521c 100644 (file)
@@ -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));
index 4276fd69ff176fc86923d7ebe9742512a1ea853b..df9be1925ba7bfb9b39bc80ba284426ca10233d8 100644 (file)
@@ -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));
index 5d62c95b13c665318ffb3a672837f28d7f897fb2..a068d5afe623583d8be9db157c328f3ac73ed9bf 100644 (file)
@@ -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");
index 60df8cfefa69bc1d7db069088ef70a31e3a56c9a..660ff7df57965cab10cfcdb26e62abaa2e3beabf 100644 (file)
@@ -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");