https://gcc.gnu.org/g:43e5eab8a4f5e95fb8539ef74de033ed9945623c
commit r16-7970-g43e5eab8a4f5e95fb8539ef74de033ed9945623c Author: Tomasz Kamiński <[email protected]> Date: Thu Mar 5 15:00:31 2026 +0100 libstdc+: Eliminate usage of alloca for non-localized formatting 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 (that depends on sizeof(_Int)) of the buffer known (__buf_size) 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, r16-7844-gbfc2b87f8244a1 modified _Pres_p and _Pres_P to have same value as _Pres_x and _Pres_X, so format specifiers are subset of one allowed for integers. In consequence we simply delegate to format method of __formatter_int, reducing the code duplication. The set of allowed specifiers is still limited per C++ standard by __formatter_ptr::parse. This patch 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. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- 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 786edbe29b20..cfb57f4a7a66 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
