Skip to content

[libcxx] Allow string to use SSO in constant evaluation. #66576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 10, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 15 additions & 39 deletions libcxx/include/string
Original file line number Diff line number Diff line change
Expand Up @@ -830,8 +830,8 @@ private:
{
union
{
__long __l;
__short __s;
__long __l;
__raw __r;
};
};
Expand Down Expand Up @@ -1729,8 +1729,10 @@ private:

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
bool __is_long() const _NOEXCEPT {
if (__libcpp_is_constant_evaluated())
return true;
if (__libcpp_is_constant_evaluated()) {
if (__builtin_constant_p(__r_.first().__l.__is_long_))
return __r_.first().__l.__is_long_;
}
return __r_.first().__s.__is_long_;
}

Expand All @@ -1748,24 +1750,11 @@ private:

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __default_init() {
__r_.first() = __rep();
if (__libcpp_is_constant_evaluated()) {
size_type __sz = __recommend(0) + 1;
pointer __ptr = __alloc_traits::allocate(__alloc(), __sz);
__begin_lifetime(__ptr, __sz);
__set_long_pointer(__ptr);
__set_long_cap(__sz);
__set_long_size(0);
}
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __deallocate_constexpr() {
if (__libcpp_is_constant_evaluated() && __get_pointer() != nullptr)
__alloc_traits::deallocate(__alloc(), __get_pointer(), __get_long_cap());
}

_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI static bool __fits_in_sso(size_type __sz) {
// SSO is disabled during constant evaluation because `__is_long` isn't constexpr friendly
return !__libcpp_is_constant_evaluated() && (__sz < __min_cap);
return (__sz < __min_cap);
}

template <class _Iterator, class _Sentinel>
Expand Down Expand Up @@ -1877,10 +1866,7 @@ private:
size_type __recommend(size_type __s) _NOEXCEPT
{
if (__s < __min_cap) {
if (__libcpp_is_constant_evaluated())
return static_cast<size_type>(__min_cap);
else
return static_cast<size_type>(__min_cap) - 1;
return static_cast<size_type>(__min_cap) - 1;
}
size_type __guess = __align_it<sizeof(value_type) < __alignment ?
__alignment/sizeof(value_type) : 1 > (__s+1) - 1;
Expand Down Expand Up @@ -1969,7 +1955,8 @@ private:
allocator_type __a = __str.__alloc();
auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
__begin_lifetime(__allocation.ptr, __allocation.count);
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
if (__is_long())
__alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap());
__alloc() = std::move(__a);
__set_long_pointer(__allocation.ptr);
__set_long_cap(__allocation.count);
Expand Down Expand Up @@ -2020,7 +2007,7 @@ private:
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_external(const value_type* __s, size_type __n);

// Assigns the value in __s, guaranteed to be __n < __min_cap in length.
inline basic_string& __assign_short(const value_type* __s, size_type __n) {
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& __assign_short(const value_type* __s, size_type __n) {
pointer __p = __is_long()
? (__set_long_size(__n), __get_long_pointer())
: (__set_short_size(__n), __get_short_pointer());
Expand Down Expand Up @@ -2334,7 +2321,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_and_replace
if (__sec_cp_sz != 0)
traits_type::copy(std::__to_address(__p) + __n_copy + __n_add,
std::__to_address(__old_p) + __n_copy + __n_del, __sec_cp_sz);
if (__old_cap+1 != __min_cap || __libcpp_is_constant_evaluated())
if (__old_cap+1 != __min_cap)
__alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
__set_long_pointer(__p);
__set_long_cap(__allocation.count);
Expand Down Expand Up @@ -2374,7 +2361,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t
traits_type::copy(std::__to_address(__p) + __n_copy + __n_add,
std::__to_address(__old_p) + __n_copy + __n_del,
__sec_cp_sz);
if (__libcpp_is_constant_evaluated() || __old_cap + 1 != __min_cap)
if (__old_cap + 1 != __min_cap)
__alloc_traits::deallocate(__alloc(), __old_p, __old_cap + 1);
__set_long_pointer(__p);
__set_long_cap(__allocation.count);
Expand Down Expand Up @@ -2537,12 +2524,8 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr
}
__move_assign_alloc(__str);
__r_.first() = __str.__r_.first();
if (__libcpp_is_constant_evaluated()) {
__str.__default_init();
} else {
__str.__set_short_size(0);
traits_type::assign(__str.__get_short_pointer()[0], value_type());
}
__str.__set_short_size(0);
traits_type::assign(__str.__get_short_pointer()[0], value_type());
}

#endif
Expand Down Expand Up @@ -2828,13 +2811,6 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_t
if (__pos > __sz)
__throw_out_of_range();
size_type __cap = capacity();
if (__libcpp_is_constant_evaluated()) {
if (__cap - __sz >= __n)
__grow_by_and_replace(__cap, 0, __sz, __pos, 0, __n, __s);
else
__grow_by_and_replace(__cap, __sz + __n - __cap, __sz, __pos, 0, __n, __s);
return *this;
}
if (__cap - __sz >= __n)
{
if (__n)
Expand All @@ -2843,7 +2819,7 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_t
size_type __n_move = __sz - __pos;
if (__n_move != 0)
{
if (__p + __pos <= __s && __s < __p + __sz)
if (std::__is_pointer_in_range(__p + __pos, __p + __sz, __s))
__s += __n;
traits_type::move(__p + __pos + __n, __p + __pos, __n_move);
}
Expand Down