https://gcc.gnu.org/g:2451667193e4e00b49c4ef9d95c0a3a1aa955f82

commit r17-562-g2451667193e4e00b49c4ef9d95c0a3a1aa955f82
Author: Tomasz Kamiński <[email protected]>
Date:   Wed May 13 09:17:47 2026 +0200

    libstdc++: Use on_month_day istream operator in ZoneInfo parsing. [PR124852]
    
    This patch changes ZoneInfo parsing, to use operator>> for on_month_day
    directly, and removes on_day tag. The operator>>(istream&, on_month_day)
    is updated to not override on.month if the MONTH component is not present,
    and set failbit instead. This allows to use in >> on >> time, to parse
    MONTH DAY TIME.
    
    We also handle failure to parse day number N for Www>=N or Www<=N
    productions, by leaving the day part of input unchanged and setting
    failbit.
    
            PR libstdc++/124852
    
    libstdc++-v3/ChangeLog:
    
            * src/c++20/tzdb.cc (on_month_day::on_day_t, on_month_day::on_day):
            Remove.
            (operator>>(istream&, on_month_day::day_t&)): Inlined into...
            (operator>>(istream&, on_month_day)): Inlined on_month_day::on_day.
            Avoid modifying on.month if MONTH is not present. Report failure
            on failure to parse day for LessEq / GreaterEq.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 libstdc++-v3/src/c++20/tzdb.cc | 89 ++++++++++++++----------------------------
 1 file changed, 30 insertions(+), 59 deletions(-)

diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
index f9238542274b..183a0c61a616 100644
--- a/libstdc++-v3/src/c++20/tzdb.cc
+++ b/libstdc++-v3/src/c++20/tzdb.cc
@@ -371,13 +371,6 @@ namespace std::chrono
        return ymd;
       }
 
-      struct on_day_t // tag type for reading ON and DAY fields only
-      {
-       on_month_day& parent;
-       friend istream& operator>>(istream&, on_day_t&&);
-      };
-
-      on_day_t on_day() { return on_day_t{*this}; }
 
       friend istream& operator>>(istream&, on_month_day&);
     };
@@ -2334,73 +2327,55 @@ namespace
       }
     };
 
-    // Read the day-component of an on_month_day expression (everything after
-    // the month).  Three forms are accepted: a plain day-of-month number,
-    // "lastXxx" where Xxx is a weekday name (LastWeekday), or "Xxx<=N" or
-    // "Xxx>=N" (LessEq / GreaterEq).  On failure the function sets failbit
-    // and leaves `to.parent` unchanged.
-    istream& operator>>(istream& in, on_month_day::on_day_t&& to)
+    // Read the MONTH DAY. Three forms are accepted for DAY:
+    // * a plain day-of-month number (DayOfMonth),
+    // * "lastWww" where Www is a weekday name (LastWeekday),
+    // * "Www<=N" or "Www>=N" (LessEq / GreaterEq).
+    // On failure to read either MONTH or DAY this function sets
+    // failbit. If DAY is not parsed, only `on.month` is modified,
+    // otherwise `on` is left unchanged.
+    istream& operator>>(istream& in, on_month_day& on)
     {
       using enum on_month_day::Kind;
-
-      on_month_day& on = to.parent;
-      int c = ws(in).peek();
-      if ('0' <= c && c <= '9')
+      if (abbrev_month m{}; in >> m)
        {
-         unsigned d;
-         in >> d;
-         if (d <= 31) [[likely]]
+         on.month = static_cast<unsigned>(m.m);
+         if (int c = ws(in).peek(); '0' <= c && c <= '9')
            {
-             on.kind = DayOfMonth;
-             on.day_of_month = d;
-             return in;
+             if (unsigned d; (in >> d) && (d <= 31)) [[likely]]
+               {
+                 on.kind = DayOfMonth;
+                 on.day_of_month = d;
+                 return in;
+               }
            }
-       }
-      else if (c == 'l') // lastSunday, lastWed, ...
-       {
-         in.ignore(4);
-         if (abbrev_weekday w{}; in >> w) [[likely]]
+         else if (c == 'l') // lastSunday, lastWed, ...
            {
-             on.kind = LastWeekday;
-             on.day_of_week = w.wd.c_encoding();
-             return in;
+             in.ignore(4);
+             if (abbrev_weekday w{}; in >> w) [[likely]]
+               {
+                 on.kind = LastWeekday;
+                 on.day_of_week = w.wd.c_encoding();
+                 return in;
+               }
            }
-       }
-      else
-       {
-         abbrev_weekday w;
-         in >> w;
-         if (auto c = in.get(); c == '<' || c == '>')
+         else if (abbrev_weekday w; in >> w) [[likely]]
            {
-             if (in.get() == '=')
-               {
-                 unsigned d;
-                 in >> d;
-                 if (d <= 31) [[likely]]
+             if (c = in.get(); c == '<' || c == '>')
+               if (in.get() == '=')
+                 if (unsigned d; (in >> d) && (d <= 31)) [[likely]]
                    {
                      on.kind = c == '<' ? LessEq : GreaterEq;
                      on.day_of_week = w.wd.c_encoding();
                      on.day_of_month = d;
                      return in;
                    }
-               }
            }
        }
       in.setstate(ios::failbit);
       return in;
     }
 
-    istream& operator>>(istream& in, on_month_day& to)
-    {
-      on_month_day md{};
-      abbrev_month m{};
-      in >> m;
-      md.month = static_cast<unsigned>(m.m);
-      if (in >> md.on_day())
-       to = md;
-      return in;
-    }
-
     istream& operator>>(istream& in, at_time& at)
     {
       int sign = 1;
@@ -2506,11 +2481,7 @@ namespace
          on_month_day on{ .kind = on_month_day::DayOfMonth,
                           .month = 1, .day_of_month = 1 };
          at_time t{};
-         if (abbrev_month m{January}; in >> m)
-           {
-             on.month = static_cast<unsigned>(m.m);
-             in >> on.on_day() >> t;
-           }
+         in >> on >> t;
          year_month_day ymd = on.pin(year(y));
          inf.m_until = sys_days(ymd) + seconds(t.time);
          if (t.indicator != at_time::Universal)

Reply via email to