On Wed, 22 Jul 2026 at 16:10, Tomasz Kaminski <[email protected]> wrote:
>
>
>
> On Fri, May 15, 2026 at 9:37 PM Jonathan Wakely <[email protected]> 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?
OK for gcc-16
>>
>>
>>
>> > 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
>> >
>> >
>>