On Fri, Aug 20, 2021 at 08:48:57AM +0200, Harald Anlauf via Gcc-patches wrote: > Hi! > > > Gesendet: Freitag, 20. August 2021 um 02:21 Uhr > > Von: "H.J. Lu" <hjl.to...@gmail.com> > > > This may have broken bootstrap on 32-bit hosts: > > > > https://gcc.gnu.org/pipermail/gcc-regression/2021-August/075209.html > > I do not understand the error message: > > ../../src-master/gcc/fortran/simplify.c: In function ‘bool > substring_has_constant_len(gfc_expr*)’: > ../../src-master/gcc/fortran/simplify.c:4557:22: error: unknown conversion > type character ‘l’ in format [-Werror=format=] > 4557 | gfc_error ("Substring start index (" HOST_WIDE_INT_PRINT_DEC > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > 4558 | ") at %L below 1", > | ~~~~~~~~~~~~~~~~~ > ../../src-master/gcc/fortran/simplify.c:4557:22: error: format ‘%L’ expects > argument of type ‘locus*’, but argument 2 has type ‘long long int’ > [-Werror=format=] > 4557 | gfc_error ("Substring start index (" HOST_WIDE_INT_PRINT_DEC > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > 4558 | ") at %L below 1", > | ~~~~~~~~~~~~~~~~~ > 4559 | istart, &ref->u.ss.start->where); > | ~~~~~~ > | | > | long long int > ../../src-master/gcc/fortran/simplify.c:4557:22: error: too many arguments > for format [-Werror=format-extra-args] > > Is there an issue with HOST_WIDE_INT_PRINT_DEC on 32-bit hosts? > What is the right way to print a HOST_WIDE_INT? > > It works on 64-bit without any warning.
gfc_error etc. aren't *printf family, it has its own format specifier handling (e.g. it handles %L and %C), and it is even different from the error/warning handling in middle-end/c-family FEs/backends. HOST_WIDE_INT_PRINT_DEC is wrong in the above spot for 2 reasons: 1) gfc_error etc. argument is automatically marked for translation and translated, having a macro in there that expands to various things depending on host makes it impossible to mark for translation and a lottery for translation. 2) hwint.h defines: #define HOST_LONG_FORMAT "l" #define HOST_LONG_LONG_FORMAT "ll" #if INT64_T_IS_LONG # define GCC_PRI64 HOST_LONG_FORMAT #else # define GCC_PRI64 HOST_LONG_LONG_FORMAT #endif #define PRId64 GCC_PRI64 "d" #define HOST_WIDE_INT_PRINT_DEC "%" PRId64 but xm-mingw32.h overrides #define HOST_LONG_LONG_FORMAT "I64" so effectively HOST_WIDE_INT_PRINT_DEC is "%ld", "%lld" or "%I64d" Now, gfc_error does handle %d or %ld, but doesn't handle %lld nor %I64d, so even if the 1) issue didn't exist, this explains why it works only on some hosts (e.g. x86_64-linux where %ld is used). But e.g. on i686-linux or many other hosts it is %lld which gfc_error doesn't handle and on Windows that %I64d. Now, the non-Fortran FE diagnostic code actually has %wd for this (w modifier like l modifier), which takes HOST_WIDE_INT/unsigned HOST_WIDE_INT argument and prints it. So, either you get through the hops to support that, unfortunately it isn't just adding support for that in fortran/error.c (error_print) and some helper functions, which wouldn't be that hard, just add 'w' next to 'l' handling, TYPE_* for that and union member etc., but one needs to modify c-family/c-format.c too to register the modifier so that gcc doesn't warn about it and knows the proper argument type etc. The other much easier but uglier option is to use a temporary buffer: char buffer[21]; sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, hwint_val); gfc_error ("... %s ...", ... buffer ...); This works, as it uses the host sprintf i.e. *printf family for which HOST_WIDE_INT_PRINT_DEC macro is designed. Jakub