summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/string27
-rw-r--r--libcxx/test/libcxx/strings/basic.string/string.modifiers/clear_and_shrink_db1.pass.cpp48
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
OpenPOWER on IntegriCloud