From: Nina Dinka Ranns Date: Tue, 7 May 2019 15:30:46 +0000 (+0000) Subject: Make allocator propagation more consistent for operator+(basic_string) (P1165R1) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f4e678ef74b2726f9c07be2b39712a9ea4eb7119;p=gcc.git Make allocator propagation more consistent for operator+(basic_string) (P1165R1) 2019-05-01 Nina Dinka Ranns Make allocator propagation more consistent for operator+(basic_string) (P1165R1) * include/bits/basic_string.h (operator+(basic_string&&, basic_string&&): Changed resulting allocator to always be the one from the first parameter. * include/bits/basic_string.tcc (operator+(const _CharT*, const basic_string&)): Changed resulting allocator to be SOCCC on the second parameter's allocator. (operator+(_CharT, const basic_string&)): Likewise. * testsuite/21_strings/basic_string/allocator/char/operator_plus.cc: New. * testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc: New. From-SVN: r270953 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5acf43eab33..47b8b42d2af 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2019-05-01 Nina Dinka Ranns + + Make allocator propagation more consistent for + operator+(basic_string) (P1165R1) + * include/bits/basic_string.h + (operator+(basic_string&&, basic_string&&): Changed resulting + allocator to always be the one from the first parameter. + * include/bits/basic_string.tcc + (operator+(const _CharT*, const basic_string&)): Changed + resulting allocator to be SOCCC on the second parameter's allocator. + (operator+(_CharT, const basic_string&)): Likewise. + * testsuite/21_strings/basic_string/allocator/char/operator_plus.cc: + New. + * testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc: + New. + 2019-05-07 Jonathan Wakely * include/bits/regex.h: Improve docs. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 4a6332a8968..5ebe86bad7d 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -6096,11 +6096,21 @@ _GLIBCXX_END_NAMESPACE_CXX11 operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { - const auto __size = __lhs.size() + __rhs.size(); - const bool __cond = (__size > __lhs.capacity() - && __size <= __rhs.capacity()); - return __cond ? std::move(__rhs.insert(0, __lhs)) - : std::move(__lhs.append(__rhs)); +#if _GLIBCXX_USE_CXX11_ABI + using _Alloc_traits = allocator_traits<_Alloc>; + bool __use_rhs = false; + if _GLIBCXX17_CONSTEXPR (typename _Alloc_traits::is_always_equal{}) + __use_rhs = true; + else if (__lhs.get_allocator() == __rhs.get_allocator()) + __use_rhs = true; + if (__use_rhs) +#endif + { + const auto __size = __lhs.size() + __rhs.size(); + if (__size > __lhs.capacity() && __size <= __rhs.capacity()) + return std::move(__rhs.insert(0, __lhs)); + } + return std::move(__lhs.append(__rhs)); } template diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 314b8fe207f..e2315cb1467 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -1161,8 +1161,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_string(__lhs); typedef basic_string<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; const __size_type __len = _Traits::length(__lhs); - __string_type __str; + __string_type __str(_Alloc_traits::_S_select_on_copy( + __rhs.get_allocator())); __str.reserve(__len + __rhs.size()); __str.append(__lhs, __len); __str.append(__rhs); @@ -1175,7 +1179,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef basic_string<_CharT, _Traits, _Alloc> __string_type; typedef typename __string_type::size_type __size_type; - __string_type __str; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; + __string_type __str(_Alloc_traits::_S_select_on_copy( + __rhs.get_allocator())); const __size_type __len = __rhs.size(); __str.reserve(__len + 1); __str.append(__size_type(1), __lhs); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc new file mode 100644 index 00000000000..c4693378d0b --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/char/operator_plus.cc @@ -0,0 +1,151 @@ +// 2019-04-30 Nina Dinka Ranns +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } +// COW strings don't support C++11 allocators: +// { dg-require-effective-target cxx11-abi } + +#include +#include +#include +#include + +using C = char; +using traits = std::char_traits; + +using __gnu_test::propagating_allocator; + +void test01() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1("something",alloc_type(1)); + test_type v2("something",alloc_type(2)); + auto r1 = v1 + v2; + VERIFY(r1.get_allocator().get_personality() == 1); + + auto r2 = v1 + std::move(v2); + VERIFY(r2.get_allocator().get_personality() == 2); + + test_type v3("something", alloc_type(3)); + test_type v4("something", alloc_type(4)); + auto r3 = std::move(v3) + v4; + VERIFY(r3.get_allocator().get_personality() == 3); + + auto r4 = std::move(v1) +std::move(v4); + VERIFY(r4.get_allocator().get_personality() == 1); + + test_type v5("something", alloc_type(5)); + auto r5 = v5 + "str"; + VERIFY(r5.get_allocator().get_personality() == 5); + + auto r6 = v5 + 'c'; + VERIFY(r6.get_allocator().get_personality() == 5); + + auto r7 = std::move(v5) + "str"; + VERIFY(r7.get_allocator().get_personality() == 5); + + test_type v6("something", alloc_type(6)); + auto r8 = std::move(v6) + 'c'; + VERIFY(r8.get_allocator().get_personality() == 6); + + test_type v7("something", alloc_type(7)); + auto r9 = "str" + v7; + VERIFY(r9.get_allocator().get_personality() == 7); + + auto r10 = 'c' + v7; + VERIFY(r10.get_allocator().get_personality() == 7); + + auto r11 = "str" + std::move(v7); + VERIFY(r11.get_allocator().get_personality() == 7); + + test_type v8("something", alloc_type(8)); + auto r12 = 'c' + std::move(v8); + VERIFY(r12.get_allocator().get_personality() == 8); +} +void test02() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1("something",alloc_type(1)); + test_type v2("something",alloc_type(2)); + auto r1 = v1 + v2; + VERIFY(r1.get_allocator().get_personality() != 1); + + auto r2 = v1 + std::move(v2); + VERIFY(r2.get_allocator().get_personality() == 2); + + test_type v3("something", alloc_type(3)); + test_type v4("something", alloc_type(4)); + auto r3 = std::move(v3) + v4; + VERIFY(r3.get_allocator().get_personality() == 3); + + auto r4 = std::move(v1) +std::move(v4); + VERIFY(r4.get_allocator().get_personality() == 1); + + test_type v5("something", alloc_type(5)); + auto r5 = v5 + "str"; + VERIFY(r5.get_allocator().get_personality() != 5); + + auto r6 = v5 + 'c'; + VERIFY(r6.get_allocator().get_personality() != 5); + + auto r7 = std::move(v5) + "str"; + VERIFY(r7.get_allocator().get_personality() == 5); + + test_type v6("something", alloc_type(6)); + auto r8 = std::move(v6) + 'c'; + VERIFY(r8.get_allocator().get_personality() == 6); + + test_type v7("something", alloc_type(7)); + auto r9 = "str" + v7; + VERIFY(r9.get_allocator().get_personality() != 7); + + auto r10 = 'c' + v7; + VERIFY(r10.get_allocator().get_personality() != 7); + + auto r11 = "str" + std::move(v7); + VERIFY(r11.get_allocator().get_personality() == 7); + + test_type v8("something", alloc_type(8)); + auto r12 = 'c' + std::move(v8); + VERIFY(r12.get_allocator().get_personality() == 8); +} +void test03() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1("s",alloc_type(1)); + v1.resize(10); + v1.shrink_to_fit(); + test_type v2(10000,'x',alloc_type(2)); + v2.reserve(10010); + + auto r=std::move(v1)+std::move(v2); + VERIFY(r.get_allocator().get_personality() == 1); +} +int main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc new file mode 100644 index 00000000000..3e1d0c3fbad --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/allocator/wchar_t/operator_plus.cc @@ -0,0 +1,152 @@ +// 2019-04-30 Nina Dinka Ranns +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } +// COW strings don't support C++11 allocators: +// { dg-require-effective-target cxx11-abi } + +#include +#include +#include +#include + +using C = wchar_t; +using traits = std::char_traits; + +using __gnu_test::propagating_allocator; + +void test01() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1(L"something",alloc_type(1)); + test_type v2(L"something",alloc_type(2)); + auto r1 = v1 + v2; + VERIFY(r1.get_allocator().get_personality() == 1); + + auto r2 = v1 + std::move(v2); + VERIFY(r2.get_allocator().get_personality() == 2); + + test_type v3(L"something", alloc_type(3)); + test_type v4(L"something", alloc_type(4)); + auto r3 = std::move(v3) + v4; + VERIFY(r3.get_allocator().get_personality() == 3); + + auto r4 = std::move(v1) +std::move(v4); + VERIFY(r4.get_allocator().get_personality() == 1); + + test_type v5(L"something", alloc_type(5)); + auto r5 = v5 + L"str"; + VERIFY(r5.get_allocator().get_personality() == 5); + + auto r6 = v5 + L'c'; + VERIFY(r6.get_allocator().get_personality() == 5); + + auto r7 = std::move(v5) + L"str"; + VERIFY(r7.get_allocator().get_personality() == 5); + + test_type v6(L"something", alloc_type(6)); + auto r8 = std::move(v6) + L'c'; + VERIFY(r8.get_allocator().get_personality() == 6); + + test_type v7(L"something", alloc_type(7)); + auto r9 = L"str" + v7; + VERIFY(r9.get_allocator().get_personality() == 7); + + auto r10 = L'c' + v7; + VERIFY(r10.get_allocator().get_personality() == 7); + + auto r11 = L"str" + std::move(v7); + VERIFY(r11.get_allocator().get_personality() == 7); + + test_type v8(L"something", alloc_type(8)); + auto r12 = L'c' + std::move(v8); + VERIFY(r12.get_allocator().get_personality() == 8); +} + +void test02() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1(L"something",alloc_type(1)); + test_type v2(L"something",alloc_type(2)); + auto r1 = v1 + v2; + VERIFY(r1.get_allocator().get_personality() != 1); + + auto r2 = v1 + std::move(v2); + VERIFY(r2.get_allocator().get_personality() == 2); + + test_type v3(L"something", alloc_type(3)); + test_type v4(L"something", alloc_type(4)); + auto r3 = std::move(v3) + v4; + VERIFY(r3.get_allocator().get_personality() == 3); + + auto r4 = std::move(v1) +std::move(v4); + VERIFY(r4.get_allocator().get_personality() == 1); + + test_type v5(L"something", alloc_type(5)); + auto r5 = v5 + L"str"; + VERIFY(r5.get_allocator().get_personality() != 5); + + auto r6 = v5 + L'c'; + VERIFY(r6.get_allocator().get_personality() != 5); + + auto r7 = std::move(v5) + L"str"; + VERIFY(r7.get_allocator().get_personality() == 5); + + test_type v6(L"something", alloc_type(6)); + auto r8 = std::move(v6) + L'c'; + VERIFY(r8.get_allocator().get_personality() == 6); + + test_type v7(L"something", alloc_type(7)); + auto r9 = L"str" + v7; + VERIFY(r9.get_allocator().get_personality() != 7); + + auto r10 = L'c' + v7; + VERIFY(r10.get_allocator().get_personality() != 7); + + auto r11 = L"str" + std::move(v7); + VERIFY(r11.get_allocator().get_personality() == 7); + + test_type v8(L"something", alloc_type(8)); + auto r12 = L'c' + std::move(v8); + VERIFY(r12.get_allocator().get_personality() == 8); +} +void test03() +{ + typedef propagating_allocator alloc_type; + typedef std::basic_string test_type; + + test_type v1(L"s",alloc_type(1)); + v1.resize(10); + v1.shrink_to_fit(); + test_type v2(10000,L'x',alloc_type(2)); + v2.reserve(10010); + + auto r=std::move(v1)+std::move(v2); + VERIFY(r.get_allocator().get_personality() == 1); +} +int main() +{ + test01(); + test02(); + test03(); + return 0; +}