PR114895 reports that on 32-bit glibc targets with 32-bit time_t, stat()
fails with EOVERFLOW once file timestamps are past 2038-01-19.
The LIBGFOR_CHECK_WORKING_STAT configure test then fails, HAVE_WORKING_STAT
is left undefined, and the build of io/unix.c breaks, since the
!HAVE_WORKING_STAT code path there is only usable on MinGW.
This can be reproduced e.g. by building the 32-bit multilib in a VM whose
clock is set past 2038.
Fix this by building libgfortran with 64-bit time_t where the C library
supports it as requested by PR103886. A new LIBGFOR_CHECK_TIME_BITS64
check, run right after AC_SYS_LARGEFILE, tests whether time_t is already
64 bits wide and, if not, whether defining _TIME_BITS to 64 makes it so;
in that case _TIME_BITS is defined to 64 in config.h. glibc only accepts
_TIME_BITS=64 together with _FILE_OFFSET_BITS=64, so the check relies on
the _FILE_OFFSET_BITS setting from AC_SYS_LARGEFILE and does nothing
when configured with --disable-largefile.
No exported libgfortran interface uses time_t, struct stat or other
time-related C types; the time_t uses are all in internal helpers, so
the library ABI does not change. Note that intrinsics returning or
taking default-kind INTEGER values (e.g. TIME, or STAT with an INTEGER(4)
array) still truncate to 32 bits; this change only makes the internal
handling and the 64-bit variants correct past 2038.
Bootstrap and regtest running on x86_64-unknown-linux-gnu. I'll see
to also somehow test a native i?86 build (the x86_64 32bit multilib
exercises it though). Given the toplevel configure.ac --disable-year2038
and it's comments I've opted for selectively enabling libgfortran since
it is one of the target libraries which suffers from issues but switching
has no effects on its ABI (and it has that build failure recorded in
PR114895). Also PR114065 reports Ada will fail to build with
-D_TIME_BITS=64 ...
OK for trunk?
Thanks,
Richard.
PR libfortran/103886
PR libfortran/114895
libgfortran/
* acinclude.m4 (LIBGFOR_CHECK_TIME_BITS64): New check for
64-bit time_t support.
* configure.ac: Invoke LIBGFOR_CHECK_TIME_BITS64.
* configure: Regenerate.
* config.h.in: Regenerate.
---
libgfortran/acinclude.m4 | 25 ++++++++++++++++
libgfortran/config.h.in | 3 ++
libgfortran/configure | 62 ++++++++++++++++++++++++++++++++++++++++
libgfortran/configure.ac | 1 +
4 files changed, 91 insertions(+)
diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4
index 118bed2b41b..890516a6aed 100644
--- a/libgfortran/acinclude.m4
+++ b/libgfortran/acinclude.m4
@@ -178,6 +178,31 @@ if test x"$libgfor_cv_have_crlf" = xyes; then
AC_DEFINE(HAVE_CRLF, 1, [Define if CRLF is line terminator.])
fi])
+dnl Check for 64-bit time_t support on 32-bit platforms (Y2038 safety).
+dnl glibc only accepts _TIME_BITS=64 together with _FILE_OFFSET_BITS=64,
+dnl so rely on AC_SYS_LARGEFILE having put the latter into confdefs.h;
+dnl with --disable-largefile the probe fails and _TIME_BITS is not set.
+AC_DEFUN([LIBGFOR_CHECK_TIME_BITS64], [
+ AC_REQUIRE([AC_SYS_LARGEFILE])
+ AC_CACHE_CHECK([for 64-bit time_t], [libgfor_cv_time_bits64], [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <time.h>
+#include <sys/types.h>
+int verify_y2038[(sizeof (time_t) >= 8) ? 1 : -1];
+]])], [libgfor_cv_time_bits64="already 64-bit"], [
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#define _TIME_BITS 64
+#include <time.h>
+#include <sys/types.h>
+int verify_y2038[(sizeof (time_t) >= 8) ? 1 : -1];
+]])], [libgfor_cv_time_bits64="yes"], [libgfor_cv_time_bits64="no"])
+ ])
+ ])
+ if test "x$libgfor_cv_time_bits64" = xyes; then
+ AC_DEFINE([_TIME_BITS], [64], [Define to 64 to enable 64-bit time_t on
32-bit systems.])
+ fi
+])
+
dnl Check whether the st_ino and st_dev stat fields taken together uniquely
dnl identify the file within the system. This is should be true for POSIX
dnl systems; it is known to be false on mingw32.
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 1d4bbfbb4a9..7a57b9a6208 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -1266,6 +1266,9 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
+/* Define to 64 to enable 64-bit time_t on 32-bit systems. */
+#undef _TIME_BITS
+
/* Define to the type of a signed integer type wide enough to hold a pointer,
if such a type exists, and if the system does not define it. */
#undef intptr_t
diff --git a/libgfortran/configure b/libgfortran/configure
index c7d2c6666bf..6aeba503714 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -16987,6 +16987,68 @@ rm -rf conftest*
fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5
+$as_echo_n "checking for 64-bit time_t... " >&6; }
+if ${libgfor_cv_time_bits64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <time.h>
+#include <sys/types.h>
+int verify_y2038[(sizeof (time_t) >= 8) ? 1 : -1];
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libgfor_cv_time_bits64="already 64-bit"
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define _TIME_BITS 64
+#include <time.h>
+#include <sys/types.h>
+int verify_y2038[(sizeof (time_t) >= 8) ? 1 : -1];
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libgfor_cv_time_bits64="yes"
+else
+ libgfor_cv_time_bits64="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgfor_cv_time_bits64" >&5
+$as_echo "$libgfor_cv_time_bits64" >&6; }
+ if test "x$libgfor_cv_time_bits64" = xyes; then
+
+$as_echo "#define _TIME_BITS 64" >>confdefs.h
+
+ fi
+
+
# Types
ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
if test "x$ac_cv_type_off_t" = xyes; then :
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index c50112df91c..95d986f1308 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -287,6 +287,7 @@ AC_SUBST(extra_ldflags_libgfortran)
LIBGFOR_WORKING_GFORTRAN
AC_SYS_LARGEFILE
+LIBGFOR_CHECK_TIME_BITS64
# Types
AC_TYPE_OFF_T
base-commit: ada5b8f08739b26bf76558c9d5157cbbdd16c205
prerequisite-patch-id: e52d299db98b0892f974152cd9fa5f6859fec5b7
prerequisite-patch-id: 39da6ec3264bae454fa504f127cd5b80a0662f04
prerequisite-patch-id: 6d6c263a964425334ad8c2edd4dd89dcbff44bfe
prerequisite-patch-id: 9a12a1706cbdff1edf8959682cd3cf9d900cd8f1
prerequisite-patch-id: b24057443c46d6979436cce479836178b19355de
prerequisite-patch-id: d61bf2c4249ecd3d9da5eeda002d332ed3a8b4fd
prerequisite-patch-id: 59cbeca60f782f48f945bc532c2235a50de6f0e5
prerequisite-patch-id: 8eddd3172e2007d0fc591124a56b372dfe83e683
prerequisite-patch-id: 862842dd3742066d039f66ffe9528bc490308c50
prerequisite-patch-id: e413d39d9af45f25483eaf229cf883c771444fbb
prerequisite-patch-id: 2faef186ad1d816bb104d89638bc4cec6d863a46
prerequisite-patch-id: b32cceb111f4f57798e4b1d58822281e7bbaf25e
prerequisite-patch-id: 08ff1c06921c5e253d911128be3a8ebb76137d3c
prerequisite-patch-id: 72aa7ba47bd81909871a9e1a2e9de14f2cf42174
prerequisite-patch-id: 2ce10434bf0a7ab22e27ff177073e10b4b7d0d72
prerequisite-patch-id: 68776813e47d3d411bef2f4229a589711887ca6c
prerequisite-patch-id: e286b2e30887f3f43a3458c7c9b3f8c8b513a91b
prerequisite-patch-id: dc07b9957107f8b453a87ad64fd8477ae26e370c
--
2.51.0