aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNina Dinka Ranns <dinka.ranns@gmail.com>2019-05-14 11:48:31 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-05-14 12:48:31 +0100
commitdb33efde17932fb29fd08f19eaeef0e527adb065 (patch)
treea59cec6e2335b171d4581888c383f4deae8ac866
parent4593483f15ca2a82049500b9434e736996bb0891 (diff)
downloadgcc-db33efde17932fb29fd08f19eaeef0e527adb065.zip
gcc-db33efde17932fb29fd08f19eaeef0e527adb065.tar.gz
gcc-db33efde17932fb29fd08f19eaeef0e527adb065.tar.bz2
Inconsistency wrt Allocators in basic_string assignment (LWG2579)
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
-rw-r--r--libstdc++-v3/ChangeLog11
-rw-r--r--libstdc++-v3/include/bits/basic_string.h58
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc37
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc36
4 files changed, 113 insertions, 29 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 3af9bf1..9a90e1b 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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)
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 5ebe86b..897acaa 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -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;
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
index 9e84262..fa9f2c7 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/copy_assign.cc
@@ -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;
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
index 292c971..e7e15a9 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc
@@ -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;
}