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 rearranged so the class contains 8 bits
reserved for future use (_M_reserved) and 8 bits of tail padding.
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 formatted directly with '{::p}' format spec.

The constructors for __formatter_int and _formatter_ptr from _Spec<_CharT>,
now also set default presentation modes, as format functions expects them.

libstdc++-v3/ChangeLog:

        * include/bits/chrono_io.h (_ChronoSpec::_M_locale_specific):
        Declare as bit fiekd in tail-padding..
        * 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.
        (__format::_Spec): Rearranged members to have 8 bits of tail-padding.
        (_Spec::_M_debug): Defined.
        (_Spec::_M_reserved): Extended to 8 bits and moved at the end.
        (_Spec::_M_reserved2): Removed.
        (_Spec::_M_parse_fill_and_align, _Spec::_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.
        (__format::__write_escaped): Adjusted for _Term_char.
        (__formatter_str::parse): Set _Pres_s if specifed and _M_debug
        instead of _Pres_esc.
        (__formatter_str::set_debug_format): Set _M_debug instead of
        _Pres_esc.
        (__formatter_str::format, __formatter_str::_M_format_range):
        Check _M_debug instead of _Prec_esc.
        (__formatter_str::_M_format_escaped): Adjusted _Term_char uses.
        (__formatter_int::__formatter_int(_Spec<_CharT>)): Set _Pres_d if
        default presentation type is not set.
        (__formatter_int::_M_parse): Adjusted default value checks.
        (__formatter_int::_M_do_parse): Set _M_debug instead of _Pres_esc.
        (__formatter_int::_M_format_character): Handle escaped presentation.
        (__formatter_int::_M_format_character_escaped)
        (__formatter_int::_S_character_width): Merged into
        _M_format_character.
        (__formatter_ptr::__formatter_ptr(_Spec<_CharT>)): Set _Pres_p if
        default presentation type is not set.
        (__formatter_ptr::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.

Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
Signed-off-by: Tomasz Kamiński <tkami...@redhat.com>
---
Removed <_CharT> argument when not required from disambiguation from
Changelog. Fixed types, and removed /* s */ comment before _Pres_c in
_Pres_type.

Pushed to trunk.

 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 92a3098e808..346eb8b3c33 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&);
 
@@ -809,7 +803,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..b4929d5ae59 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
+    _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 8 bits 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
-       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 character of width greater than 1
+         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