From db33efde17932fb29fd08f19eaeef0e527adb065 Mon Sep 17 00:00:00 2001 From: Nina Dinka Ranns Date: Tue, 14 May 2019 11:48:31 +0000 Subject: [PATCH] Inconsistency wrt Allocators in basic_string assignment (LWG2579) 2019-05-14 Nina Dinka Ranns 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 | 11 ++++ libstdc++-v3/include/bits/basic_string.h | 58 +++++++++---------- .../allocator/char/copy_assign.cc | 37 ++++++++++++ .../allocator/wchar_t/copy_assign.cc | 36 ++++++++++++ 4 files changed, 113 insertions(+), 29 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3af9bf155a0..9a90e1b8bfc 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,14 @@ +2019-05-14 Nina Dinka Ranns + + 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 * 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 5ebe86bad7d..897acaa8c02 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 9e8426292a1..fa9f2c75918 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 alloc_type; + + typedef std::basic_string 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 alloc_type; + + typedef std::basic_string 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 292c9718929..e7e15a97acd 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 alloc_type; + + typedef std::basic_string 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 alloc_type; + + typedef std::basic_string 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; } -- 2.30.2