diff --git a/libcxx/include/__string b/libcxx/__string copy from libcxx/include/__string copy to libcxx/__string --- a/libcxx/include/__string +++ b/libcxx/__string @@ -165,6 +165,8 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \ + _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias(value_type const*, size_type)) \ + _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias(value_type const*, size_type)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ @@ -179,7 +181,6 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ diff --git a/libcxx/include/__string b/libcxx/include/__string --- a/libcxx/include/__string +++ b/libcxx/include/__string @@ -165,6 +165,8 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \ + _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias(value_type const*, size_type)) \ + _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias(value_type const*, size_type)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \ @@ -179,7 +181,6 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ diff --git a/libcxx/include/string b/libcxx/include/string --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1571,6 +1571,12 @@ size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff); + // __assign_no_alias is invoked for assignment operations where we + // have proof that the input does not alias the current instance. + // For example, operator=(basic_string) performs a 'self' check. + template + void __assign_no_alias(const value_type* __s, size_type __n); + _LIBCPP_INLINE_VISIBILITY void __erase_to_end(size_type __pos); @@ -2202,6 +2208,23 @@ // assign +template +template +void basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias( + const value_type* __s, size_type __n) { + size_type __cap = __is_short ? __min_cap : __get_long_cap(); + if (__n < __cap) { + pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer(); + __is_short ? __set_short_size(__n) : __set_long_size(__n); + traits_type::copy(_VSTD::__to_address(__p), __s, __n); + traits_type::assign(__p[__n], value_type()); + __invalidate_iterators_past(__n); + } else { + size_type __sz = __is_short ? __get_short_size() : __get_long_size(); + __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); + } +} + template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) @@ -2268,16 +2291,19 @@ basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { - if (this != &__str) - { - __copy_assign_alloc(__str); - const bool __str_is_long = __str.__is_long(); // Force single branch - if (__is_long() || __str_is_long) { - return assign(__str.data(), __str.size()); - } + if (this != &__str) { + __copy_assign_alloc(__str); + if (!__is_long()) { + if (!__str.__is_long() /* !__str_is_long */) { __r_.first().__r = __str.__r_.first().__r; + } else { + __assign_no_alias(__str.data(), __str.size()); + } + } else { + __assign_no_alias(__str.data(), __str.size()); } - return *this; + } + return *this; } #ifndef _LIBCPP_CXX03_LANG diff --git a/libcxx/include/string b/libcxx/string copy from libcxx/include/string copy to libcxx/string --- a/libcxx/include/string +++ b/libcxx/string @@ -1571,6 +1571,12 @@ size_type __n_copy, size_type __n_del, size_type __n_add, const value_type* __p_new_stuff); + // __assign_no_alias is invoked for assignment operations where we + // have proof that the input does not alias the current instance. + // For example, operator=(basic_string) performs a 'self' check. + template + void __assign_no_alias(const value_type* __s, size_type __n); + _LIBCPP_INLINE_VISIBILITY void __erase_to_end(size_type __pos); @@ -2202,6 +2208,23 @@ // assign +template +template +void basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias( + const value_type* __s, size_type __n) { + size_type __cap = __is_short ? __min_cap : __get_long_cap(); + if (__n < __cap) { + pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer(); + __is_short ? __set_short_size(__n) : __set_long_size(__n); + traits_type::copy(_VSTD::__to_address(__p), __s, __n); + traits_type::assign(__p[__n], value_type()); + __invalidate_iterators_past(__n); + } else { + size_type __sz = __is_short ? __get_short_size() : __get_long_size(); + __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s); + } +} + template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) @@ -2268,16 +2291,19 @@ basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str) { - if (this != &__str) - { - __copy_assign_alloc(__str); - const bool __str_is_long = __str.__is_long(); // Force single branch - if (__is_long() || __str_is_long) { - return assign(__str.data(), __str.size()); - } + if (this != &__str) { + __copy_assign_alloc(__str); + if (!__is_long()) { + if (!__str.__is_long() /* !__str_is_long */) { __r_.first().__r = __str.__r_.first().__r; + } else { + __assign_no_alias(__str.data(), __str.size()); + } + } else { + __assign_no_alias(__str.data(), __str.size()); } - return *this; + } + return *this; } #ifndef _LIBCPP_CXX03_LANG