On Tue, 23 Sept 2025 at 13:34, Tomasz Kamiński <[email protected]> wrote:
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/chrono_io.h (__formatter_chrono::_M_parse):
>         Replace _ParseContext with basic_format_parse_context<_CharT> and
>         make it non-template.
>         (__formatter_duration::_M_parse): Replace _ParseContext with
>         basic_format_parse_context<_CharT> and remove unused default
>         argument.
> ---
> Tested on x86_64-linux. OK for trunk?

OK for trunk


>
>  libstdc++-v3/include/bits/chrono_io.h | 520 +++++++++++++-------------
>  1 file changed, 259 insertions(+), 261 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/chrono_io.h 
> b/libstdc++-v3/include/bits/chrono_io.h
> index 85b2013cf70..0a6a3a5ce5a 100644
> --- a/libstdc++-v3/include/bits/chrono_io.h
> +++ b/libstdc++-v3/include/bits/chrono_io.h
> @@ -559,282 +559,281 @@ namespace __format
>        __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
>        : _M_spec(__spec)
>        { }
> +
> +      constexpr typename basic_format_parse_context<_CharT>::iterator
> +      _M_parse(basic_format_parse_context<_CharT>& __pc, _ChronoParts 
> __parts,
> +              const _ChronoSpec<_CharT>& __def)
> +      {
> +       auto __first = __pc.begin();
> +       auto __last = __pc.end();
>
> -      template<typename _ParseContext>
> -       constexpr typename _ParseContext::iterator
> -       _M_parse(_ParseContext& __pc, _ChronoParts __parts,
> -                const _ChronoSpec<_CharT>& __def)
> -       {
> -         auto __first = __pc.begin();
> -         auto __last = __pc.end();
> -
> -         _ChronoSpec<_CharT> __spec = __def;
> -
> -         auto __finalize = [this, &__spec, &__def] {
> -           using enum _ChronoParts;
> -           _ChronoParts __checked
> -             = __spec._M_debug ? _YearMonthDay|_IndexedWeekday
> -                               : _Month|_Weekday;
> -           // n.b. for calendar types __def._M_needed contains only parts
> -           // copied from the input, remaining ones are computed, and thus ok
> -           __spec._M_needs_ok_check
> -             = __spec._M_needs(__def._M_needed & __checked);
> -           _M_spec = __spec;
> -         };
> -
> -         auto __finished = [&] {
> -           if (__first == __last || *__first == '}')
> -             {
> -               __finalize();
> -               return true;
> -             }
> -           return false;
> -         };
> -
> -         if (__finished())
> -           return __first;
> -
> -         __first = __spec._M_parse_fill_and_align(__first, __last);
> -         if (__finished())
> -           return __first;
> +       _ChronoSpec<_CharT> __spec = __def;
>
> -         __first = __spec._M_parse_width(__first, __last, __pc);
> -         if (__finished())
> -           return __first;
> +       auto __finalize = [this, &__spec, &__def] {
> +         using enum _ChronoParts;
> +         _ChronoParts __checked
> +           = __spec._M_debug ? _YearMonthDay|_IndexedWeekday
> +                             : _Month|_Weekday;
> +         // n.b. for calendar types __def._M_needed contains only parts
> +         // copied from the input, remaining ones are computed, and thus ok
> +         __spec._M_needs_ok_check
> +            = __spec._M_needs(__def._M_needed & __checked);
> +         _M_spec = __spec;
> +       };
>
> -         if (*__first == '.')
> +       auto __finished = [&] {
> +         if (__first == __last || *__first == '}')
>             {
> -             if ((__parts & _ChronoParts::_EpochUnits) == 0
> -                 || !__spec._M_floating_point_rep)
> -               __throw_format_error("format error: invalid precision for 
> duration");
> -
> -             // Precision is allowed, but value is ignored.
> -             __first = _Spec<_CharT>()._M_parse_precision(__first, __last, 
> __pc);
> -             // Still inditate that there was user supplied precision.
> -             __spec._M_prec_kind = _WP_value;
> -            if (__finished())
> -              return __first;
> +             __finalize();
> +             return true;
>             }
> +         return false;
> +       };
> +
> +       if (__finished())
> +         return __first;
> +
> +       __first = __spec._M_parse_fill_and_align(__first, __last);
> +       if (__finished())
> +         return __first;
>
> -         __spec._M_localized = false;
> -         __first = __spec._M_parse_locale(__first, __last);
> -         if (__finished())
> -           return __first;
> +       __first = __spec._M_parse_width(__first, __last, __pc);
> +       if (__finished())
> +         return __first;
>
> -         // Everything up to the end of the string or the first '}' is a
> -         // chrono-specs string. Check it is valid.
> +       if (*__first == '.')
>           {
> -           __string_view __str(__first, __last - __first);
> -           auto __end = __str.find('}');
> -           if (__end != __str.npos)
> -             {
> -               __str.remove_suffix(__str.length() - __end);
> -               __last = __first + __end;
> -             }
> -           if (__str.find('{') != __str.npos)
> -             __throw_format_error("chrono format error: '{' in 
> chrono-specs");
> +           if ((__parts & _ChronoParts::_EpochUnits) == 0
> +                 || !__spec._M_floating_point_rep)
> +             __throw_format_error("format error: invalid precision for 
> duration");
> +
> +           // Precision is allowed, but value is ignored.
> +           __first = _Spec<_CharT>()._M_parse_precision(__first, __last, 
> __pc);
> +           // Still inditate that there was user supplied precision.
> +           __spec._M_prec_kind = _WP_value;
> +           if (__finished())
> +             return __first;
>           }
>
> -         // Parse chrono-specs in [first,last), checking each conversion-spec
> -         // against __parts (so fail for %Y if no year in parts).
> -         // Save range in __spec._M_chrono_specs.
> -         __spec._M_debug = false;
> -         __spec._M_locale_specific = false;
> -         __spec._M_needed = _ChronoParts::_None;
> -         __spec._M_chrono_specs = __string_view();
> -
> -         const auto __chrono_specs = __first++; // Skip leading '%'
> -         if (*__chrono_specs != '%')
> -           __throw_format_error("chrono format error: no '%' at start of "
> -                                "chrono-specs");
> +       __spec._M_localized = false;
> +       __first = __spec._M_parse_locale(__first, __last);
> +       if (__finished())
> +         return __first;
>
> -         _CharT __mod{};
> -         bool __conv = true;
> -         while (__first != __last)
> +       // Everything up to the end of the string or the first '}' is a
> +       // chrono-specs string. Check it is valid.
> +       {
> +         __string_view __str(__first, __last - __first);
> +         auto __end = __str.find('}');
> +         if (__end != __str.npos)
>             {
> -             enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O };
> -             _Mods __allowed_mods = _Mod_none;
> +             __str.remove_suffix(__str.length() - __end);
> +             __last = __first + __end;
> +           }
> +         if (__str.find('{') != __str.npos)
> +           __throw_format_error("chrono format error: '{' in chrono-specs");
> +       }
>
> -             _ChronoParts __needed = _ChronoParts::_None;
> -             bool __locale_specific = false;
> +       // Parse chrono-specs in [first,last), checking each conversion-spec
> +       // against __parts (so fail for %Y if no year in parts).
> +       // Save range in __spec._M_chrono_specs.
> +       __spec._M_debug = false;
> +       __spec._M_locale_specific = false;
> +       __spec._M_needed = _ChronoParts::_None;
> +       __spec._M_chrono_specs = __string_view();
> +
> +       const auto __chrono_specs = __first++; // Skip leading '%'
> +       if (*__chrono_specs != '%')
> +         __throw_format_error("chrono format error: no '%' at start of "
> +                              "chrono-specs");
> +
> +       _CharT __mod{};
> +       bool __conv = true;
> +       while (__first != __last)
> +         {
> +           enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O };
> +           _Mods __allowed_mods = _Mod_none;
>
> -             _CharT __c = *__first++;
> -             switch (__c)
> -               {
> -               using enum _ChronoParts;
> -               case 'a':
> -               case 'A':
> -                 __needed = _Weekday;
> -                 __locale_specific = true;
> -                 break;
> -               case 'b':
> -               case 'h':
> -               case 'B':
> -                 __needed = _Month;
> -                 __locale_specific = true;
> -                 break;
> -               case 'c':
> -                 __needed = _Date|_HoursMinutesSeconds;
> -                 __allowed_mods = _Mod_E;
> -                 __locale_specific = true;
> -                 break;
> -               case 'C':
> -                 __needed = _Year;
> -                 __allowed_mods = _Mod_E;
> -                 break;
> -               case 'd':
> -               case 'e':
> -                 __needed = _Day;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'D':
> -               case 'F':
> -                 __needed = _YearMonthDay;
> -                 break;
> -               case 'g':
> -               case 'G':
> -               case 'V':
> -                 __needed = _LocalDays|_Year|_DayOfYear|_Weekday;
> -                 break;
> -               case 'H':
> -               case 'I':
> -                 __needed = _HoursMinutesSeconds;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'j':
> -                 __needed = __parts & _DayOfYear;
> -                 // If we do not know day-of-year then we must have a 
> duration,
> -                 // which is to be formatted as decimal number of days.
> -                 if (__needed == _None)
> -                   __needed = _HoursMinutesSeconds;
> -                 break;
> -               case 'm':
> -                 __needed = _Month;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'M':
> -                 __needed = _HoursMinutesSeconds;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'p':
> -               case 'r':
> -                 __locale_specific = true;
> -                 [[fallthrough]];
> -               case 'R':
> -                 __needed = _HoursMinutesSeconds;
> -                 break;
> -               case 'T':
> -                 __needed = _TimeOfDay;
> -                 break;
> -               case 'q':
> -                 __needed = _UnitSuffix;
> -                 break;
> -               case 'Q':
> -                 __needed = _EpochUnits;
> -                 break;
> -               case 'S':
> -                 __needed = _TimeOfDay;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'u':
> -               case 'w':
> -                 __needed = _Weekday;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'U':
> -               case 'W':
> -                 __needed = _DayOfYear|_Weekday;
> -                 __allowed_mods = _Mod_O;
> -                 break;
> -               case 'x':
> -                 __needed = _Date;
> -                 __locale_specific = true;
> -                 __allowed_mods = _Mod_E;
> -                 break;
> -               case 'X':
> -                 __needed = _HoursMinutesSeconds;
> -                 __locale_specific = true;
> -                 __allowed_mods = _Mod_E;
> -                 break;
> -               case 'y':
> -                 __needed = _Year;
> -                 __allowed_mods = _Mod_E_O;
> -                 break;
> -               case 'Y':
> -                 __needed = _Year;
> -                 __allowed_mods = _Mod_E;
> -                 break;
> -               case 'z':
> -                 __needed = _ZoneOffset;
> -                 __allowed_mods = _Mod_E_O;
> -                 break;
> -               case 'Z':
> -                 __needed = _ZoneAbbrev;
> -                 break;
> -               case 'n':
> -               case 't':
> -               case '%':
> -                 break;
> -               case 'O':
> -               case 'E':
> -                 if (__mod) [[unlikely]]
> -                   {
> -                     __allowed_mods = _Mod_none;
> -                     break;
> -                   }
> -                 __mod = __c;
> -                 continue;
> -               default:
> -                 __throw_format_error("chrono format error: invalid "
> -                                      " specifier in chrono-specs");
> -               }
> +           _ChronoParts __needed = _ChronoParts::_None;
> +           bool __locale_specific = false;
>
> -             if ((__mod == 'E' && !(__allowed_mods & _Mod_E))
> -                   || (__mod == 'O' && !(__allowed_mods & _Mod_O)))
> -               __throw_format_error("chrono format error: invalid "
> -                                    " modifier in chrono-specs");
> -             if (__mod && __c != 'z')
> +           _CharT __c = *__first++;
> +           switch (__c)
> +             {
> +             using enum _ChronoParts;
> +             case 'a':
> +             case 'A':
> +               __needed = _Weekday;
>                 __locale_specific = true;
> -             __mod = _CharT();
> -
> -             // localized formats do not include subseconds
> -             if (__locale_specific)
> -               __needed -= _ChronoParts::_Subseconds;
> -
> -             if ((__parts & __needed) != __needed)
> -               __throw_format_error("chrono format error: format argument "
> -                                    "does not contain the information "
> -                                    "required by the chrono-specs");
> -             __spec._M_needed |= __needed;
> -             __spec._M_locale_specific |= __locale_specific;
> -
> -             // Scan for next '%', ignoring literal-chars before it.
> -             size_t __pos = __string_view(__first, __last - 
> __first).find('%');
> -             if (__pos == 0)
> -               ++__first;
> -             else
> -               {
> -                 if (__pos == __string_view::npos)
> -                   {
> -                     __first = __last;
> -                     __conv = false;
> -                   }
> -                 else
> -                   __first += __pos + 1;
> -               }
> +               break;
> +             case 'b':
> +             case 'h':
> +             case 'B':
> +               __needed = _Month;
> +               __locale_specific = true;
> +               break;
> +             case 'c':
> +               __needed = _Date|_HoursMinutesSeconds;
> +               __allowed_mods = _Mod_E;
> +               __locale_specific = true;
> +               break;
> +             case 'C':
> +               __needed = _Year;
> +               __allowed_mods = _Mod_E;
> +               break;
> +             case 'd':
> +             case 'e':
> +               __needed = _Day;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'D':
> +             case 'F':
> +               __needed = _YearMonthDay;
> +               break;
> +             case 'g':
> +             case 'G':
> +             case 'V':
> +               __needed = _LocalDays|_Year|_DayOfYear|_Weekday;
> +               break;
> +             case 'H':
> +             case 'I':
> +               __needed = _HoursMinutesSeconds;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'j':
> +               __needed = __parts & _DayOfYear;
> +               // If we do not know day-of-year then we must have a duration,
> +               // which is to be formatted as decimal number of days.
> +               if (__needed == _None)
> +                 __needed = _HoursMinutesSeconds;
> +               break;
> +             case 'm':
> +               __needed = _Month;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'M':
> +               __needed = _HoursMinutesSeconds;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'p':
> +             case 'r':
> +               __locale_specific = true;
> +               [[fallthrough]];
> +             case 'R':
> +               __needed = _HoursMinutesSeconds;
> +               break;
> +             case 'T':
> +               __needed = _TimeOfDay;
> +               break;
> +             case 'q':
> +               __needed = _UnitSuffix;
> +               break;
> +             case 'Q':
> +               __needed = _EpochUnits;
> +               break;
> +             case 'S':
> +               __needed = _TimeOfDay;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'u':
> +             case 'w':
> +               __needed = _Weekday;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'U':
> +             case 'W':
> +               __needed = _DayOfYear|_Weekday;
> +               __allowed_mods = _Mod_O;
> +               break;
> +             case 'x':
> +               __needed = _Date;
> +               __locale_specific = true;
> +               __allowed_mods = _Mod_E;
> +               break;
> +             case 'X':
> +               __needed = _HoursMinutesSeconds;
> +               __locale_specific = true;
> +               __allowed_mods = _Mod_E;
> +               break;
> +             case 'y':
> +               __needed = _Year;
> +               __allowed_mods = _Mod_E_O;
> +               break;
> +             case 'Y':
> +               __needed = _Year;
> +               __allowed_mods = _Mod_E;
> +               break;
> +             case 'z':
> +               __needed = _ZoneOffset;
> +               __allowed_mods = _Mod_E_O;
> +               break;
> +             case 'Z':
> +               __needed = _ZoneAbbrev;
> +               break;
> +             case 'n':
> +             case 't':
> +             case '%':
> +               break;
> +             case 'O':
> +             case 'E':
> +               if (__mod) [[unlikely]]
> +                 {
> +                   __allowed_mods = _Mod_none;
> +                   break;
> +                 }
> +               __mod = __c;
> +               continue;
> +             default:
> +               __throw_format_error("chrono format error: invalid specifier "
> +                                    "in chrono-specs");
>             }
>
> -         // Check for a '%' conversion-spec without a type.
> -         if (__conv || __mod != _CharT())
> -           __throw_format_error("chrono format error: unescaped '%' in "
> -                                "chrono-specs");
> +           if ((__mod == 'E' && !(__allowed_mods & _Mod_E))
> +                  || (__mod == 'O' && !(__allowed_mods & _Mod_O)))
> +             __throw_format_error("chrono format error: invalid  modifier "
> +                                  "in chrono-specs");
> +           if (__mod && __c != 'z')
> +             __locale_specific = true;
> +           __mod = _CharT();
> +
> +           // localized formats do not include subseconds
> +           if (__locale_specific)
> +             __needed -= _ChronoParts::_Subseconds;
> +
> +           if ((__parts & __needed) != __needed)
> +             __throw_format_error("chrono format error: format argument does 
> "
> +                                  "not contain the information required by 
> the "
> +                                  "chrono-specs");
> +           __spec._M_needed |= __needed;
> +           __spec._M_locale_specific |= __locale_specific;
> +
> +           // Scan for next '%', ignoring literal-chars before it.
> +           size_t __pos = __string_view(__first, __last - __first).find('%');
> +           if (__pos == 0)
> +             ++__first;
> +           else
> +             {
> +               if (__pos == __string_view::npos)
> +                 {
> +                   __first = __last;
> +                   __conv = false;
> +                 }
> +               else
> +                 __first += __pos + 1;
> +             }
> +         }
>
> -         __spec._M_chrono_specs
> -           = __string_view(__chrono_specs, __first - __chrono_specs);
> +       // Check for a '%' conversion-spec without a type.
> +       if (__conv || __mod != _CharT())
> +         __throw_format_error("chrono format error: unescaped '%' in "
> +                              "chrono-specs");
>
> -         __finalize();
> -         return __first;
> -       }
> +       __spec._M_chrono_specs
> +         = __string_view(__chrono_specs, __first - __chrono_specs);
> +
> +       __finalize();
> +       return __first;
> +      }
>
>        // pre: !_M_spec._M_chrono_specs.empty()
>        template<typename _FormatContext>
> @@ -869,7 +868,6 @@ namespace __format
>           return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill);
>         }
>
> -
>        _ChronoSpec<_CharT> _M_spec;
>
>      protected:
> @@ -1934,10 +1932,10 @@ namespace __format
>        using __formatter_chrono<_CharT>::__formatter_chrono;
>        using __formatter_chrono<_CharT>::_M_spec;
>
> -      template<typename _Duration, typename _ParseContext>
> -       constexpr typename _ParseContext::iterator
> -       _M_parse(_ParseContext& __pc, _ChronoParts __parts,
> -                const _ChronoSpec<_CharT>& __def = {})
> +      template<typename _Duration>
> +       constexpr typename basic_format_parse_context<_CharT>::iterator
> +       _M_parse(basic_format_parse_context<_CharT>& __pc, _ChronoParts 
> __parts,
> +                const _ChronoSpec<_CharT>& __def)
>         {
>           using _Rep = typename _Duration::rep;
>           using enum _ChronoParts;
> --
> 2.51.0
>

Reply via email to