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.*

> +  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?

> +
> +  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
>
>

Reply via email to