On Tue, Apr 1, 2025 at 2:46 PM Jonathan Wakely <jwak...@redhat.com> wrote:
> On Tue, 1 Apr 2025 at 11:34, Tomasz Kaminski <tkami...@redhat.com> wrote: > > > > > > > > On Mon, Mar 31, 2025 at 7:28 PM Jonathan Wakely <jwak...@redhat.com> > wrote: > >> > >> In r15-8491-g778c28c70f8573 I added a use of the Autoconf macro > >> AC_STRUCT_TIMEZONE, but that requires a link-test for the global tzname > >> object if tm.tm_zone isn't supported. That link-test isn't allowed for > >> cross-compilation, so bootstrap fails if tm.tm_zone isn't supported. > >> > >> Since libstdc++ only cares about tm.tm_zone and won't use tzname anyway, > >> we don't need the link-test. Replace AC_STRUCT_TIMEZONE with a custom > >> macro that only checks for tm.tm_zone. We can improve on the Autoconf > >> macro by checking it's a suitable type, which isn't actually checked by > >> AC_STRUCT_TIMEZONE. > >> > >> libstdc++-v3/ChangeLog: > >> > >> PR libstdc++/119550 > >> * acinclude.m4 (GLIBCXX_STRUCT_TM_TM_ZONE): New macro. > >> * config.h.in: Regenerate. > >> * configure: Regenerate. > >> * configure.ac: Use GLIBCXX_STRUCT_TM_TM_ZONE. > >> * include/bits/chrono_io.h (__formatter_chrono::_M_c): Check > >> _GLIBCXX_USE_STRUCT_TM_TM_ZONE instead of > >> _GLIBCXX_HAVE_STRUCT_TM_TM_ZONE. > >> --- > >> > >> Testing x86_64-linux and sparc-solaris2.11, looks fine so far. > >> > >> libstdc++-v3/acinclude.m4 | 35 ++++ > >> libstdc++-v3/config.h.in | 21 +-- > >> libstdc++-v3/configure | 238 ++++++++------------------ > >> libstdc++-v3/configure.ac | 5 +- > >> libstdc++-v3/include/bits/chrono_io.h | 2 +- > >> 5 files changed, 109 insertions(+), 192 deletions(-) > >> > >> diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 > >> index e668d2dba27..02fd349e11d 100644 > >> --- a/libstdc++-v3/acinclude.m4 > >> +++ b/libstdc++-v3/acinclude.m4 > >> @@ -5744,6 +5744,41 @@ AC_DEFUN([GLIBCXX_ZONEINFO_DIR], [ > >> fi > >> ]) > >> > >> +dnl > >> +dnl Check for a tm_zone member in struct tm. > >> +dnl > >> +dnl This member is defined as const char* in Glibc, newlib, > POSIX.1-2024, > >> +dnl and as char* in BSD (including macOS). > >> +dnl > >> +dnl Defines: > >> +dnl _GLIBCXX_USE_STRUCT_TM_TM_ZONE if struct tm has a tm_zone member. > >> +dnl > >> +AC_DEFUN([GLIBCXX_STRUCT_TM_TM_ZONE], [ > >> + > >> + AC_LANG_SAVE > > > > From documentation this is deprecated in favor of AC_LANG_PUSH. > > It looks like that is supported by autoconf 2.69 and is already used > elsewhere in GCC. We don't currently use it in libstdc++ but it should > be safe to do so. > > >> + AC_LANG_CPLUSPLUS > >> + ac_save_CXXFLAGS="$CXXFLAGS" > >> + CXXFLAGS="$CXXFLAGS -std=c++20" > > > > The program that is compiled does not seem to require C++20. > > If we change the declaration of "t" to use "= {}", we could do it in > C++98. > > Any reason to adjust the flags at all? > > We only need to use the tm_zone member in C++20 mode, and it's > possible that on some platform it's not exposed for older standards > (very unlikely, but possible). I wanted to test for exactly what we > require. I don't feel strongly about it though. > I would found it surprising if the layout of the structure would fiffer that much, wouldn't this cause ABI compatibility problems for TU that memcopies struct tm and are compiled with different language versions? I have slight preference towards not overriding CXXFLAGS, as for me this suggest that struct tm was changed in C++20 (or linked C standard), which is not the case. But I am fine either way. > > >> > >> + > >> + AC_CACHE_CHECK([for tm_zone member of struct tm], > glibcxx_cv_tm_zone, [ > >> + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <time.h> > >> + ], > >> + [struct tm t{}; t.tm_zone = (char*)0;] > >> + )], > >> + [glibcxx_cv_tm_zone=yes], > >> + [glibcxx_cv_tm_zone=no] > >> + ) > >> + ]) > >> + > >> + if test $glibcxx_cv_tm_zone = yes; then > >> + AC_DEFINE(_GLIBCXX_USE_STRUCT_TM_TM_ZONE, 1, > >> + [Define if struct tm has a tm_zone member.]) > >> + fi > >> + > >> + CXXFLAGS="$ac_save_CXXFLAGS" > >> + AC_LANG_RESTORE > >> +]) > >> + > >> dnl > >> dnl Check whether lock tables can be aligned to avoid false sharing. > >> dnl > >> diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in > >> index be151f43dd6..77bbaf1beaa 100644 > >> --- a/libstdc++-v3/config.h.in > >> +++ b/libstdc++-v3/config.h.in > >> @@ -74,10 +74,6 @@ > >> don't. */ > >> #undef HAVE_DECL_STRNLEN > >> > >> -/* Define to 1 if you have the declaration of `tzname', and to 0 if > you don't. > >> - */ > >> -#undef HAVE_DECL_TZNAME > >> - > >> /* Define to 1 if you have the <dirent.h> header file. */ > >> #undef HAVE_DIRENT_H > >> > >> @@ -412,9 +408,6 @@ > >> /* Define to 1 if `d_type' is a member of `struct dirent'. */ > >> #undef HAVE_STRUCT_DIRENT_D_TYPE > >> > >> -/* Define to 1 if `tm_zone' is a member of `struct tm'. */ > >> -#undef HAVE_STRUCT_TM_TM_ZONE > >> - > >> /* Define if strxfrm_l is available in <string.h>. */ > >> #undef HAVE_STRXFRM_L > >> > >> @@ -506,17 +499,9 @@ > >> /* Define to 1 if the target supports thread-local storage. */ > >> #undef HAVE_TLS > >> > >> -/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use > >> - `HAVE_STRUCT_TM_TM_ZONE' instead. */ > >> -#undef HAVE_TM_ZONE > >> - > >> /* Define if truncate is available in <unistd.h>. */ > >> #undef HAVE_TRUNCATE > >> > >> -/* Define to 1 if you don't have `tm_zone' but do have the external > array > >> - `tzname'. */ > >> -#undef HAVE_TZNAME > >> - > >> /* Define to 1 if you have the <uchar.h> header file. */ > >> #undef HAVE_UCHAR_H > >> > >> @@ -605,9 +590,6 @@ > >> /* Define to 1 if you have the ANSI C header files. */ > >> #undef STDC_HEADERS > >> > >> -/* Define to 1 if your <sys/time.h> declares `struct tm'. */ > >> -#undef TM_IN_SYS_TIME > >> - > >> /* Version number of package */ > >> #undef VERSION > >> > >> @@ -906,6 +888,9 @@ > >> /* Define to restrict std::__basic_file<> to stdio APIs. */ > >> #undef _GLIBCXX_USE_STDIO_PURE > >> > >> +/* Define if struct tm has a tm_zone member. */ > >> +#undef _GLIBCXX_USE_STRUCT_TM_TM_ZONE > >> + > >> /* Define if struct stat has timespec members. */ > >> #undef _GLIBCXX_USE_ST_MTIM > >> > >> diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure > >> index 67d2b8c7b72..56d0bcb297e 100755 > >> --- a/libstdc++-v3/configure > >> +++ b/libstdc++-v3/configure > >> @@ -2731,63 +2731,6 @@ $as_echo "$ac_res" >&6; } > >> eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno > >> > >> } # ac_fn_c_check_decl > >> - > >> -# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES > >> -# ---------------------------------------------------- > >> -# Tries to find if the field MEMBER exists in type AGGR, after > including > >> -# INCLUDES, setting cache variable VAR accordingly. > >> -ac_fn_c_check_member () > >> -{ > >> - as_lineno=${as_lineno-"$1"} > as_lineno_stack=as_lineno_stack=$as_lineno_stack > >> - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 > >> -$as_echo_n "checking for $2.$3... " >&6; } > >> -if eval \${$4+:} false; then : > >> - $as_echo_n "(cached) " >&6 > >> -else > >> - cat confdefs.h - <<_ACEOF >conftest.$ac_ext > >> -/* end confdefs.h. */ > >> -$5 > >> -int > >> -main () > >> -{ > >> -static $2 ac_aggr; > >> -if (ac_aggr.$3) > >> -return 0; > >> - ; > >> - return 0; > >> -} > >> -_ACEOF > >> -if ac_fn_c_try_compile "$LINENO"; then : > >> - eval "$4=yes" > >> -else > >> - cat confdefs.h - <<_ACEOF >conftest.$ac_ext > >> -/* end confdefs.h. */ > >> -$5 > >> -int > >> -main () > >> -{ > >> -static $2 ac_aggr; > >> -if (sizeof ac_aggr.$3) > >> -return 0; > >> - ; > >> - return 0; > >> -} > >> -_ACEOF > >> -if ac_fn_c_try_compile "$LINENO"; then : > >> - eval "$4=yes" > >> -else > >> - eval "$4=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 > >> -eval ac_res=\$$4 > >> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: > $ac_res" >&5 > >> -$as_echo "$ac_res" >&6; } > >> - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno > >> - > >> -} # ac_fn_c_check_member > >> cat >config.log <<_ACEOF > >> This file contains any messages produced by compilers while > >> running configure, to aid debugging if configure makes a mistake. > >> @@ -12337,7 +12280,7 @@ else > >> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 > >> lt_status=$lt_dlunknown > >> cat > conftest.$ac_ext <<_LT_EOF > >> -#line 12340 "configure" > >> +#line 12283 "configure" > >> #include "confdefs.h" > >> > >> #if HAVE_DLFCN_H > >> @@ -12443,7 +12386,7 @@ else > >> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 > >> lt_status=$lt_dlunknown > >> cat > conftest.$ac_ext <<_LT_EOF > >> -#line 12446 "configure" > >> +#line 12389 "configure" > >> #include "confdefs.h" > >> > >> #if HAVE_DLFCN_H > >> @@ -16239,7 +16182,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } > >> # Fake what AC_TRY_COMPILE does. > >> > >> cat > conftest.$ac_ext << EOF > >> -#line 16242 "configure" > >> +#line 16185 "configure" > >> int main() > >> { > >> typedef bool atomic_type; > >> @@ -16274,7 +16217,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } > >> rm -f conftest* > >> > >> cat > conftest.$ac_ext << EOF > >> -#line 16277 "configure" > >> +#line 16220 "configure" > >> int main() > >> { > >> typedef short atomic_type; > >> @@ -16309,7 +16252,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } > >> rm -f conftest* > >> > >> cat > conftest.$ac_ext << EOF > >> -#line 16312 "configure" > >> +#line 16255 "configure" > >> int main() > >> { > >> // NB: _Atomic_word not necessarily int. > >> @@ -16345,7 +16288,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } > >> rm -f conftest* > >> > >> cat > conftest.$ac_ext << EOF > >> -#line 16348 "configure" > >> +#line 16291 "configure" > >> int main() > >> { > >> typedef long long atomic_type; > >> @@ -16501,7 +16444,7 @@ $as_echo "mutex" >&6; } > >> # unnecessary for this test. > >> > >> cat > conftest.$ac_ext << EOF > >> -#line 16504 "configure" > >> +#line 16447 "configure" > >> int main() > >> { > >> _Decimal32 d1; > >> @@ -16543,7 +16486,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > >> # unnecessary for this test. > >> > >> cat > conftest.$ac_ext << EOF > >> -#line 16546 "configure" > >> +#line 16489 "configure" > >> template<typename T1, typename T2> > >> struct same > >> { typedef T2 type; }; > >> @@ -54482,6 +54425,65 @@ _ACEOF > >> fi > >> > >> > >> +# For std::chrono formatters to use tm::tm_zone > >> + > >> + > >> + > >> + ac_ext=cpp > >> +ac_cpp='$CXXCPP $CPPFLAGS' > >> +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' > >> +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS > conftest.$ac_ext $LIBS >&5' > >> +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu > >> + > >> + ac_save_CXXFLAGS="$CXXFLAGS" > >> + CXXFLAGS="$CXXFLAGS -std=c++20" > >> + > >> + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tm_zone member > of struct tm" >&5 > >> +$as_echo_n "checking for tm_zone member of struct tm... " >&6; } > >> +if ${glibcxx_cv_tm_zone+:} false; then : > >> + $as_echo_n "(cached) " >&6 > >> +else > >> + > >> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext > >> +/* end confdefs.h. */ > >> +#include <time.h> > >> + > >> +int > >> +main () > >> +{ > >> +struct tm t{}; t.tm_zone = (char*)0; > >> + > >> + ; > >> + return 0; > >> +} > >> +_ACEOF > >> +if ac_fn_cxx_try_compile "$LINENO"; then : > >> + glibcxx_cv_tm_zone=yes > >> +else > >> + glibcxx_cv_tm_zone=no > >> + > >> +fi > >> +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext > >> + > >> +fi > >> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_tm_zone" > >&5 > >> +$as_echo "$glibcxx_cv_tm_zone" >&6; } > >> + > >> + if test $glibcxx_cv_tm_zone = yes; then > >> + > >> +$as_echo "#define _GLIBCXX_USE_STRUCT_TM_TM_ZONE 1" >>confdefs.h > >> + > >> + fi > >> + > >> + CXXFLAGS="$ac_save_CXXFLAGS" > >> + ac_ext=c > >> +ac_cpp='$CPP $CPPFLAGS' > >> +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' > >> +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS > conftest.$ac_ext $LIBS >&5' > >> +ac_compiler_gnu=$ac_cv_c_compiler_gnu > >> + > >> + > >> + > >> # For src/c++11/shared_ptr.cc alignment. > >> > >> > >> @@ -54697,112 +54699,6 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu > >> > >> > >> > >> -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is > in sys/time.h or time.h" >&5 > >> -$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " > >&6; } > >> -if ${ac_cv_struct_tm+:} false; then : > >> - $as_echo_n "(cached) " >&6 > >> -else > >> - cat confdefs.h - <<_ACEOF >conftest.$ac_ext > >> -/* end confdefs.h. */ > >> -#include <sys/types.h> > >> -#include <time.h> > >> - > >> -int > >> -main () > >> -{ > >> -struct tm tm; > >> - int *p = &tm.tm_sec; > >> - return !p; > >> - ; > >> - return 0; > >> -} > >> -_ACEOF > >> -if ac_fn_c_try_compile "$LINENO"; then : > >> - ac_cv_struct_tm=time.h > >> -else > >> - ac_cv_struct_tm=sys/time.h > >> -fi > >> -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext > >> -fi > >> -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 > >> -$as_echo "$ac_cv_struct_tm" >&6; } > >> -if test $ac_cv_struct_tm = sys/time.h; then > >> - > >> -$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h > >> - > >> -fi > >> - > >> -ac_fn_c_check_member "$LINENO" "struct tm" "tm_zone" > "ac_cv_member_struct_tm_tm_zone" "#include <sys/types.h> > >> -#include <$ac_cv_struct_tm> > >> - > >> -" > >> -if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then : > >> - > >> -cat >>confdefs.h <<_ACEOF > >> -#define HAVE_STRUCT_TM_TM_ZONE 1 > >> -_ACEOF > >> - > >> - > >> -fi > >> - > >> -if test "$ac_cv_member_struct_tm_tm_zone" = yes; then > >> - > >> -$as_echo "#define HAVE_TM_ZONE 1" >>confdefs.h > >> - > >> -else > >> - ac_fn_c_check_decl "$LINENO" "tzname" "ac_cv_have_decl_tzname" > "#include <time.h> > >> -" > >> -if test "x$ac_cv_have_decl_tzname" = xyes; then : > >> - ac_have_decl=1 > >> -else > >> - ac_have_decl=0 > >> -fi > >> - > >> -cat >>confdefs.h <<_ACEOF > >> -#define HAVE_DECL_TZNAME $ac_have_decl > >> -_ACEOF > >> - > >> - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tzname" >&5 > >> -$as_echo_n "checking for tzname... " >&6; } > >> -if ${ac_cv_var_tzname+:} false; then : > >> - $as_echo_n "(cached) " >&6 > >> -else > >> - if test x$gcc_no_link = xyes; then > >> - as_fn_error $? "Link tests are not allowed after > GCC_NO_EXECUTABLES." "$LINENO" 5 > >> -fi > >> -cat confdefs.h - <<_ACEOF >conftest.$ac_ext > >> -/* end confdefs.h. */ > >> -#include <time.h> > >> -#if !HAVE_DECL_TZNAME > >> -extern char *tzname[]; > >> -#endif > >> - > >> -int > >> -main () > >> -{ > >> -return tzname[0][0]; > >> - ; > >> - return 0; > >> -} > >> -_ACEOF > >> -if ac_fn_c_try_link "$LINENO"; then : > >> - ac_cv_var_tzname=yes > >> -else > >> - ac_cv_var_tzname=no > >> -fi > >> -rm -f core conftest.err conftest.$ac_objext \ > >> - conftest$ac_exeext conftest.$ac_ext > >> -fi > >> -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_var_tzname" >&5 > >> -$as_echo "$ac_cv_var_tzname" >&6; } > >> - if test $ac_cv_var_tzname = yes; then > >> - > >> -$as_echo "#define HAVE_TZNAME 1" >>confdefs.h > >> - > >> - fi > >> -fi > >> - > >> - > >> # Define documentation rules conditionally. > >> > >> # See if makeinfo has been installed and is modern enough > >> diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac > >> index fe0cdde1f7a..a6c01b29e94 100644 > >> --- a/libstdc++-v3/configure.ac > >> +++ b/libstdc++-v3/configure.ac > >> @@ -572,6 +572,9 @@ GLIBCXX_EMERGENCY_EH_ALLOC > >> # For src/c++20/tzdb.cc defaults. > >> GLIBCXX_ZONEINFO_DIR > >> > >> +# For std::chrono formatters to use tm::tm_zone > >> +GLIBCXX_STRUCT_TM_TM_ZONE > >> + > >> # For src/c++11/shared_ptr.cc alignment. > >> GLIBCXX_CHECK_ALIGNAS_CACHELINE > >> > >> @@ -584,8 +587,6 @@ GLIBCXX_CHECK_FILEBUF_NATIVE_HANDLES > >> # For std::text_encoding > >> GLIBCXX_CHECK_TEXT_ENCODING > >> > >> -AC_STRUCT_TIMEZONE > >> - > >> # Define documentation rules conditionally. > >> > >> # See if makeinfo has been installed and is modern enough > >> diff --git a/libstdc++-v3/include/bits/chrono_io.h > b/libstdc++-v3/include/bits/chrono_io.h > >> index 3a5bc5695fb..d8721093706 100644 > >> --- a/libstdc++-v3/include/bits/chrono_io.h > >> +++ b/libstdc++-v3/include/bits/chrono_io.h > >> @@ -905,7 +905,7 @@ namespace __format > >> // time zone info available for the time in __tm. > >> __tm.tm_isdst = -1; > >> > >> -#ifdef _GLIBCXX_HAVE_STRUCT_TM_TM_ZONE > >> +#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE > >> // POSIX.1-2024 adds tm.tm_zone which will be used for %Z. > >> // BSD has had tm_zone since 1987 but as char* so cast away > const. > >> if constexpr (__is_time_point_v<_Tp>) > >> -- > >> 2.49.0 > >> > >