aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits/basic_string.tcc
diff options
context:
space:
mode:
authorAndrew Luo <andrewluotechnologies@outlook.com>2020-08-06 19:35:43 +0100
committerJonathan Wakely <jwakely@redhat.com>2020-08-06 19:49:07 +0100
commit140cf935cd118f7208b7c3826a8b9d50936242f0 (patch)
tree65f67d2de44231a18d83ebdb1fffa3eff6602d86 /libstdc++-v3/include/bits/basic_string.tcc
parent4e39f563c0cd25401f689c2093cb8c13692156ef (diff)
libstdc++: Implement P0966 std::string::reserve should not shrink
Remove ability for reserve(n) to reduce a string's capacity. Add a new reserve() overload that makes a shrink-to-fit request, and make shrink_to_fit() use that. libstdc++-v3/ChangeLog: 2020-07-30 Andrew Luo <andrewluotechnologies@outlook.com> Jonathan Wakely <jwakely@redhat.com> * config/abi/pre/gnu.ver (GLIBCXX_3.4): Use less greedy patterns for basic_string members. (GLIBCXX_3.4.29): Export new basic_string::reserve symbols. * doc/xml/manual/status_cxx2020.xml: Update P0966 status. * include/bits/basic_string.h (shrink_to_fit()): Call reserve(). (reserve(size_type)): Remove default argument. (reserve()): Declare new overload. [!_GLIBCXX_USE_CXX11_ABI] (shrink_to_fit, reserve): Likewise. * include/bits/basic_string.tcc (reserve(size_type)): Remove support for shrinking capacity. (reserve()): Perform shrink-to-fit operation. [!_GLIBCXX_USE_CXX11_ABI] (reserve): Likewise. * testsuite/21_strings/basic_string/capacity/1.cc: Adjust to reflect new behavior. * testsuite/21_strings/basic_string/capacity/char/1.cc: Likewise. * testsuite/21_strings/basic_string/capacity/char/18654.cc: Likewise. * testsuite/21_strings/basic_string/capacity/char/2.cc: Likewise. * testsuite/21_strings/basic_string/capacity/wchar_t/1.cc: Likewise. * testsuite/21_strings/basic_string/capacity/wchar_t/18654.cc: Likewise. * testsuite/21_strings/basic_string/capacity/wchar_t/2.cc: Likewise.
Diffstat (limited to 'libstdc++-v3/include/bits/basic_string.tcc')
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc119
1 files changed, 86 insertions, 33 deletions
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 75218a40610..a64b63a37fb 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -280,29 +280,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
reserve(size_type __res)
{
- // Make sure we don't shrink below the current size.
- if (__res < length())
- __res = length();
-
const size_type __capacity = capacity();
- if (__res != __capacity)
- {
- if (__res > __capacity
- || __res > size_type(_S_local_capacity))
- {
- pointer __tmp = _M_create(__res, __capacity);
- this->_S_copy(__tmp, _M_data(), length() + 1);
- _M_dispose();
- _M_data(__tmp);
- _M_capacity(__res);
- }
- else if (!_M_is_local())
- {
- this->_S_copy(_M_local_data(), _M_data(), length() + 1);
- _M_destroy(__capacity);
- _M_data(_M_local_data());
- }
- }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2968. Inconsistencies between basic_string reserve and
+ // vector/unordered_map/unordered_set reserve functions
+ // P0966 reserve should not shrink
+ if (__res <= __capacity)
+ return;
+
+ pointer __tmp = _M_create(__res, __capacity);
+ this->_S_copy(__tmp, _M_data(), length() + 1);
+ _M_dispose();
+ _M_data(__tmp);
+ _M_capacity(__res);
}
template<typename _CharT, typename _Traits, typename _Alloc>
@@ -345,6 +335,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, typename _Traits, typename _Alloc>
void
basic_string<_CharT, _Traits, _Alloc>::
+ reserve()
+ {
+ if (_M_is_local())
+ return;
+
+ const size_type __length = length();
+ const size_type __capacity = _M_allocated_capacity;
+
+ if (__length <= size_type(_S_local_capacity))
+ {
+ this->_S_copy(_M_local_data(), _M_data(), __length + 1);
+ _M_destroy(__capacity);
+ _M_data(_M_local_data());
+ }
+#if __cpp_exceptions
+ else if (__length < __capacity)
+ try
+ {
+ pointer __tmp
+ = _Alloc_traits::allocate(_M_get_allocator(), __length + 1);
+ this->_S_copy(__tmp, _M_data(), __length + 1);
+ _M_dispose();
+ _M_data(__tmp);
+ _M_capacity(__length);
+ }
+ catch (const __cxxabiv1::__forced_unwind&)
+ { throw; }
+ catch (...)
+ { /* swallow the exception */ }
+#endif
+ }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ basic_string<_CharT, _Traits, _Alloc>::
resize(size_type __n, _CharT __c)
{
const size_type __size = this->size();
@@ -953,16 +978,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
reserve(size_type __res)
{
- if (__res != this->capacity() || _M_rep()->_M_is_shared())
- {
- // Make sure we don't shrink below the current size
- if (__res < this->size())
- __res = this->size();
- const allocator_type __a = get_allocator();
- _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
- _M_rep()->_M_dispose(__a);
- _M_data(__tmp);
- }
+ const size_type __capacity = capacity();
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2968. Inconsistencies between basic_string reserve and
+ // vector/unordered_map/unordered_set reserve functions
+ // P0966 reserve should not shrink
+ if (__res <= __capacity)
+ {
+ if (!_M_rep()->_M_is_shared())
+ return;
+
+ // unshare, but keep same capacity
+ __res = __capacity;
+ }
+
+ const allocator_type __a = get_allocator();
+ _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
+ _M_rep()->_M_dispose(__a);
+ _M_data(__tmp);
}
template<typename _CharT, typename _Traits, typename _Alloc>
@@ -1006,7 +1040,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// The standard places no restriction on allocating more memory
// than is strictly needed within this layer at the moment or as
- // requested by an explicit application call to reserve().
+ // requested by an explicit application call to reserve(n).
// Many malloc implementations perform quite poorly when an
// application attempts to allocate memory in a stepwise fashion
@@ -1140,6 +1174,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ void
+ basic_string<_CharT, _Traits, _Alloc>::
+ reserve()
+ {
+ if (length() < capacity() || _M_rep()->_M_is_shared())
+ try
+ {
+ const allocator_type __a = get_allocator();
+ _CharT* __tmp = _M_rep()->_M_clone(__a);
+ _M_rep()->_M_dispose(__a);
+ _M_data(__tmp);
+ }
+ catch (const __cxxabiv1::__forced_unwind&)
+ { throw; }
+ catch (...)
+ { /* swallow the exception */ }
+ }
+
template<typename _CharT, typename _Traits, typename _Alloc>
typename basic_string<_CharT, _Traits, _Alloc>::size_type
basic_string<_CharT, _Traits, _Alloc>::