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

Jonathan Wakely jwakely@redhat.com
Fri May 15 19:37:12 GMT 2026


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).


> 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
>
>



More information about the Libstdc++ mailing list