diff options
-rw-r--r-- | libcxx/include/string | 27 | ||||
-rw-r--r-- | libcxx/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp | 48 |
2 files changed, 69 insertions, 6 deletions
diff --git a/libcxx/include/string b/libcxx/include/string index e8ec709c25a..2630799c060 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1257,6 +1257,8 @@ public: _LIBCPP_INLINE_VISIBILITY bool __invariants() const; + _LIBCPP_INLINE_VISIBILITY void __clear_and_shrink(); + _LIBCPP_INLINE_VISIBILITY bool __is_long() const _NOEXCEPT {return bool(__r_.first().__s.__size_ & __short_mask);} @@ -1426,16 +1428,14 @@ private: { if (!__str.__is_long()) { - clear(); - shrink_to_fit(); + __clear_and_shrink(); __alloc() = __str.__alloc(); } else { allocator_type __a = __str.__alloc(); pointer __p = __alloc_traits::allocate(__a, __str.__get_long_cap()); - clear(); - shrink_to_fit(); + __clear_and_shrink(); __alloc() = _VSTD::move(__a); __set_long_pointer(__p); __set_long_cap(__str.__get_long_cap()); @@ -2125,8 +2125,7 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) #endif { - clear(); - shrink_to_fit(); + __clear_and_shrink(); __r_.first() = __str.__r_.first(); __move_assign_alloc(__str); __str.__zero(); @@ -3579,6 +3578,22 @@ basic_string<_CharT, _Traits, _Allocator>::__invariants() const return true; } +// __clear_and_shrink + +template<class _CharT, class _Traits, class _Allocator> +inline _LIBCPP_INLINE_VISIBILITY +void +basic_string<_CharT, _Traits, _Allocator>::__clear_and_shrink() +{ + clear(); + if(__is_long()) + { + __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); + __set_long_cap(0); + __set_short_size(0); + } +} + // operator== template<class _CharT, class _Traits, class _Allocator> diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp new file mode 100644 index 00000000000..b7e278b7591 --- /dev/null +++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <string> + +// Call __clear_and_shrink() and ensure string invariants hold + +#if _LIBCPP_DEBUG >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include <string> +#include <cassert> + +int main() +{ + std::string l = "Long string so that allocation definitely, for sure, absolutely happens. Probably."; + std::string s = "short"; + + assert(l.__invariants()); + assert(s.__invariants()); + + s.__clear_and_shrink(); + assert(s.__invariants()); + assert(s.size() == 0); + + { + std::string::size_type cap = l.capacity(); + l.__clear_and_shrink(); + assert(l.__invariants()); + assert(l.size() == 0); + assert(l.capacity() < cap); + } +} + +#else + +int main() +{ +} + +#endif |