https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110739

--- Comment #4 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Tomasz Kaminski <tkami...@gcc.gnu.org>:

https://gcc.gnu.org/g:4b3cefed1a08344495fedec4982d85168bd8173f

commit r16-1709-g4b3cefed1a08344495fedec4982d85168bd8173f
Author: Tomasz KamiÅski <tkami...@redhat.com>
Date:   Tue Jun 24 14:07:46 2025 +0200

    libstdc++: Type-erase chrono-data for formatting [PR110739]

    This patch reworks the formatting for the chrono types, such that they are
all
    formatted in terms of _ChronoData class, that includes all required fields.
    Populating each required field is performed in formatter for specific type,
    based on the chrono-spec used.

    To facilitate above, the _ChronoSpec now includes additional _M_needed
field,
    that represnts the chrono data that is referenced by format spec (this
value
    is also configured for __defSpec). This value differs from the value of
    __parts passed to _M_parse, which does include all fields that can be
computed
    from input (e.g. weekday_indexed can be computed for year_month_day). Later
    it is used to fill _ChronoData, in particular _M_fill_* family of
functions,
    to determine if given field needs to be set, and thus its value needs to be
    computed.

    In consequence _ChronoParts enum was extended with additional values, that
    allows more fine grained identification:
     * _TimeOfDay is separated into _HoursMinutesSeconds and _Subseconds,
     * _TimeZone is separated into _ZoneAbbrev and _ZoneOffset,
     * _LocalDays, _WeekdayIndex are defined and in included in _Date,
     * _Duration is removed, and instead _EpochUnits and _UnitSuffix are
       introduced.
    Furthermore, to avoid name conflicts _ChonoParts is now defined as enum
class,
    with additional operators that simplify uses.

    In addition to fields that can be printed using chrono-spec, _ChronoData
stores:
     * Total days in wall time (_M_ldays), day of year (_M_day_of_year) - used
by
       struct tm construction, and for ISO calendar computation.
     * Total seconds in wall time (_M_lseconds) - this value may be different
from
       sum of days, hours, minutes, seconds (e.g. see utc_time below). Included
       to allow future extension, like printing total minutes.
     * Total seconds since epoch - due offset different from above. Again to be
       used with future extension (e.g. %s as proposed in P2945R1).
     * Subseconds - count of attoseconds (10^(-18)), in addition to printing
can
       be used to  compute fractional hours, minutes.
    The both total seconds fields use single _TotalSeconds enumerator in
    _ChronoParts, that when present in combination with _EpochUnits or
_LocalDays
    indicates that _M_eseconds (_EpochSeconds) or _M_lseconds (_LocalSeconds)
are
    provided/required.

    To handle type formatting of time since epoch ('%Q'|_EpochUnits), we use
the
    format_args mechanism, where the result of +d.count() (see LWG4118) is
erased
    into make_format_args to local __arg_store, that is later referenced by
    _M_ereps (_M_ereps.get(0)).

    To handle precision values, and in prepartion to allow user to configure
ones,
    we store the precision as third element of _M_ereps (_M_ereps.get(2)), this
    allows duration with precision to be printed using "{0:{2}}". For
subseconds
    the precision is handled differently depending on the representation:
     * for integral reps, _M_subseconds value is used to determine fractional
value,
       precision is trimmed to 18 digits;
     * for floating-points, _M_ereps stores duration<Rep> initialized with only
       fractional seconds, that is later formatted with precision.
    Always using _M_subseconds fields for integral duration, means that we do
not
    use formattter for user-defined durations that are considered to be
integral
    (see empty_spec.cc file change). To avoid potentially expensive computation
    of _M_subseconds, we make sure that _ChronoParts::_Subseconds is set only
if
    _Subseconds are needed. In particular we remove this flag for localized
ouput
    in _M_parse.

    Construction of the _M_ereps as described above is handled by
__formatter_duration,
    that is then used to format duration, hh_mm_ss and time_points
specializations.
    This class also handles _UnitSuffix, the _M_units_suffix field is populated
    either with predefined suffix (chrono::__detail::__units_suffix) or one
produced
    locally.

    Finally, formatters for types listed below contains type specific logic:
     * hh_mm_ss - we do not compute total duration and seconds, unless
explicitly
       requested, as such computation may overflow;
     * utc_time - for time during leap second insertion, the _M_seconds field
is
       increased to 60;
     * __local_time_fmt - exception is thrown if zone offset (_ZoneOffset) or
       abbrevation (_ZoneAbbrev) is requsted, but corresponding pointer is
null,
       futhermore conversion from `char` to `wchar_t` for abbreviation is
performed
       if needed.

            PR libstdc++/110739

    libstdc++-v3/ChangeLog:

            * include/bits/chrono_io.h (__format::__no_timezone_available):
            Removed, replaced with separate throws in formatter for
            __local_time_fmt
            (__format::_ChronoParts): Defined additional enumertors and
            declared as enum class.
            (__format::operator&(_ChronoParts, _ChronoParts))
            (__format::operator&=(_ChronoParts&, _ChronoParts))
            (__format::operator-(_ChronoParts, _ChronoParts))
            (__format::operator-=(_ChronoParts&, _ChronoParts))
            (__format::operator==(_ChronoParts, decltype(nullptr)))
            (_ChronoSpec::_M_time_only, _ChronoSpec::_M_floating_point_rep)
            (_ChronoSpec::_M_custom_rep, _ChronoSpec::_M_needed)
            (_ChronoSpec::_M_needs, __format::_ChronoData): Define.
            (__format::__formatter_chrono): Redefine to accept _ChronoData.
            (__formatter_chrono::_M_format_to_ostream): Moved to
            __formatter_duration.
            (__format::__formatter_duration): Define.
            (__formatter_chrono_info::format): Pass value-constructed
            _ChronoData.
            (std::formatter<chrono::day, _CharT>)
            (std::formatter<chrono::month, _CharT>)
            (std::formatter<chrono::year, _CharT>)
            (std::formatter<chrono::weekday, _CharT>)
            (std::formatter<chrono::weekday_indexed, _CharT>)
            (std::formatter<chrono::weekday_last, _CharT>)
            (std::formatter<chrono::month_day, _CharT>)
            (std::formatter<chrono::month_day_last, _CharT>)
            (std::formatter<chrono::month_weekday, _CharT>)
            (std::formatter<chrono::month_weekday_indexed, _CharT>)
            (std::formatter<chrono::month_weekday_last, _CharT>)
            (std::formatter<chrono::year_month, _CharT>)
            (std::formatter<chrono::year_month_day, _CharT>)
            (std::formatter<chrono::year_month_day_last, _CharT>)
            (std::formatter<chrono::year_month_weekday, _CharT>)
            (std::formatter<chrono::year_month_weekday_indexed, _CharT>)
            (std::formatter<chrono::year_month_weekday_last, _CharT>):
            Construct _ChronoData in format, and configure _M_needed in
            _ChronoSpec.
            (std::formatter<chrono::duration<_Rep, _Period>, _CharT>)
            (std::formatter<chrono::hh_mm_ss<_Duration>, _CharT>)
            (std::formatter<chrono::sys_time<_Duration>, _CharT>)
            (std::formatter<chrono::utc_time<_Duration>, _CharT>)
            (std::formatter<chrono::tai_time<_Duration>, _CharT>)
            (std::formatter<chrono::gps_time<_Duration>, _CharT>)
            (std::formatter<chrono::file_time<_Duration>, _CharT>)
            (std::formatter<chrono::local_time<_Duration>, _CharT>)
            (std::formatter<chrono::_detail::__local_time_fmt<_Duration>,
_CharT>):
            Reworked in terms of __formatter_duration and _ChronoData.
            (std::formatter<chrono::_detail::__utc_leap_second<_Duration>,
_CharT>):
            Removed.
            (_Parser<_Duration>::operator()): Adjusted for _ChronoParts
            being enum class.
            * include/std/chrono (__detail::__utc_leap_second): Removed,
            replaced with simply bumping _M_seconds in _ChronoData.
            * testsuite/std/time/format/empty_spec.cc: Updated %S integral
            ouput.

    Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
    Signed-off-by: Tomasz KamiÅski <tkami...@redhat.com>

Reply via email to