diff options
author | Nina Dinka Ranns <dinka.ranns@gmail.com> | 2019-05-14 11:48:31 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2019-05-14 12:48:31 +0100 |
commit | db33efde17932fb29fd08f19eaeef0e527adb065 (patch) | |
tree | a59cec6e2335b171d4581888c383f4deae8ac866 | |
parent | 4593483f15ca2a82049500b9434e736996bb0891 (diff) | |
download | gcc-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
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; } |