[PATCH] libstdc++: Use on_month_day istream operator in ZoneInfo parsing. [PR124852]

Tomasz Kaminski tkaminsk@redhat.com
Wed Jul 22 15:10:27 GMT 2026


On Fri, May 15, 2026 at 9:37 PM Jonathan Wakely <jwakely@redhat.com> wrote:

> On Wed, 13 May 2026 at 10:22 +0200, Tomasz Kamiński wrote:
> >This patch changes ZoneInfo parsing, to use operator>> for on_month_day
> >direclty, and removes on_day tag. The operator>>(istream&, on_month_day)
>
> "directly"
>
> >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
> >MONT DAY TIME.
>
> "MONTH"
>
> >
> >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 libsdc++/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 in...
> >       (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.
> >---
> >Realized this yesterday, but decied that doing this as separate patch as
> this
> >is reverting direction. If this causes some failure, I want git blame to
> >show only me for it.
> >
> >Tested on x86_64-linux locally. OK for trunk?
>
> OK for trunk with a few typos fixed (two above, two below).
>
OK for GCC 16,a As we are backporting a previous patch, this is what we
have on trunk?

>
>
> > 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 f9238542274..8db86a8d4b0 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 set
>
> "sets"
>
> >+    // failbit. If DAY is not pared, only `on.month` is modified,
>
> "parsed"
>
> >+    // 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)
> >--
> >2.54.0
> >
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260722/a0246fe5/attachment.htm>


More information about the Libstdc++ mailing list