Inconsistency wrt Allocators in basic_string assignment (LWG2579)
authorNina Dinka Ranns <dinka.ranns@gmail.com>
Tue, 14 May 2019 11:48:31 +0000 (11:48 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 14 May 2019 11:48:31 +0000 (12:48 +0100)
2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>

Inconsistency wrt Allocators in basic_string assignment (LWG2579)
* include/bits/basic_string.h: (operator=(const basic_string&):
Move allocator decision to assign.
(assign(const basic_string&)): Move allocator decision here.
* testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
Add tests.
* testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
Add tests.

From-SVN: r271165

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc

index 3af9bf155a0678d461306727a6d703e9b4559d9b..9a90e1b8bfcd5e34dc9f299a94536e5da43a80d7 100644 (file)
@@ -1,3 +1,14 @@
+2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+
+       Inconsistency wrt Allocators in basic_string assignment (LWG2579)
+       * include/bits/basic_string.h: (operator=(const basic_string&):
+       Move allocator decision to assign.
+       (assign(const basic_string&)): Move allocator decision here.
+       * testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
+       Add tests.
+       * testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
+       Add tests.
+
 2019-05-14  Jonathan Wakely  <jwakely@redhat.com>
 
        * testsuite/util/testsuite_allocator.h (memory_resource)
index 5ebe86bad7dcfc5d9a05f3145873facef123d6f9..897acaa8c022bb5d231726b60ca9cb7095c78b2b 100644 (file)
@@ -664,35 +664,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       basic_string&
       operator=(const basic_string& __str)
       {
-#if __cplusplus >= 201103L
-       if (_Alloc_traits::_S_propagate_on_copy_assign())
-         {
-           if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
-               && _M_get_allocator() != __str._M_get_allocator())
-             {
-               // Propagating allocator cannot free existing storage so must
-               // deallocate it before replacing current allocator.
-               if (__str.size() <= _S_local_capacity)
-                 {
-                   _M_destroy(_M_allocated_capacity);
-                   _M_data(_M_local_data());
-                   _M_set_length(0);
-                 }
-               else
-                 {
-                   const auto __len = __str.size();
-                   auto __alloc = __str._M_get_allocator();
-                   // If this allocation throws there are no effects:
-                   auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
-                   _M_destroy(_M_allocated_capacity);
-                   _M_data(__ptr);
-                   _M_capacity(__len);
-                   _M_set_length(__len);
-                 }
-             }
-           std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
-         }
-#endif
        return this->assign(__str);
       }
 
@@ -1363,6 +1334,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
       basic_string&
       assign(const basic_string& __str)
       {
+#if __cplusplus >= 201103L
+       if (_Alloc_traits::_S_propagate_on_copy_assign())
+         {
+           if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
+               && _M_get_allocator() != __str._M_get_allocator())
+             {
+               // Propagating allocator cannot free existing storage so must
+               // deallocate it before replacing current allocator.
+               if (__str.size() <= _S_local_capacity)
+                 {
+                   _M_destroy(_M_allocated_capacity);
+                   _M_data(_M_local_data());
+                   _M_set_length(0);
+                 }
+               else
+                 {
+                   const auto __len = __str.size();
+                   auto __alloc = __str._M_get_allocator();
+                   // If this allocation throws there are no effects:
+                   auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
+                   _M_destroy(_M_allocated_capacity);
+                   _M_data(__ptr);
+                   _M_capacity(__len);
+                   _M_set_length(__len);
+                 }
+             }
+           std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
+         }
+#endif
        this->_M_assign(__str);
        return *this;
       }
index 9e8426292a1cc8e2ab2dbaac799816a8ad9e181e..fa9f2c75918145a6a6678dd5bcff5542729d0545 100644 (file)
@@ -133,10 +133,47 @@ void test03()
   VERIFY( v1.get_allocator() == a2 );
 }
 
+void test04()
+{
+  // LWG2579
+  typedef propagating_allocator<C, true> alloc_type;
+
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1("tralalala",alloc_type(1));
+  test_type v2("content", alloc_type(2));
+  test_type v3("content2", alloc_type(3));
+
+  v1.assign(v2);
+  v3 = v2;
+  VERIFY(2 == v1.get_allocator().get_personality());
+  VERIFY(2 == v3.get_allocator().get_personality());
+
+}
+
+void test05()
+{
+  // LWG2579
+  typedef propagating_allocator<C, false> alloc_type;
+
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1("tralalala",alloc_type(1));
+  test_type v2("content", alloc_type(2));
+  test_type v3("content2", alloc_type(3));
+
+  v1.assign(v2);
+  v3 = v2;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(3 == v3.get_allocator().get_personality());
+}
+
 int main()
 {
   test01();
   test02();
   test03();
+  test04();
+  test05();
   return 0;
 }
index 292c97189294eff5fa20a80e4a1e0460fe6a377f..e7e15a97acd0326614a2694067476ecd48d0675c 100644 (file)
@@ -133,10 +133,46 @@ void test03()
   VERIFY( v1.get_allocator() == a2 );
 }
 
+void test04()
+{
+  // LWG2579
+  typedef propagating_allocator<C, true> alloc_type;
+
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(L"tralalala",alloc_type(1));
+  test_type v2(L"content", alloc_type(2));
+  test_type v3(L"content2", alloc_type(3));
+
+  v1.assign(v2);
+  v3 = v2;
+  VERIFY(2 == v1.get_allocator().get_personality());
+  VERIFY(2 == v3.get_allocator().get_personality());
+
+}
+
+void test05()
+{
+  // LWG2579
+  typedef propagating_allocator<C, false> alloc_type;
+
+  typedef std::basic_string<C, traits, alloc_type> test_type;
+
+  test_type v1(L"tralalala",alloc_type(1));
+  test_type v2(L"content", alloc_type(2));
+  test_type v3(L"content2", alloc_type(3));
+
+  v1.assign(v2);
+  v3 = v2;
+  VERIFY(1 == v1.get_allocator().get_personality());
+  VERIFY(3 == v3.get_allocator().get_personality());
+}
 int main()
 {
   test01();
   test02();
   test03();
+  test04();
+  test05();
   return 0;
 }