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

--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Tomasz Kaminski <[email protected]>:

https://gcc.gnu.org/g:f7cde200320e0800e4fcc5cea399e9faef50f8d4

commit r17-2060-gf7cde200320e0800e4fcc5cea399e9faef50f8d4
Author: Tomasz KamiÅski <[email protected]>
Date:   Tue Jun 30 09:46:07 2026 +0200

    libstdc++: Cascade wall-time saves in lazy expansion seeding [PR124853]

    When _M_get_sys_info seeds a Zone line by looking up the active rule
    just before info.begin, the previous code interpreted each rule in
    isolation against ri.offset() (the line's standard offset alone),
    ignoring the running save accumulated by earlier rules in the same
    year. For most zones this gives the right answer because the search
    only matters when no rule has fired yet, but for zones whose rule
    set has wall-time rules whose effective firing time depends on a
    prior rule's save it produces wrong answers.

    Canonical case: Europe/Paris around 1945.  France's rules

      R Fr 1945 o - Apr 2  2 2 M
      R Fr 1945 o - Sep 16 3 0 -

    both use plain wall time. In Paris's stdoff=1 frame, the September
    rule's at_time of 03:00 wall translates to UT Sep 16 02:00 if no
    prior save is applied, but to UT Sep 16 00:00 once the running save
    of 2h from the April rule is taken into account.  When seeding a
    sys_info whose info.begin falls between those two values, the simple
    search picks the April rule (save=2 â CEMT, total offset 3h) when
    the correct answer is the September rule (save=0 â CET, total offset
    1h). libstdc++ reports this as a sustained CEMT stretch where zic
    and libc agree on CET.

    To address above the finding algorithm, is now expanded to collect
    three rule transitions around specified time t, while continuing to
    ignore the save.
    * curr_tran: transition happening before or at time t,
    * prev_tran: transition preceding above transition,
    * next_tran: transition happening after time t.

    This collects sufficient information to adjust the start_time (if
    Wall time is used) for curr_tran (save of prev_tran) and next_tran
    (save of curr_tran). Assuming that applying save value does not
    change order of transition (cascading save would be ill-defined
    otherwise), after the adjustment the actual active rule is:
     * next_tran.rule: if the adjustment pushed next_tran.when to
       time before or at t, which happen for positive save (see
       test_positive),
     * prev_tran.rule: if adjustment pushed curr_tran.when to time
       after time t, which happens for negative save (see test_negative),
     * curr_tran.rule.

    For the time at the start (Jan/1) or end of the year (December/31),
    for each rule, in addition to transition in year of t, we check
    transitions in previous or next year respectively (years in range
    [first_year, last_year]). This handle rules whose firing (specified
    in local time) crosses a year boundary due to a large stdoff or save.
    One example is Pacific/Auckland's 1946 Jan 1 rule, in stdoff=12h,
    fires at 1945-12-31 11:30 UT, see test_next_year.

    The fallback "earliest STD rule" logic is preserved for the case
    where no rule has fired yet, but is extracted to separate function.
    This lookup is optimized, by searching the rules by name, from, and
    save in that order, grouping std rules in given year together.

            PR libstdc++/124853

    libstdc++-v3/ChangeLog:

            * src/c++20/tzdb.cc
            (time_zone::_M_get_sys_info): Extract code blocks to
            separate functions, and invoke them.
            (<unnamed>::find_active_rule): Modify algorithm to
            handle cascading saves.
            (<unnamed>::find_first_std): Simplified implementation
            benefiting from reordering of rules.
            (chrono::reload_tzdb): Sort rules by name, from and save.
            * testsuite/std/time/time_zone/wall_cascade.cc: New test.

    Reviewed-by: Tomasz KamiÅski <[email protected]>
    Co-authored-by: Álvaro Begué <[email protected]>
    Signed-off-by: Tomasz KamiÅski <[email protected]>
    Signed-off-by: Álvaro Begué <[email protected]>

Reply via email to