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?
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