This computes the underlying type of int64_t in a configure check and uses that for HOST_WIDE_INT. This makes sure we can use the PRI?64 macros from inttypes.h for HOST_WIDE_INT_PRINT_*, which the following patch re-instantiates.
The patch also makes sure inttypes.h defines PRId64 and if not, provides replacements in hwint.h (like previously), matching int64_t. Built on i586-linux-gnu and x86_64-linux-gnu (to verify both 'long' and 'long long' choices). A bootstrap and regtest on x86_64-unknown-linux-gnu is pending. Ok? Thanks, Richard. 2014-06-02 Richard Biener <rguent...@suse.de> * configure.ac: Check whether the underlying type of int64_t is long or long long. * configure: Regenerate. * config.in: Likewise. * hwint.h (HOST_WIDE_INT): Match the underlying type of int64_t. (HOST_WIDE_INT_PRINT_*): Define in terms of PRI*64. Index: gcc/configure.ac =================================================================== *** gcc/configure.ac (revision 211125) --- gcc/configure.ac (working copy) *************** if test x"$ac_cv_c_uint64_t" = x"no" -o *** 316,321 **** --- 316,350 ---- AC_MSG_ERROR([uint64_t or int64_t not found]) fi + # check what underlying integer type int64_t uses + AC_LANG_PUSH(C++) + AC_CACHE_CHECK(for int64_t underlying type, ac_cv_int64_t_type, [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #ifdef HAVE_STDINT_H + #include <stdint.h> + #endif + template <typename T> struct X { }; + template <> + struct X<long> { typedef long t; }; + ]], [[typename X<int64_t>::t x;]])],[ac_cv_int64_t_type=long],[ac_cv_int64_t_type="long long"])]) + if test x$ac_cv_int64_t_type = xlong; then + AC_DEFINE(INT64_T_IS_LONG, 1, + [Define if int64_t uses long as underlying type.]) + else + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #ifdef HAVE_STDINT_H + #include <stdint.h> + #endif + template <typename T> struct X { }; + template <> + struct X<long long> { typedef long long t; }; + ]], [[typename X<int64_t>::t x;]])],[],[AC_MSG_ERROR([error verifying int64_t uses long long])]) + fi + AC_LANG_POP(C++) + + + + # --------------------- # Warnings and checking # --------------------- *************** LIBS="$save_LIBS" *** 1055,1067 **** AC_SUBST(LDEXP_LIB) # Use <inttypes.h> only if it exists, ! # doesn't clash with <sys/types.h>, and declares intmax_t. AC_MSG_CHECKING(for inttypes.h) AC_CACHE_VAL(gcc_cv_header_inttypes_h, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM( ! [[#include <sys/types.h> #include <inttypes.h>]], ! [[intmax_t i = -1;]])], [gcc_cv_header_inttypes_h=yes], [gcc_cv_header_inttypes_h=no])]) AC_MSG_RESULT($gcc_cv_header_inttypes_h) --- 1084,1101 ---- AC_SUBST(LDEXP_LIB) # Use <inttypes.h> only if it exists, ! # doesn't clash with <sys/types.h>, declares intmax_t and defines ! # PRId64 AC_MSG_CHECKING(for inttypes.h) AC_CACHE_VAL(gcc_cv_header_inttypes_h, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM( ! [[#define __STDC_FORMAT_MACROS ! #include <sys/types.h> #include <inttypes.h>]], ! [[intmax_t i = -1; ! #ifndef PRId64 ! choke me ! #endif]])], [gcc_cv_header_inttypes_h=yes], [gcc_cv_header_inttypes_h=no])]) AC_MSG_RESULT($gcc_cv_header_inttypes_h) Index: gcc/hwint.h =================================================================== *** gcc/hwint.h (revision 211125) --- gcc/hwint.h (working copy) *************** extern char sizeof_long_long_must_be_8[s *** 46,58 **** #endif /* Set HOST_WIDE_INT, this should be always 64 bits. ! ! With a sane ABI, 'long' is the largest efficient host integer type. ! Thus, we use that unless we have to use 'long long' ! because we're on a 32-bit host. */ #define HOST_BITS_PER_WIDE_INT 64 ! #if HOST_BITS_PER_LONG == 64 # define HOST_WIDE_INT long # define HOST_WIDE_INT_C(X) X ## L #else --- 46,56 ---- #endif /* Set HOST_WIDE_INT, this should be always 64 bits. ! The underlying type is matched to that of int64_t and assumed ! to be either long or long long. */ #define HOST_BITS_PER_WIDE_INT 64 ! #if INT64_T_IS_LONG # define HOST_WIDE_INT long # define HOST_WIDE_INT_C(X) X ## L #else *************** extern char sizeof_long_long_must_be_8[s *** 75,122 **** typedef before using the __asm_fprintf__ format attribute. */ typedef HOST_WIDE_INT __gcc_host_wide_int__; - /* Various printf format strings for HOST_WIDE_INT. */ - - #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG - # define HOST_WIDE_INT_PRINT HOST_LONG_FORMAT - # define HOST_WIDE_INT_PRINT_C "L" - /* HOST_BITS_PER_WIDE_INT is 64 bits. */ - # define HOST_WIDE_INT_PRINT_DOUBLE_HEX \ - "0x%" HOST_LONG_FORMAT "x%016" HOST_LONG_FORMAT "x" - # define HOST_WIDE_INT_PRINT_PADDED_HEX \ - "%016" HOST_LONG_FORMAT "x" - #else - # define HOST_WIDE_INT_PRINT HOST_LONG_LONG_FORMAT - # define HOST_WIDE_INT_PRINT_C "LL" - /* HOST_BITS_PER_WIDE_INT is 64 bits. */ - # define HOST_WIDE_INT_PRINT_DOUBLE_HEX \ - "0x%" HOST_LONG_LONG_FORMAT "x%016" HOST_LONG_LONG_FORMAT "x" - # define HOST_WIDE_INT_PRINT_PADDED_HEX \ - "%016" HOST_LONG_LONG_FORMAT "x" - #endif /* HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG */ - - #define HOST_WIDE_INT_PRINT_DEC "%" HOST_WIDE_INT_PRINT "d" - #define HOST_WIDE_INT_PRINT_DEC_C HOST_WIDE_INT_PRINT_DEC HOST_WIDE_INT_PRINT_C - #define HOST_WIDE_INT_PRINT_UNSIGNED "%" HOST_WIDE_INT_PRINT "u" - #define HOST_WIDE_INT_PRINT_HEX "%#" HOST_WIDE_INT_PRINT "x" - #define HOST_WIDE_INT_PRINT_HEX_PURE "%" HOST_WIDE_INT_PRINT "x" - /* Provide C99 <inttypes.h> style format definitions for 64bits. */ #ifndef HAVE_INTTYPES_H #undef PRId64 ! #define PRId64 HOST_WIDE_INT_PRINT "d" #undef PRIi64 ! #define PRIi64 HOST_WIDE_INT_PRINT "i" #undef PRIo64 ! #define PRIo64 HOST_WIDE_INT_PRINT "o" #undef PRIu64 ! #define PRIu64 HOST_WIDE_INT_PRINT "u" #undef PRIx64 ! #define PRIx64 HOST_WIDE_INT_PRINT "x" #undef PRIX64 ! #define PRIX64 HOST_WIDE_INT_PRINT "X" #endif /* Define HOST_WIDEST_FAST_INT to the widest integer type supported efficiently in hardware. (That is, the widest integer type that fits in a hardware register.) Normally this is "long" but on some hosts it --- 73,117 ---- typedef before using the __asm_fprintf__ format attribute. */ typedef HOST_WIDE_INT __gcc_host_wide_int__; /* Provide C99 <inttypes.h> style format definitions for 64bits. */ #ifndef HAVE_INTTYPES_H + #if INT64_T_IS_LONG + # define GCC_PRI64 HOST_LONG_FORMAT + #else + # define GCC_PRI64 HOST_LONG_LONG_FORMAT + #endif #undef PRId64 ! #define PRId64 GCC_PRI64 "d" #undef PRIi64 ! #define PRIi64 GCC_PRI64 "i" #undef PRIo64 ! #define PRIo64 GCC_PRI64 "o" #undef PRIu64 ! #define PRIu64 GCC_PRI64 "u" #undef PRIx64 ! #define PRIx64 GCC_PRI64 "x" #undef PRIX64 ! #define PRIX64 GCC_PRI64 "X" #endif + /* Various printf format strings for HOST_WIDE_INT. */ + + #if INT64_T_IS_LONG + # define HOST_WIDE_INT_PRINT HOST_LONG_FORMAT + # define HOST_WIDE_INT_PRINT_C "L" + #else + # define HOST_WIDE_INT_PRINT HOST_LONG_LONG_FORMAT + # define HOST_WIDE_INT_PRINT_C "LL" + #endif + + #define HOST_WIDE_INT_PRINT_DEC "%" PRId64 + #define HOST_WIDE_INT_PRINT_DEC_C "%" PRId64 HOST_WIDE_INT_PRINT_C + #define HOST_WIDE_INT_PRINT_UNSIGNED "%" PRIu64 + #define HOST_WIDE_INT_PRINT_HEX "%#" PRIx64 + #define HOST_WIDE_INT_PRINT_HEX_PURE "%" PRIx64 + #define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%" PRIx64 "%016" PRIx64 + #define HOST_WIDE_INT_PRINT_PADDED_HEX "%016" PRIx64 + /* Define HOST_WIDEST_FAST_INT to the widest integer type supported efficiently in hardware. (That is, the widest integer type that fits in a hardware register.) Normally this is "long" but on some hosts it