On Tue, May 20, 2025 at 11:41 AM Jonathan Wakely <jwak...@redhat.com> wrote:

> On 20/05/25 09:35 +0200, Tomasz Kamiński wrote:
> >These patch makes following changes to _Pres_type values:
> > * _Pres_esc is replaced with separate _M_debug flag.
> > * _Pres_s, _Pres_p do not overlap with _Pres_none.
> > * hexadecimal presentation use same values for pointer, integer
> >   and floating point types.
> >
> >The members of _Spec<_CharT> are rearanged so the class contains 8 bits
>
> s/rearanged/rearranged/
>
> >of reserved for future use (_M_reserved) and 8 bits of tail padding.
>
> s/of reserved/reserved/
>
> >Derived classes (like _ChronoSpec<_CharT>) can reuse the storage for
> initial
> >members. We also add _SpecBase as the base class for _Spec<_CharT> to make
> >it non-C++98 POD, which allows tail padding to be reused on Itanium ABI.
> >
> >Finally, the format enumerators are defined as enum class with unsigned
> >char as underlying type, followed by using enum to bring names in scope.
> >_Term_char names are adjusted for consistency, and enumerator values are
> >changed so it can fit in smaller bitfields.
> >
> >The '?' is changed to separate _M_debug flag, to allow debug format to be
> >independent from the presentation type, and applied to multiple
> presentation
> >types. For example it could be used to trigger memberwise or reflection
> based
> >formatting.
> >
> >The _M_format_character and _M_format_character_escaped functions are
> merged
> >to single function that handle normal and debug presentation. In
> particular
> >this would allow future support for '?c' for printing integer types as
> escaped
> >character. _S_character_width is also folded in the merged function.
> >
> >Decoupling _Pres_s value from _Pres_none, allows it to be used for string
> >presentation for range formatting, and removes the need for separate
> _Pres_seq
> >and _Pres_str. This does not affect formatting of bool as
> __formatter_int::_M_parse
> >overrides default value of _M_type. And with separation of the _M_debug
> flag,
> >__formatter_str::format behavior is now agnostic to _M_type value.
> >
> >The values for integer presentation types, are arranged so textual
> presentations
> >(_Prec_s, _Pres_c) are grouped together. For consistency floating point
> >hexadecimal presentation uses the same values as integer ones.
> >
> >New _Pres_p and setting for _M_alt enables using some spec to configure
> formatting
> >of  uintptr_t with __formatter_int, and const void* with __formatter_ptr.
> >Differentiating it from _Pres_none would allow future of formatter<T*,
> _CharT>
> >that would require explicit presentation type to be specified. This would
> allow
> >std::vector<T*> to be formatter directly with '{::p}' format spec.
>
> s/formatter/formatted/
>
> >The constructors for __formatter_int and _formatter_ptr from
> _Spec<_CharT>,
>
> s/_formatter_ptr/__formatter_ptr/
>
> >now also set default presentation modes, as format functions expects them.
> >
> >libstdc++-v3/ChangeLog:
> >
> >       * include/bits/chrono_io.h
> (_ChronoSpec<_CharT>::_M_locale_specific):
> >       Declare as bit filed in tail-padding..
>
> s/filed/field/
>
> >       * include/bits/formatfwd.h (__format::_Align): Defined as enum
> class
> >       and add using enum.
> >       * include/std/format (__format::_Pres_type, __format::_Sign)
> >       (__format::_WidthPrec,  __format::_Arg_t): Defined as enum class
> and
> >       add using enum.
> >       (_Pres_type::_Pres_esc): Replace with _Pres_max.
> >       (_Pres_type::_Pres_seq, _Pres_type::_Pres_str): Remove.
> >       (__format::_Pres_type): Updated values of enumerators as described
> above.
>
> This line is more than 80 columns, please add a line break.
>
> Please adjust the rest of the ChangeLog to keep to around 74 chars
> where possible.
>
I will remove <_CharT> from _Spec, _Chrono_spec, _forrmatter_int,
__formatter_ptr,
and __formatter_str, as there are non specializations. This should help
with keeping
in the limit.

>
> >       (_Spec<_CharT>): Rearranged members to have 8 bits of tail-padding.
> >       (_Spec<_CharT>::_M_debug): Defined.
> >       (_Spec<_CharT>::_M_reserved): Extended to 8 bits and moved at the
> end.
> >       (_Spec<_CharT>::_M_reserved2): Removed.
> >       (_Spec<_CharT>::_M_parse_fill_and_align,
> _Spec<_CharT>::_M_parse_sign)
> >       (__format::__write_padded_as_spec): Adjusted default value checks.
> >       (__format::_Term_char): Add using enum and adjust enumertors.
> >       (__Escapes::_S_term): Adjusted for _Term_char values.
> >       (__format::__should_escape_ascii): Adjusted _Term_char uses.
> >       (__foramt::__write_escaped): Adjusted for _Term_char.
> >       (__formatter_str<_CharT>::parse): Set _Pres_s if specifed and
> _M_debug
> >       instead of _Pres_esc.
> >       (__formatter_str<_CharT>::set_debug_format): Set _M_debug instead
> of
> >       _Pres_esc.
> >       (__formatter_str<_CharT>::format,
> __formatter_str<_CharT>::_M_format_range):
> >       Check _M_debug instead of _Prec_esc.
> >       (__formatter_str<_CharT>::_M_format_escaped): Adjusted _Term_char
> uses.
> >       (__formatter_int<_CharT>::__formatter_int(_Spec<_CharT>)): Set
> _Pres_d if
> >       default presentation type is not set.
> >       (__formatter_int<_CharT>::_M_parse): Adjusted default value checks.
> >       (__formatter_int<_CharT>::_M_do_parse): Set _M_debug instead of
> _Pres_esc.
> >       (__formatter_int<_CharT>::_M_format_character): Handle escaped
> presentation.
> >       (__formatter_int<_CharT>::_M_format_character_escaped)
> >       (__formatter_int<_CharT>::_S_character_width): Merged into
> _M_format_character.
> >       (__formatter_ptr<_CharT>::__formatter_ptr(_Spec<_CharT>)): Set
> _Pres_p if default
> >       presentation type is not set.
> >       (__formatter_ptr<_CharT>::parse): Add default __type parameter,
> store _Pres_p,
> >       and handle _M_alt to be consistent with meaning for integers.
> >       (__foramtter_ptr<_CharT>::_M_set_default): Define.
> >       (__format::__pack_arg_types, std::basic_format_args): Add
> necessary casts.
> >       (formatter<_CharT, _CharT>::set_debug_format)
> >       (formatter<char, wchar_t>::set_debug_format): Set _M_debug instead
> of _Pres_esc.
> >       (formatter<_CharT, _CharT>::format, formatter<char,
> wchar_t>::format):
> >       Simplify calls to _M_format_character.
> >       (range_formatter<_Rg, _CharT>::parse): Replace _Pres_str with
> _Pres_s
> >       and set _M_debug instead of _Pres_esc.
> >       (range_formatter<_Rg, _CharT>::format): Replace _Pres_str with
> _Pres_s.
> >---
> >Adjusted values for the _Term_char so they can now fit in 2 bits bitfield.
> >Handle _Term_non.
> >I think the commit message is now longer than the diff.
>
> :-)
>
> >OK for trunk?
>
> OK, thanks.
>
> (There are two more spelling typos noted below ...)
>
>
> > libstdc++-v3/include/bits/chrono_io.h |  18 +-
> > libstdc++-v3/include/bits/formatfwd.h |   3 +-
> > libstdc++-v3/include/std/format       | 257 ++++++++++++++------------
> > 3 files changed, 145 insertions(+), 133 deletions(-)
> >
> >diff --git a/libstdc++-v3/include/bits/chrono_io.h
> b/libstdc++-v3/include/bits/chrono_io.h
> >index ace8b9f2629..991142fd83f 100644
> >--- a/libstdc++-v3/include/bits/chrono_io.h
> >+++ b/libstdc++-v3/include/bits/chrono_io.h
> >@@ -207,21 +207,15 @@ namespace __format
> >   template<typename _CharT>
> >     struct _ChronoSpec : _Spec<_CharT>
> >     {
> >-      basic_string_view<_CharT> _M_chrono_specs;
> >-
> >-      // Use one of the reserved bits in __format::_Spec<C>.
> >+      // Placed in tail-padding of __format::_Spec<C>.
> >       // This indicates that a locale-dependent conversion specifier
> such as
> >       // %a is used in the chrono-specs. This is not the same as the
> >       // _Spec<C>::_M_localized member which indicates that "L" was
> present
> >       // in the format-spec, e.g. "{:L%a}" is localized and
> locale-specific,
> >       // but "{:L}" is only localized and "{:%a}" is only
> locale-specific.
> >-      constexpr bool
> >-      _M_locale_specific() const noexcept
> >-      { return this->_M_reserved; }
> >+      unsigned _M_locale_specific : 1;
> >
> >-      constexpr void
> >-      _M_locale_specific(bool __b) noexcept
> >-      { this->_M_reserved = __b; }
> >+      basic_string_view<_CharT> _M_chrono_specs;
> >     };
> >
> >   // Represents the information provided by a chrono type.
> >@@ -488,7 +482,7 @@ namespace __format
> >         _M_spec = __spec;
> >         _M_spec._M_chrono_specs
> >                = __string_view(__chrono_specs, __first - __chrono_specs);
> >-        _M_spec._M_locale_specific(__locale_specific);
> >+        _M_spec._M_locale_specific = __locale_specific;
> >
> >         return __first;
> >       }
> >@@ -512,7 +506,7 @@ namespace __format
> >         //       of chrono types is underspecified
> >         if constexpr (is_same_v<_CharT, char>)
> >           if constexpr (__unicode::__literal_encoding_is_utf8())
> >-            if (_M_spec._M_localized && _M_spec._M_locale_specific())
> >+            if (_M_spec._M_localized && _M_spec._M_locale_specific)
> >               {
> >                 extern locale __with_encoding_conversion(const locale&);
> >
> >@@ -806,7 +800,7 @@ namespace __format
> >         //       of chrono types is underspecified
> >         if constexpr (is_same_v<_CharT, char>)
> >           if constexpr (__unicode::__literal_encoding_is_utf8())
> >-            if (_M_spec._M_localized && _M_spec._M_locale_specific()
> >+            if (_M_spec._M_localized && _M_spec._M_locale_specific
> >                   && __loc != locale::classic())
> >               {
> >                 extern string_view
> >diff --git a/libstdc++-v3/include/bits/formatfwd.h
> b/libstdc++-v3/include/bits/formatfwd.h
> >index 3fa01ad1eab..777e6290f74 100644
> >--- a/libstdc++-v3/include/bits/formatfwd.h
> >+++ b/libstdc++-v3/include/bits/formatfwd.h
> >@@ -71,12 +71,13 @@ namespace __format
> >     concept __char = same_as<_CharT, char>;
> > #endif
> >
> >-  enum _Align {
> >+  enum class _Align : unsigned char {
> >     _Align_default,
> >     _Align_left,
> >     _Align_right,
> >     _Align_centre,
> >   };
> >+  using enum _Align;
> >
> >   template<typename _CharT> struct _Spec;
> >
> >diff --git a/libstdc++-v3/include/std/format
> b/libstdc++-v3/include/std/format
> >index b1823db83bc..c0a10a38152 100644
> >--- a/libstdc++-v3/include/std/format
> >+++ b/libstdc++-v3/include/std/format
> >@@ -472,30 +472,33 @@ namespace __format
> >       return {0, nullptr};
> >     }
> >
> >-  enum _Pres_type {
> >+  enum class _Pres_type : unsigned char {
> >     _Pres_none = 0, // Default type (not valid for integer presentation
> types).
> >+    _Pres_s = 1,  // For strings, bool, ranges
> >     // Presentation types for integral types (including bool and charT).
> >-    _Pres_d = 1, _Pres_b, _Pres_B, _Pres_o, _Pres_x, _Pres_X, _Pres_c,
> >-    // Presentation types for floating-point types.
> >-    _Pres_a = 1, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F, _Pres_g,
> _Pres_G,
> >-    _Pres_p = 0, _Pres_P,     // For pointers.
> >-    _Pres_s = 0,              // For strings, bool
> >-    _Pres_seq = 0, _Pres_str, // For ranges
> >-    _Pres_esc = 0xf,          // For strings, charT and ranges
>
> This /* s */ confused me more than it helped me, but maybe I'm just
> being slow this morning.
>
> >+    /* s */  _Pres_c = 2, _Pres_x, _Pres_X, _Pres_d, _Pres_o, _Pres_b,
> _Pres_B,
> >+    // Presentation types for floating-point types
> >+    _Pres_g = 1, _Pres_G, _Pres_a, _Pres_A, _Pres_e, _Pres_E, _Pres_f,
> _Pres_F,
> >+    // For pointers, the value are same as hexadecimal presentations for
> integers
> >+    _Pres_p = _Pres_x, _Pres_P = _Pres_X,
> >+    _Pres_max = 0xf,
> >   };
> >+  using enum _Pres_type;
> >
> >-  enum _Sign {
> >+  enum class _Sign : unsigned char {
> >     _Sign_default,
> >     _Sign_plus,
> >     _Sign_minus,  // XXX does this need to be distinct from
> _Sign_default?
> >     _Sign_space,
> >   };
> >+  using enum _Sign;
> >
> >-  enum _WidthPrec {
> >+  enum _WidthPrec : unsigned char {
> >     _WP_none,    // No width/prec specified.
> >     _WP_value,   // Fixed width/prec specified.
> >     _WP_from_arg // Use a formatting argument for width/prec.
> >   };
> >+  using enum _WidthPrec;
> >
> >   template<typename _Context>
> >     size_t
> >@@ -507,9 +510,17 @@ namespace __format
> >   constexpr bool __is_xdigit(char __c)
> >   { return std::__detail::__from_chars_alnum_to_val(__c) < 16; }
> >
> >+  // Used to make _Spec a non-C++98 POD, so the tail-padding is used.
> >+  // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#pod
> >+  struct _SpecBase
> >+  { };
> >+
> >   template<typename _CharT>
> >-    struct _Spec
> >+    struct _Spec : _SpecBase
> >     {
> >+      unsigned short _M_width;
> >+      unsigned short _M_prec;
> >+      char32_t _M_fill = ' ';
> >       _Align     _M_align : 2;
> >       _Sign      _M_sign : 2;
> >       unsigned   _M_alt : 1;
> >@@ -517,12 +528,11 @@ namespace __format
> >       unsigned   _M_zero_fill : 1;
> >       _WidthPrec _M_width_kind : 2;
> >       _WidthPrec _M_prec_kind : 2;
> >+      unsigned   _M_debug : 1;
> >       _Pres_type _M_type : 4;
> >-      unsigned   _M_reserved : 1;
> >-      unsigned   _M_reserved2 : 16;
> >-      unsigned short _M_width;
> >-      unsigned short _M_prec;
> >-      char32_t _M_fill = ' ';
> >+      unsigned   _M_reserved : 8;
> >+      // This class has  8bits of tail padding, that can be used by
> >+      // derived classes.
> >
> >       using iterator = typename basic_string_view<_CharT>::iterator;
> >
> >@@ -562,7 +572,7 @@ namespace __format
> >             char32_t __c = *__beg++;
> >             if (__is_scalar_value(__c))
> >               if (auto __next = __beg.base(); __next != __last)
> >-                if (_Align __align = _S_align(*__next))
> >+                if (_Align __align = _S_align(*__next); __align !=
> _Align_default)
> >                   {
> >                     _M_fill = __c;
> >                     _M_align = __align;
> >@@ -571,14 +581,14 @@ namespace __format
> >            }
> >         }
> >       else if (__last - __first >= 2)
> >-        if (_Align __align = _S_align(__first[1]))
> >+        if (_Align __align = _S_align(__first[1]); __align !=
> _Align_default)
> >           {
> >             _M_fill = *__first;
> >             _M_align = __align;
> >             return __first + 2;
> >           }
> >
> >-      if (_Align __align = _S_align(__first[0]))
> >+      if (_Align __align = _S_align(__first[0]); __align !=
> _Align_default)
> >         {
> >           _M_fill = ' ';
> >           _M_align = __align;
> >@@ -603,7 +613,7 @@ namespace __format
> >       constexpr iterator
> >       _M_parse_sign(iterator __first, iterator) noexcept
> >       {
> >-      if (_Sign __sign = _S_sign(*__first))
> >+      if (_Sign __sign = _S_sign(*__first); __sign != _Sign_default)
> >         {
> >           _M_sign = __sign;
> >           return __first + 1;
> >@@ -871,7 +881,7 @@ namespace __format
> >
> >       const size_t __nfill = __width - __estimated_width;
> >
> >-      if (__spec._M_align)
> >+      if (__spec._M_align != _Align_default)
> >       __align = __spec._M_align;
> >
> >       return __format::__write_padded(__fc.out(), __str, __align,
> __nfill,
> >@@ -896,12 +906,12 @@ namespace __format
> >        }
> >     }
> >
> >-
> >-  // Values are indices into _Escapes::all.
> >   enum class _Term_char : unsigned char {
> >-    _Tc_quote = 12,
> >-    _Tc_apos = 15
> >+    _Term_none,
> >+    _Term_quote,
> >+    _Term_apos,
> >   };
> >+  using enum _Term_char;
> >
> >   template<typename _CharT>
> >     struct _Escapes
> >@@ -912,10 +922,6 @@ namespace __format
> >       _Str_view _S_all()
> >       { return _GLIBCXX_WIDEN("\t\\t\n\\n\r\\r\\\\\\\"\\\"'\\'\\u\\x"); }
> >
> >-      static constexpr
> >-      _CharT _S_term(_Term_char __term)
> >-      { return _S_all()[static_cast<unsigned char>(__term)]; }
> >-
> >       static consteval
> >       _Str_view _S_tab()
> >       { return _S_all().substr(0, 3); }
> >@@ -947,6 +953,21 @@ namespace __format
> >       static consteval
> >       _Str_view _S_x()
> >       { return _S_all().substr(20, 2); }
> >+
> >+      static constexpr
> >+      _Str_view _S_term(_Term_char __term)
> >+      {
> >+      switch (__term)
> >+        {
> >+        case _Term_none:
> >+          return _Str_view();
> >+        case _Term_quote:
> >+          return _S_quote().substr(0, 1);
> >+        case _Term_apos:
> >+          return _S_apos().substr(0, 1);
> >+        }
> >+      __builtin_unreachable();
> >+      }
> >     };
> >
> >   template<typename _CharT>
> >@@ -991,9 +1012,9 @@ namespace __format
> >         case _Esc::_S_bslash()[0]:
> >           return true;
> >         case _Esc::_S_quote()[0]:
> >-          return __term == _Term_char::_Tc_quote;
> >+          return __term == _Term_quote;
> >         case _Esc::_S_apos()[0]:
> >-          return __term == _Term_char::_Tc_apos;
> >+          return __term == _Term_apos;
> >         default:
> >           return (__c >= 0 && __c < 0x20) || __c == 0x7f;
> >       };
> >@@ -1062,9 +1083,8 @@ namespace __format
> >         case _Esc::_S_apos()[0]:
> >           return __format::__write(__out, _Esc::_S_apos().substr(1, 2));
> >         default:
> >-          return __format::__write_escape_seq(__out,
> >-                              static_cast<_UChar>(__c),
> >-                                              _Esc::_S_u());
> >+          return __format::__write_escape_seq(
> >+                   __out, static_cast<_UChar>(__c), _Esc::_S_u());
> >       }
> >     }
> >
> >@@ -1177,8 +1197,7 @@ namespace __format
> >     _Out
> >     __write_escaped(_Out __out,  basic_string_view<_CharT> __str,
> _Term_char __term)
> >     {
> >-      *__out = _Escapes<_CharT>::_S_term(__term);
> >-      ++__out;
> >+      __out = __format::__write(__out,
> _Escapes<_CharT>::_S_term(__term));
> >
> >       if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
> >       __out = __format::__write_escaped_unicode(__out, __str, __term);
> >@@ -1189,8 +1208,7 @@ namespace __format
> >       // TODO Handle non-ascii extended encoding
> >       __out = __format::__write_escaped_ascii(__out, __str, __term);
> >
> >-      *__out = _Escapes<_CharT>::_S_term(__term);
> >-      return ++__out;
> >+      return __format::__write(__out, _Escapes<_CharT>::_S_term(__term));
> >     }
> >
> >   // A lightweight optional<locale>.
> >@@ -1312,11 +1330,14 @@ namespace __format
> >         return __first;
> >
> >       if (*__first == 's')
> >-        ++__first;
> >+        {
> >+          __spec._M_type = _Pres_s;
> >+          ++__first;
> >+        }
> > #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
> >       else if (*__first == '?')
> >         {
> >-          __spec._M_type = _Pres_esc;
> >+          __spec._M_debug = true;
> >           ++__first;
> >         }
> > #endif
> >@@ -1332,7 +1353,7 @@ namespace __format
> >       format(basic_string_view<_CharT> __s,
> >              basic_format_context<_Out, _CharT>& __fc) const
> >       {
> >-        if (_M_spec._M_type == _Pres_esc)
> >+        if (_M_spec._M_debug)
> >           return _M_format_escaped(__s, __fc);
> >
> >         if (_M_spec._M_width_kind == _WP_none
> >@@ -1349,22 +1370,21 @@ namespace __format
> >       _M_format_escaped(basic_string_view<_CharT> __s,
> >                         basic_format_context<_Out, _CharT>& __fc) const
> >       {
> >-        constexpr auto __term = __format::_Term_char::_Tc_quote;
> >         const size_t __padwidth = _M_spec._M_get_width(__fc);
> >         if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none)
> >-          return __format::__write_escaped(__fc.out(), __s, __term);
> >+          return __format::__write_escaped(__fc.out(), __s, _Term_quote);
> >
> >         const size_t __maxwidth = _M_spec._M_get_precision(__fc);
> >         const size_t __width = __truncate(__s, __maxwidth);
> >         // N.B. Escaping only increases width
> >         if (__padwidth <= __width && _M_spec._M_prec_kind == _WP_none)
> >-          return __format::__write_escaped(__fc.out(), __s, __term);
> >+          return __format::__write_escaped(__fc.out(), __s, _Term_quote);
> >
> >         // N.B. [tab:format.type.string] defines '?' as
> >         // Copies the escaped string ([format.string.escaped]) to the
> output,
> >         // so precision seem to appy to escaped string.
> >         _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth,
> __maxwidth);
> >-        __format::__write_escaped(__sink.out(), __s, __term);
> >+        __format::__write_escaped(__sink.out(), __s, _Term_quote);
> >         return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill);
> >       }
> >
> >@@ -1388,7 +1408,7 @@ namespace __format
> >                                size_t(ranges::distance(__rg)));
> >             return format(__str, __fc);
> >           }
> >-        else if (_M_spec._M_type != _Pres_esc)
> >+        else if (!_M_spec._M_debug)
> >           {
> >             const size_t __padwidth = _M_spec._M_get_width(__fc);
> >             if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none)
> >@@ -1441,7 +1461,7 @@ namespace __format
> >
> >       constexpr void
> >       set_debug_format() noexcept
> >-      { _M_spec._M_type = _Pres_esc; }
> >+      { _M_spec._M_debug = true; }
> > #endif
> >
> >     private:
> >@@ -1462,7 +1482,10 @@ namespace __format
> >       constexpr
> >       __formatter_int(_Spec<_CharT> __spec) noexcept
> >       : _M_spec(__spec)
> >-      { }
> >+      {
> >+      if (_M_spec._M_type == _Pres_none)
> >+        _M_spec._M_type = _Pres_d;
> >+      }
> >
> >       constexpr typename basic_format_parse_context<_CharT>::iterator
> >       _M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type
> __type)
> >@@ -1551,7 +1574,7 @@ namespace __format
> >         case 's':
> >           if (__type == _AsBool)
> >             {
> >-              __spec._M_type = _Pres_s; // same value (and meaning) as
> "none"
> >+              __spec._M_type = _Pres_s; // same meaning as "none" for
> bool
> >               ++__first;
> >             }
> >           break;
> >@@ -1559,7 +1582,7 @@ namespace __format
> >         case '?':
> >           if (__type == _AsChar)
> >             {
> >-              __spec._M_type = _Pres_esc;
> >+              __spec._M_debug = true;
> >               ++__first;
> >             }
> > #endif
> >@@ -1580,7 +1603,8 @@ namespace __format
> >           {
> >             auto __end = _M_do_parse(__pc, _AsBool);
> >             if (_M_spec._M_type == _Pres_s)
> >-              if (_M_spec._M_sign || _M_spec._M_alt ||
> _M_spec._M_zero_fill)
> >+              if (_M_spec._M_sign != _Sign_default || _M_spec._M_alt
> >+                    || _M_spec._M_zero_fill)
> >                 __throw_format_error("format error: format-spec contains
> "
> >                                      "invalid formatting options for "
> >                                      "'bool'");
> >@@ -1589,8 +1613,9 @@ namespace __format
> >         else if constexpr (__char<_Tp>)
> >           {
> >             auto __end = _M_do_parse(__pc, _AsChar);
> >-            if (_M_spec._M_type == _Pres_c || _M_spec._M_type ==
> _Pres_esc)
> >-              if (_M_spec._M_sign || _M_spec._M_alt ||
> _M_spec._M_zero_fill
> >+            if (_M_spec._M_type == _Pres_c)
> >+              if (_M_spec._M_sign != _Sign_default || _M_spec._M_alt
> >+                    || _M_spec._M_zero_fill
> >                     /* XXX should be invalid? || _M_spec._M_localized */)
> >                 __throw_format_error("format error: format-spec contains
> "
> >                                      "invalid formatting options for "
> >@@ -1702,51 +1727,34 @@ namespace __format
> >                                                 _M_spec);
> >       }
> >
> >-      [[__gnu__::__always_inline__]]
> >-      static size_t
> >-      _S_character_width(_CharT __c)
> >-      {
> >-      // N.B. single byte cannot encode charcter of width greater than 1
>
> s/charcter/character/
>
> >-      if constexpr (sizeof(_CharT) > 1u &&
> >-                      __unicode::__literal_encoding_is_unicode<_CharT>())
> >-        return __unicode::__field_width(__c);
> >-      else
> >-        return 1u;
> >-      }
> >-
> >       template<typename _Out>
> >       typename basic_format_context<_Out, _CharT>::iterator
> >       _M_format_character(_CharT __c,
> >-                    basic_format_context<_Out, _CharT>& __fc) const
> >+                          basic_format_context<_Out, _CharT>& __fc) const
> >       {
> >-        return __format::__write_padded_as_spec({&__c, 1u},
> >-                                                _S_character_width(__c),
> >-                                                __fc, _M_spec);
> >-      }
> >+        basic_string_view<_CharT> __in(&__c, 1u);
> >+        size_t __width = 1u;
> >+        // N.B. single byte cannot encode charcter of width greater than
> 1
>
> s/charcter/character/
>
> >+        if constexpr (sizeof(_CharT) > 1u &&
> >+
> __unicode::__literal_encoding_is_unicode<_CharT>())
> >+          __width = __unicode::__field_width(__c);
> >
> >-      template<typename _Out>
> >-      typename basic_format_context<_Out, _CharT>::iterator
> >-      _M_format_character_escaped(_CharT __c,
> >-                                  basic_format_context<_Out, _CharT>&
> __fc) const
> >-      {
> >-        using _Esc = _Escapes<_CharT>;
> >-        constexpr auto __term = __format::_Term_char::_Tc_apos;
> >-        const basic_string_view<_CharT> __in(&__c, 1u);
> >-        if (_M_spec._M_get_width(__fc) <= 3u)
> >-          return __format::__write_escaped(__fc.out(), __in, __term);
> >+        if (!_M_spec._M_debug)
> >+          return __format::__write_padded_as_spec(__in, __width,
> >+                                                  __fc, _M_spec);
> >+
> >+        __width += 2;
> >+        if (_M_spec._M_get_width(__fc) <= __width)
> >+          return __format::__write_escaped(__fc.out(), __in, _Term_apos);
> >
> >         _CharT __buf[12];
> >-        __format::_Fixedbuf_sink<_CharT> __sink(__buf);
> >-        __format::__write_escaped(__sink.out(), __in, __term);
> >+        _Fixedbuf_sink<_CharT> __sink(__buf);
> >+        __format::__write_escaped(__sink.out(), __in, _Term_apos);
> >
> >-        const basic_string_view<_CharT> __escaped = __sink.view();
> >-        size_t __estimated_width;
> >-        if (__escaped[1] == _Esc::_S_bslash()[0]) // escape sequence
> >-          __estimated_width = __escaped.size();
> >-        else
> >-          __estimated_width = 2 + _S_character_width(__c);
> >-        return __format::__write_padded_as_spec(__escaped,
> >-                                                __estimated_width,
> >+        __in = __sink.view();
> >+        if (__in[1] == _Escapes<_CharT>::_S_bslash()[0]) // escape
> sequence
> >+          __width = __in.size();
> >+        return __format::__write_padded_as_spec(__in, __width,
> >                                                 __fc, _M_spec);
> >       }
> >
> >@@ -2423,17 +2431,18 @@ namespace __format
> >       constexpr
> >       __formatter_ptr(_Spec<_CharT> __spec) noexcept
> >       : _M_spec(__spec)
> >-      { }
> >+      { _M_set_default(_Pres_p); }
> >
> >       constexpr typename basic_format_parse_context<_CharT>::iterator
> >-      parse(basic_format_parse_context<_CharT>& __pc)
> >+      parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type
> = _Pres_p)
> >       {
> >       __format::_Spec<_CharT> __spec{};
> >       const auto __last = __pc.end();
> >       auto __first = __pc.begin();
> >
> >-      auto __finalize = [this, &__spec] {
> >+      auto __finalize = [this, &__spec, __type] {
> >         _M_spec = __spec;
> >+        _M_set_default(__type);
> >       };
> >
> >       auto __finished = [&] {
> >@@ -2461,19 +2470,23 @@ namespace __format
> > #endif
> >
> >       __first = __spec._M_parse_width(__first, __last, __pc);
> >+      if (__finished())
> >+        return __first;
> >
> >-      if (__first != __last)
> >+      if (*__first == 'p')
> >         {
> >-          if (*__first == 'p')
> >-            ++__first;
> >+          __spec._M_type = _Pres_p;
> >+          _M_spec._M_alt = !_M_spec._M_alt;
> >+          ++__first;
> >+        }
> > #if __glibcxx_format >= 202304L
> >-          else if (*__first == 'P')
> >-          {
> >-            __spec._M_type = __format::_Pres_P;
> >-            ++__first;
> >-          }
> >-#endif
> >+      else if (*__first == 'P')
> >+        {
> >+          __spec._M_type = _Pres_P;
> >+          _M_spec._M_alt = !_M_spec._M_alt;
> >+          ++__first;
> >         }
> >+#endif
> >
> >       if (__finished())
> >         return __first;
> >@@ -2540,6 +2553,17 @@ namespace __format
> >       }
> >
> >     private:
> >+      [[__gnu__::__always_inline__]]
> >+      constexpr void
> >+      _M_set_default(_Pres_type __type)
> >+      {
> >+      if (_M_spec._M_type == _Pres_none && __type != _Pres_none)
> >+      {
> >+        _M_spec._M_type = __type;
> >+        _M_spec._M_alt = !_M_spec._M_alt;
> >+      }
> >+      }
> >+
> >       __format::_Spec<_CharT> _M_spec{};
> >     };
> >
> >@@ -2562,11 +2586,8 @@ namespace __format
> >       typename basic_format_context<_Out, _CharT>::iterator
> >       format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const
> >       {
> >-        if (_M_f._M_spec._M_type == __format::_Pres_none
> >-            || _M_f._M_spec._M_type == __format::_Pres_c)
> >+        if (_M_f._M_spec._M_type == __format::_Pres_c)
> >           return _M_f._M_format_character(__u, __fc);
> >-        else if (_M_f._M_spec._M_type == __format::_Pres_esc)
> >-          return _M_f._M_format_character_escaped(__u, __fc);
> >         else
> >           return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u),
> __fc);
> >       }
> >@@ -2574,7 +2595,7 @@ namespace __format
> > #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
> >       constexpr void
> >       set_debug_format() noexcept
> >-      { _M_f._M_spec._M_type = __format::_Pres_esc; }
> >+      { _M_f._M_spec._M_debug = true; }
> > #endif
> >
> >     private:
> >@@ -2598,11 +2619,8 @@ namespace __format
> >       typename basic_format_context<_Out, wchar_t>::iterator
> >       format(char __u, basic_format_context<_Out, wchar_t>& __fc) const
> >       {
> >-        if (_M_f._M_spec._M_type == __format::_Pres_none
> >-            || _M_f._M_spec._M_type == __format::_Pres_c)
> >+        if (_M_f._M_spec._M_type == __format::_Pres_c)
> >           return _M_f._M_format_character(__u, __fc);
> >-        else if (_M_f._M_spec._M_type == __format::_Pres_esc)
> >-          return _M_f._M_format_character_escaped(__u, __fc);
> >         else
> >           return _M_f.format(static_cast<unsigned char>(__u), __fc);
> >       }
> >@@ -2610,7 +2628,7 @@ namespace __format
> > #if __glibcxx_format_ranges // C++ >= 23 && HOSTED
> >       constexpr void
> >       set_debug_format() noexcept
> >-      { _M_f._M_spec._M_type = __format::_Pres_esc; }
> >+      { _M_f._M_spec._M_debug = true; }
> > #endif
> >
> >     private:
> >@@ -3864,7 +3882,7 @@ namespace __format
> >       }
> >     };
> >
> >-  enum _Arg_t : unsigned char {
> >+  enum class _Arg_t : unsigned char {
> >     _Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull,
> >     _Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr,
> _Arg_handle,
> >     _Arg_i128, _Arg_u128, _Arg_float128,
> >@@ -3876,6 +3894,7 @@ namespace __format
> >     _Arg_ieee128 = _Arg_float128,
> > #endif
> >   };
> >+  using enum _Arg_t;
> >
> >   template<typename _Context>
> >     struct _Arg_value
> >@@ -4488,7 +4507,7 @@ namespace __format
> >     {
> >       __UINT64_TYPE__ __packed_types = 0;
> >       for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i)
> >-      __packed_types = (__packed_types << _Bits) | *__i;
> >+      __packed_types = (__packed_types << _Bits) | (unsigned)*__i;
> >       return __packed_types;
> >     }
> > } // namespace __format
> >@@ -4501,7 +4520,7 @@ namespace __format
> >       static constexpr int _S_packed_type_mask = 0b11111;
> >       static constexpr int _S_max_packed_args = 12;
> >
> >-      static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) );
> >+      static_assert( (unsigned)__format::_Arg_max_ <= (1u <<
> _S_packed_type_bits) );
> >
> >       template<typename... _Args>
> >       using _Store = __format::_Arg_store<_Context, _Args...>;
> >@@ -5849,7 +5868,7 @@ namespace __format
> >        if (*__first == '?')
> >          {
> >            ++__first;
> >-           __spec._M_type = __format::_Pres_esc;
> >+           __spec._M_debug = true;
> >            if (__finished() || *__first != 's')
> >              __throw_format_error("format error: '?' is allowed only in"
> >                                   " combination with 's'");
> >@@ -5860,8 +5879,7 @@ namespace __format
> >            ++__first;
> >            if constexpr (same_as<_Tp, _CharT>)
> >              {
> >-               if (__spec._M_type != __format::_Pres_esc)
> >-                 __spec._M_type = __format::_Pres_str;
> >+               __spec._M_type = __format::_Pres_s;
> >                if (__finished())
> >                  return __finalize();
> >                __throw_format_error("format error: element format
> specifier"
> >@@ -5943,8 +5961,7 @@ namespace __format
> >       _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc)
> const
> >       {
> >         if constexpr (same_as<_Tp, _CharT>)
> >-          if (_M_spec._M_type == __format::_Pres_str
> >-                || _M_spec._M_type == __format::_Pres_esc)
> >+          if (_M_spec._M_type == __format::_Pres_s)
> >             {
> >               __format::__formatter_str __fstr(_M_spec);
> >               return __fstr._M_format_range(__rg, __fc);
> >--
> >2.49.0
> >
> >
>
>

Reply via email to