Index: include/string =================================================================== --- include/string +++ include/string @@ -1407,6 +1407,18 @@ __alloc_traits::propagate_on_container_copy_assignment::value>());} _LIBCPP_INLINE_VISIBILITY + void __clear_and_shrink() + { + clear(); + if(__is_long()) + { + __alloc_traits::deallocate(__alloc(), __get_long_pointer(), capacity() + 1); + __set_long_cap(0); + __set_short_size(0); + } + } + + _LIBCPP_INLINE_VISIBILITY void __copy_assign_alloc(const basic_string& __str, true_type) { if (__alloc() == __str.__alloc()) @@ -1415,16 +1427,14 @@ { 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()); @@ -2102,8 +2112,7 @@ _NOEXCEPT_(is_nothrow_move_assignable::value) #endif { - clear(); - shrink_to_fit(); + __clear_and_shrink(); __r_.first() = __str.__r_.first(); __move_assign_alloc(__str); __str.__zero(); Index: test/libcxx/strings/basic.string/string.modifiers/copy_assign_move_assign_db1.pass.cpp =================================================================== --- test/libcxx/strings/basic.string/string.modifiers/copy_assign_move_assign_db1.pass.cpp +++ test/libcxx/strings/basic.string/string.modifiers/copy_assign_move_assign_db1.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// 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 +#include + +int main() +{ + std::string l = "Long string so that allocation definitely, for sure, absolutely happens. Probably."; + std::string l2 = l; + std::string s = "short"; + std::string s2 = s; + std::string empty = ""; + + assert(l.__invariants()); + assert(s.__invariants()); + assert(l2.__invariants()); + assert(s2.__invariants()); + assert(empty.__invariants()); + + + s2 = empty; + assert(s2.__invariants()); + assert(s2.size() == 0); + assert(empty.__invariants()); + s2 = empty; + assert(s2.__invariants()); + assert(s2.size() == 0); + assert(empty.__invariants()); + + { + std::string::size_type cap = l.capacity(); + l = empty; + assert(l.__invariants()); + assert(l.size() == 0); + assert(empty.__invariants()); + cap = l2.capacity(); + l2 = std::move(empty); + assert(l2.capacity() < cap); + assert(l2.__invariants()); + assert(l2.size() == 0); + assert(empty.__invariants()); + } +} + +#else + +int main() +{ +} + +#endif