On Wed, 6 May 2026 at 17:05, Tomasz Kaminski <[email protected]> wrote: > > > > On Wed, May 6, 2026 at 5:14 PM Jonathan Wakely <[email protected]> wrote: >> >> On Wed, 6 May 2026 at 15:47, Tomasz Kaminski <[email protected]> wrote: >> > >> > >> > >> > On Wed, May 6, 2026 at 4:18 PM Jonathan Wakely <[email protected]> wrote: >> >> >> >> This change allows the hardcoded list of leap seconds in <chrono> to be >> >> used even when the program is executing after the hardcoded expiry date >> >> in that header. If the OS-provided leapseconds file has a later expiry >> >> date (or contains new leap seconds added after the one in 2017) then the >> >> new __detail::__leap_seconds_expiry() function will return that new >> >> dynamically-obtained expiry date. The __detail::__get_leap_second_info >> >> function in the header can check that new expiry date instead of relying >> >> only on the hardcoded one. >> >> >> >> This change means that in the worst case we now make two calls into the >> >> library (one to get the dynamic expiry date and then possibly another >> >> one to get the actual list of new leap seconds). Previously we just make >> >> one, to get the list. The change seems worthwhile, because it means that >> >> in more cases we don't need to increment+decrement the reference count >> >> on a tzdb object and use its leapseconds vector, we can just use the >> >> hardcoded array. >> >> >> >> The new expiry date is stored in a global variable, rather than being >> >> per-tzdb object, but that seems fine because we only ever expect that >> >> expiry date to move forwards in time, not to move forwards and backwards >> >> as new tzdb objects are loaded by chrono::reload_tzdb(). Even if a new >> >> list of leap seconds is loaded, we still expect an expiry date that was >> >> loaded previously to be valid. >> > >> > I was wondering about it in connection to the test that overrides the zone >> > directory, >> > and may move the date around. But for those already impacted by the fact >> > that >> > any date with an expiry date before one that we hardcode is ignored. >> > However, >> > for that reason, I would ensure we do not move the date backward; >> > suggestion below. >> > (In also could move backward if reading #experies fails). >> > >> >> >> >> >> >> libstdc++-v3/ChangeLog: >> >> >> >> PR libstdc++/123165 >> >> * acinclude.m4 (libtool_VERSION): Bump version. >> >> * config/abi/pre/gnu.ver (GLIBCXX_3.4.36): Add new symbol >> >> version and export new symbol. >> >> * configure: Regenerate. >> >> * include/std/chrono (__detail::__leap_seconds_expiry): >> >> Declare new function. >> >> (__detail::__get_leap_second_info): Use new function. >> >> * src/c++20/tzdb.cc (__detail::__leap_seconds_expiry): Define. >> >> (tzdb_list::_Node::_S_read_leap_seconds): Read 'expires' line >> >> from leapseconds file and optionally update global cache. >> >> * testsuite/std/time/tzdb/leap_seconds.cc: Add expires line to >> >> replacement leapseconds file. >> >> * testsuite/util/testsuite_abi.cc: Update known_versions and >> >> latestp. >> >> --- >> >> >> >> Tested x86_64-linux. >> >> >> >> >> >> libstdc++-v3/acinclude.m4 | 2 +- >> >> libstdc++-v3/config/abi/pre/gnu.ver | 7 ++ >> >> libstdc++-v3/configure | 2 +- >> >> libstdc++-v3/include/std/chrono | 9 +- >> >> libstdc++-v3/src/c++20/tzdb.cc | 88 ++++++++++++++++--- >> >> .../testsuite/std/time/tzdb/leap_seconds.cc | 1 + >> >> libstdc++-v3/testsuite/util/testsuite_abi.cc | 3 +- >> >> 7 files changed, 96 insertions(+), 16 deletions(-) >> >> >> >> diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 >> >> index 8dc9e17b214c..3a4b11a98a28 100644 >> >> --- a/libstdc++-v3/acinclude.m4 >> >> +++ b/libstdc++-v3/acinclude.m4 >> >> @@ -4085,7 +4085,7 @@ changequote([,])dnl >> >> fi >> >> >> >> # For libtool versioning info, format is CURRENT:REVISION:AGE >> >> -libtool_VERSION=6:35:0 >> >> +libtool_VERSION=6:36:0 >> >> >> >> # Everything parsed; figure out what files and settings to use. >> >> case $enable_symvers in >> >> diff --git a/libstdc++-v3/config/abi/pre/gnu.ver >> >> b/libstdc++-v3/config/abi/pre/gnu.ver >> >> index bd4da6418295..35aaf89984d1 100644 >> >> --- a/libstdc++-v3/config/abi/pre/gnu.ver >> >> +++ b/libstdc++-v3/config/abi/pre/gnu.ver >> >> @@ -2623,6 +2623,13 @@ GLIBCXX_3.4.35 { >> >> >> >> } GLIBCXX_3.4.34; >> >> >> >> +# GCC 17.1.0 >> >> +GLIBCXX_3.4.36 { >> >> + >> >> + _ZNSt6chrono8__detail21__leap_seconds_expiryEv; >> >> + >> >> +} GLIBCXX_3.4.35; >> >> + >> >> # Symbols in the support library (libsupc++) have their own tag. >> >> CXXABI_1.3 { >> >> >> >> diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure >> >> index 6713e4504b1c..013c388b9c2f 100755 >> >> --- a/libstdc++-v3/configure >> >> +++ b/libstdc++-v3/configure >> >> @@ -51418,7 +51418,7 @@ $as_echo "$as_me: WARNING: === Symbol versioning >> >> will be disabled." >&2;} >> >> fi >> >> >> >> # For libtool versioning info, format is CURRENT:REVISION:AGE >> >> -libtool_VERSION=6:35:0 >> >> +libtool_VERSION=6:36:0 >> >> >> >> # Everything parsed; figure out what files and settings to use. >> >> case $enable_symvers in >> >> diff --git a/libstdc++-v3/include/std/chrono >> >> b/libstdc++-v3/include/std/chrono >> >> index 674f867dcdc7..228293f12bef 100644 >> >> --- a/libstdc++-v3/include/std/chrono >> >> +++ b/libstdc++-v3/include/std/chrono >> >> @@ -3217,6 +3217,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> >> >> >> namespace __detail >> >> { >> >> + // The list below is known to be valid until (at least) this date. >> >> + // This value is defined in the library (possibly to a newer value >> >> than >> >> + // the hardcoded value below) and can change at runtime. >> >> + sys_seconds __leap_seconds_expiry(); >> >> + >> >> inline leap_second_info >> >> __get_leap_second_info(sys_seconds __ss, bool __is_utc) >> >> { >> >> @@ -3252,12 +3257,12 @@ namespace __detail >> >> 1435708800, // 1 Jul 2015 >> >> 1483228800, // 1 Jan 2017 >> >> }; >> >> +#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI // use chrono::tzdb >> >> // The list above is known to be valid until (at least) this date >> >> // and only contains positive leap seconds. >> >> constexpr sys_seconds __expires(1798416000s); // 2026-12-28 >> >> 00:00:00 U >> > >> > >> >> >> >> -#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI >> >> - if (__ss > __expires) >> >> + if (__ss > __expires && __ss > __leap_seconds_expiry()) >> >> { >> >> // Use updated leap_seconds from tzdb. >> >> size_t __n = std::size(__leaps); >> >> diff --git a/libstdc++-v3/src/c++20/tzdb.cc >> >> b/libstdc++-v3/src/c++20/tzdb.cc >> >> index b0fbfc46a6d3..ba0020814ba8 100644 >> >> --- a/libstdc++-v3/src/c++20/tzdb.cc >> >> +++ b/libstdc++-v3/src/c++20/tzdb.cc >> >> @@ -1251,6 +1251,40 @@ namespace std::chrono >> >> } >> >> #endif // TZDB_DISABLED >> >> >> >> +namespace >> >> +{ >> >> +#if ATOMIC_LONG_LOCK_FREE == 2 >> >> + using expiry_type = unsigned long; >> >> +#else >> >> + using expiry_type = unsigned; >> >> +#endif >> >> + // When GCC 16.1 was released with stable C++20 chrono support (in >> >> 2026), >> >> + // the last leap second in the list was the one in 2017. If another >> >> leap >> >> >> + // second is introduced in future, objects compiled by GCC 16.1 will >> >> not >> >> + // contain that leap second in the hardcoded list in <chrono>. >> >> + // This expiry time must be less than that first post-2017 leap second, >> >> + // so that old copies of __get_leap_second_info will use >> >> tzdb::leap_seconds >> >> + // which will contain the post-2017 leap seconds. >> >> + // If no new leap second is introduced, then this expiry time can just >> >> be >> >> + // updated to the 'expires' value read from the leapseconds file. >> >> + // tzdata 2026a leapseconds list expires at 2026-12-28 00:00:00 UTC >> >> + constinit std::atomic<expiry_type> >> >> leap_seconds_expiry{leap27th_expiry}; >> > >> > Could you extract the __expires from >> > tzdb_list::_Node::_S_read_leap_seconds() >> > (in this file) as the global (but TU-local) variables, and use the >> > __expires as initializer here, >> > so we do not need to update two prices. This will not add any symbols to >> > the library, as we are in source file. >> > (This is why I am not suggesting doing that in header, as we will need to >> > make the data inline). > > OK, as I understand the code, this value can be updated to one second > prior to the date of the 28th leap second, or current time, if none was > inserted. > However, the commit message does not contain the number of leap seconds know > for GCC17, > > Maybe change comment to something like this: > // When GCC 16.1 was released with stable C++20 chrono support (in 2026), > // the leap second data contained 27 entries, with the last one in 2017. > constexpr min_leap_second_count = 27; /// review: use that as magic number, > so searching for it will find this comment
Ack.
