[gcc r17-2537] libstdc++: Fix condition for stopping lazy zone expansion [PR116110]

Tomasz Kaminski via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:57a09e2f362ab8a8be84250fd4266b333a74b977

commit r17-2537-g57a09e2f362ab8a8be84250fd4266b333a74b977
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]>

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 c2a036bc2cae..43f6a0dbb846 100644
--- a/libstdc++-v3/src/c++20/tzdb.cc
+++ b/libstdc++-v3/src/c++20/tzdb.cc
@@ -1232,10 +1232,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 1ec01d359552..45daed8c0509 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.