[PATCH] libstdc++: Support _TIME_BITS=64 for system_clock::to_time_t [PR99832]
Tomasz Kaminski
tkaminsk@redhat.com
Tue Jun 3 14:24:52 GMT 2025
On Tue, Jun 3, 2025 at 3:46 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> For some 32-bit targets Glibc supports changing the size of time_t to be
> 64 bits by defining _TIME_BITS=64. That causes an ABI change which
> would affect std::chrono::system_clock::to_time_t. Because to_time_t is
> not a function template, its mangled name does not depend on the return
> type, so it has the same mangled name whether it returns a 32-bit time_t
> or a 64-bit time_t. On targets where the size of time_t can be selected
> at preprocessing time, that can cause ODR violations, e.g. the linker
> selects a definition of to_time_t that returns a 32-bit value but a
> caller expects 64-bit and so reads 32 bits of garbage from the stack.
>
> This commit adds always_inline to to_time_t when time_t has been changed
> from a 32-bit type to a 64-bit type by defining _TIME_BITS=64. This
> ensures that callers expecting a 64-bit time_t can't link to a
> definition returning a 32-bit time_t.
>
> We use the internal Glibc macro __USE_TIME64_REDIRECTS to detect the
> case where time_t defaults to 32-bit for the target but has been
> explicitly changed to 64-bit by the user.
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/99832
> * include/bits/chrono.h (system_clock::to_time_t): Add always
> inline_attribute for 64-bit time_t on 32-bit target.
> * testsuite/20_util/system_clock/time64.cc: New test.
> ---
>
> Tested x86_64-linux (-m64 and -m32, with recent glibc).
>
LGTM. Thanks for the commit message, very educating.
>
> libstdc++-v3/include/bits/chrono.h | 3 +++
> .../testsuite/20_util/system_clock/time64.cc | 21 +++++++++++++++++++
> 2 files changed, 24 insertions(+)
> create mode 100644 libstdc++-v3/testsuite/20_util/system_clock/time64.cc
>
> diff --git a/libstdc++-v3/include/bits/chrono.h
> b/libstdc++-v3/include/bits/chrono.h
> index fad216203d2f..5c6ee759b381 100644
> --- a/libstdc++-v3/include/bits/chrono.h
> +++ b/libstdc++-v3/include/bits/chrono.h
> @@ -1244,6 +1244,9 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2)
> now() noexcept;
>
> // Map to C API
> +#ifdef __USE_TIME64_REDIRECTS
> + [[__gnu__::__always_inline__]]
> +#endif
> static std::time_t
> to_time_t(const time_point& __t) noexcept
> {
> diff --git a/libstdc++-v3/testsuite/20_util/system_clock/time64.cc
> b/libstdc++-v3/testsuite/20_util/system_clock/time64.cc
> new file mode 100644
> index 000000000000..3cbf80e0f06e
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/20_util/system_clock/time64.cc
> @@ -0,0 +1,21 @@
> +// { dg-options "-D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64 -O0 -g0" }
> +// { dg-do compile { target *-*-linux-gnu } }
> +// { dg-require-effective-target c++20 }
> +// { dg-require-effective-target ilp32 }
> +// { dg-final { scan-assembler-not "system_clock9to_time_t" } }
> +
> +#include <chrono>
> +
> +template<typename T>
> +std::time_t
> +test()
> +{
> + using std::chrono::system_clock;
> +
> + if constexpr (sizeof(T) == 8)
> + return system_clock::to_time_t(system_clock::now());
> + else // _TIME_BITS=64 had no effect, maybe an old Glibc
> + return 0;
> +}
> +
> +auto t = test<std::time_t>();
> --
> 2.49.0
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250603/d9307030/attachment.htm>
More information about the Libstdc++
mailing list