On Tue, May 20, 2025 at 12:41 PM Tomasz Kaminski <tkami...@redhat.com>
wrote:

>
>
> 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.
>>
>> >       (_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
>>
> Changing it to /* _Pres_s, */
>
Finally removed it, as adding this comment will put integer presentation
types over 80 column
limit, and I think there is more value in having them in one line.

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