On Thu, Mar 5, 2026 at 3:48 PM Tomasz Kamiński <[email protected]> wrote:
> This patch eliminate the use of __builtin_alloca for non-localized > formatting > of integers and pointers. > > For integers, the transcoding to _CharT moved from _M_format_int function > to format. This makes the maximum size of the buffer known (__buf_size) > that depends on sizeof(_Int) and allows use local array of _CharT (__wbuf) > for the storage. The _M_format_int is modified to accept the string of > _CharT. > > For pointers, format specifiers are subset of one allowed from the > integers, > so we simply delegate to __formatter_int::format, instead of repeated > formatting. > (_Pres_p and _Pres_P was modified by r16-7844-gbfc2b87f8244a1 to have same > value > as _Pres_x and _Pres_X). The set of allowed specifier is still limited per > C++ > standard by __formatter_ptr::parse. > > We also fix issue in __formatter_ptr::parse, where for 'p' and 'P' the > value > of _M_alt was negated for _M_spec (result of previous parse) instead of > __spec > (result of current parse), and adjust the __formatter_ptr default > constructor > to set _M_spec._M_type and _M_spec._M_alt appropriately. > > libstdc++-v3/ChangeLog: > > * include/std/format (__formatter_int::format): Handle transcoding > to _CharT before calling _M_format_int. > (__formatter_int::_M_format_int): Accept basic_string_view<_CharT> > and remove transcoding. > (__formatter_ptr::__formatter_ptr): Configure _M_spec member. > (__formatter_ptr::parse): Negate _M_alt for __spec and not _M_spec. > (__formatter_ptr::format): Delegate to __formatter_int. > > Signed-off-by: Tomasz Kamiński <[email protected]> > --- > This could be done for GCC-17, but I think we should at least merge > chagnes for __formatter_ptr cosntructor and parse for GCC16, so the __spec > value is configured in way compatible with __formatter_int. > > Testing on x86_64-linux. OK for trunk when test passes? > All test passed. > > libstdc++-v3/include/std/format | 102 +++++++++----------------------- > 1 file changed, 29 insertions(+), 73 deletions(-) > > diff --git a/libstdc++-v3/include/std/format > b/libstdc++-v3/include/std/format > index ec3d0018efd..9ee9bb4c9e2 100644 > --- a/libstdc++-v3/include/std/format > +++ b/libstdc++-v3/include/std/format > @@ -1647,7 +1647,8 @@ namespace __format > if (_M_spec._M_type == _Pres_c) > return _M_format_character(_S_to_character(__i), __fc); > > - char __buf[sizeof(_Int) * __CHAR_BIT__ + 3]; > + constexpr size_t __buf_size = sizeof(_Int) * __CHAR_BIT__ + 3; > + char __buf[__buf_size]; > to_chars_result __res{}; > > string_view __base_prefix; > @@ -1707,8 +1708,21 @@ namespace __format > } > __start = __format::__put_sign(__i, _M_spec._M_sign, __start - > 1); > > - return _M_format_int(string_view(__start, __res.ptr - __start), > - __start_digits - __start, __fc); > + > + string_view __narrow_str(__start, __res.ptr - __start); > + size_t __prefix_len = __start_digits - __start; > + if constexpr (is_same_v<char, _CharT>) > + return _M_format_int(__narrow_str, __prefix_len, __fc); > +#ifdef _GLIBCXX_USE_WCHAR_T > + else > + { > + _CharT __wbuf[__buf_size]; > + size_t __n = __narrow_str.size(); > + std::__to_wstring_numeric(__narrow_str.data(), __n, __wbuf); > + return _M_format_int(basic_string_view<_CharT>(__wbuf, __n), > + __prefix_len, __fc); > + } > +#endif > } > > template<typename _Out> > @@ -1795,24 +1809,10 @@ namespace __format > > template<typename _Out> > typename basic_format_context<_Out, _CharT>::iterator > - _M_format_int(string_view __narrow_str, size_t __prefix_len, > + _M_format_int(basic_string_view<_CharT> __str, size_t __prefix_len, > basic_format_context<_Out, _CharT>& __fc) const > { > size_t __width = _M_spec._M_get_width(__fc); > - > - basic_string_view<_CharT> __str; > - if constexpr (is_same_v<char, _CharT>) > - __str = __narrow_str; > -#ifdef _GLIBCXX_USE_WCHAR_T > - else > - { > - size_t __n = __narrow_str.size(); > - auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT)); > - std::__to_wstring_numeric(__narrow_str.data(), __n, __p); > - __str = {__p, __n}; > - } > -#endif > - > if (_M_spec._M_localized) > { > const auto& __l = __fc.locale(); > @@ -2433,7 +2433,13 @@ namespace __format > template<__format::__char _CharT> > struct __formatter_ptr > { > - __formatter_ptr() = default; > + constexpr > + __formatter_ptr() noexcept > + : _M_spec() > + { > + _M_spec._M_type = _Pres_p; > + _M_spec._M_alt = true; > + } > > constexpr > __formatter_ptr(_Spec<_CharT> __spec) noexcept > @@ -2483,14 +2489,14 @@ namespace __format > if (*__first == 'p') > { > __spec._M_type = _Pres_p; > - _M_spec._M_alt = !_M_spec._M_alt; > + __spec._M_alt = !__spec._M_alt; > ++__first; > } > #if __glibcxx_format >= 202304L > else if (*__first == 'P') > { > __spec._M_type = _Pres_P; > - _M_spec._M_alt = !_M_spec._M_alt; > + __spec._M_alt = !__spec._M_alt; > ++__first; > } > #endif > @@ -2506,57 +2512,7 @@ namespace __format > format(const void* __v, basic_format_context<_Out, _CharT>& __fc) > const > { > auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v); > - char __buf[2 + sizeof(__v) * 2]; > - auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf), > - __u, 16); > - int __n = __ptr - __buf; > - __buf[0] = '0'; > - __buf[1] = 'x'; > -#if __glibcxx_format >= 202304L > - if (_M_spec._M_type == __format::_Pres_P) > - { > - __buf[1] = 'X'; > - for (auto __p = __buf + 2; __p != __ptr; ++__p) > -#if __has_builtin(__builtin_toupper) > - *__p = __builtin_toupper(*__p); > -#else > - *__p = std::toupper(*__p); > -#endif > - } > -#endif > - > - basic_string_view<_CharT> __str; > - if constexpr (is_same_v<_CharT, char>) > - __str = string_view(__buf, __n); > -#ifdef _GLIBCXX_USE_WCHAR_T > - else > - { > - auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT)); > - std::__to_wstring_numeric(__buf, __n, __p); > - __str = wstring_view(__p, __n); > - } > -#endif > - > -#if __glibcxx_format >= 202304L > - if (_M_spec._M_zero_fill) > - { > - size_t __width = _M_spec._M_get_width(__fc); > - if (__width <= __str.size()) > - return __format::__write(__fc.out(), __str); > - > - auto __out = __fc.out(); > - // Write "0x" or "0X" prefix before zero-filling. > - __out = __format::__write(std::move(__out), __str.substr(0, > 2)); > - __str.remove_prefix(2); > - size_t __nfill = __width - __n; > - return __format::__write_padded(std::move(__out), __str, > - __format::_Align_right, > - __nfill, _CharT('0')); > - } > -#endif > - > - return __format::__write_padded_as_spec(__str, __n, __fc, > _M_spec, > - __format::_Align_right); > + return __formatter_int<_CharT>(_M_spec).format(__u, __fc); > } > > private: > @@ -2571,7 +2527,7 @@ namespace __format > } > } > > - __format::_Spec<_CharT> _M_spec{}; > + __format::_Spec<_CharT> _M_spec; > }; > > } // namespace __format > -- > 2.53.0 > >
