[gcc r16-9374] libstdc++: Fix condition for stopping lazy zone expansion [PR116110]

Tomasz Kaminski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <20260723072553.B42B14BA23D3__40091.7129636341$1784791593$gmane$org@sourceware.org>
https://gcc.gnu.org/g:63e144c9b6902d3e7694f206a49a8745ec0728cf

commit r16-9374-g63e144c9b6902d3e7694f206a49a8745ec0728cf
Author: Tomasz Kamiński <[email protected]>
Date:   Fri Jul 17 21:14:42 2026 +0200

    libstdc++: Fix condition for stopping lazy zone expansion [PR116110]
    
    At indicated by the pre-existing comment, the lazy zone expansion can be
    only resumed from STD (save == 0) zone. However, the current condition
    for stopping on DST (save != 0) doesn't ensure that, as some rule specify
    transitions between DST zones. For example August 1945 of Y rule used by
    America/Dawson only change letters:
      Y 1942 o - F 9 2 1 W
      Y 1945 o - Au 14 23u 1 P
    
    This patch correct the condition, by using next_rule (i.e. one applying
    after last expanded zone): either there is no zone (last expanded range)
    or it have save zero.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/116110
            * src/c++20/tzdb.cc (time_zone::_M_get_sys_info): Correct
            condition for stopping zone expansion before STD zone.
            * testsuite/std/time/time_zone/116110.cc (test_dawson):
            Add test for America/Dawson August 1945 transition.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>
    (cherry picked from commit 57a09e2f362ab8a8be84250fd4266b333a74b977)

Diff:
---
 libstdc++-v3/src/c++20/tzdb.cc                     |  4 +--
 .../testsuite/std/time/time_zone/116110.cc         | 41 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
index 683a9f8f7e81..a11483553031 100644
--- a/libstdc++-v3/src/c++20/tzdb.cc
+++ b/libstdc++-v3/src/c++20/tzdb.cc
@@ -1027,10 +1027,10 @@ namespace std::chrono
 	  result_index = new_infos.size() - 1;
 	else if (result_index >= 0 && !merged)
 	  {
-	    // Finish on a DST sys_info if possible, so that if we resume
+	    // Finish before a STD sys_info if possible, so that if we resume
 	    // generating sys_info objects after this time point, save=0
 	    // should be correct for the next sys_info.
-	    if (num_after > 1 || info.save != 0min)
+	    if (num_after > 1 || !next_rule || next_rule->save == 0s)
 	      --num_after;
 	  }
 
diff --git a/libstdc++-v3/testsuite/std/time/time_zone/116110.cc b/libstdc++-v3/testsuite/std/time/time_zone/116110.cc
index 26b9ba33c316..3751c5df910c 100644
--- a/libstdc++-v3/testsuite/std/time/time_zone/116110.cc
+++ b/libstdc++-v3/testsuite/std/time/time_zone/116110.cc
@@ -78,9 +78,50 @@ test_apia()
   VERIFY( info.abbrev == "+14" );
 }
 
+void
+test_dawson()
+{
+  /* 1945 August rule change changes letters (abbrev)
+     and remains in DST:
+  R Y 1942 o - F 9 2 1 W
+  R Y 1945 o - Au 14 23u 1 P
+  R Y 1945 o - S 30 2 0 S
+  Z America/Dawson -9:17:40 - LMT 1900 Au 20
+  -9 Y Y%sT 1965
+  -9 Yu Y%sT 1973 O 28
+  */
+
+  auto* tz = locate_zone("America/Dawson");
+  
+  // Triggers rule transitions from the start.
+  sys_info info = tz->get_info(sys_days(1900y/August/20) + 10h);
+  VERIFY( info.offset == -9h );
+  VERIFY( info.save == 0min );
+  VERIFY( info.abbrev == "YST" );
+
+  // Check YWT transition at 02:00 + 9h UT, that is DST
+  info = tz->get_info(sys_days(1942y/February/9) + 11h);
+  VERIFY( info.offset == -8h );
+  VERIFY( info.save == 60min );
+  VERIFY( info.abbrev == "YWT" );
+
+  // Check YPT transition at 23:00 UT, remains DST
+  info = tz->get_info(sys_days(1945y/August/14) + 23h);
+  VERIFY( info.offset == -8h );
+  VERIFY( info.save == 60min );
+  VERIFY( info.abbrev == "YPT" );
+
+  // Check YST transition at 02:00 + 8h UT, switches to STD
+  info = tz->get_info(sys_days(1945y/September/30) + 10h);
+  VERIFY( info.offset == -9h );
+  VERIFY( info.save == 0min );
+  VERIFY( info.abbrev == "YST" );
+}
+
 int main()
 {
   test_broken_hill();
   test_kiritimati();
   test_apia();
+  test_dawson();
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.