On 20.08.21 02:21, H.J. Lu wrote:
This may have broken bootstrap on 32-bit hosts:
https://gcc.gnu.org/pipermail/gcc-regression/2021-August/075209.html
The latter has:
../../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
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HOST_WIDE_INT_PRINT_DEC is:
#define HOST_WIDE_INT_PRINT_DEC "%" PRId64
and the latter is something like:
"ld" or "lld"
I fail to see why that shouldn't work – and also building with:
CC="gcc-10 -m32 -fno-lto -O2" CXX="g++-10 -m32 -fno-lto -O2" .../configure
--prefix=... --disable-multilib --disable-libstdcxx-pch --enable-multiarch
--enable-languages=c,c++,fortran --disable-lto
did succeed.
Looking at the format checking:
gfortran.h:void gfc_error (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
with
gfortran.h:#define ATTRIBUTE_GCC_GFC(m, n) __attribute__ ((__format__
(__gcc_gfc__, m, n))) ATTRIBUTE_NONNULL(m)
I do see that the C/C++ part (which also uses
HOST_WIDE_INT_PRINT_DEC) have some special code
for HWI, which is used for via
init_dynamic_diag_info
contains support for hwi not for gfc_{error,warning} via
init_dynamic_gfc_info
I did wonder whether that causes the differences (→ attached patch).
On the other hand, %ld and %lld are pretty standard – and the
comment in the function talks about %w – which is not used
(except in spec files and in 'go').
Hence: No idea what's the problem or goes wrong.
Maybe the patch is still useful – at least it gives an
error when HWI is neither long nor long long ...
(Build with and without that patch with the options
shown aboved (and 'error:' in stage 1, 2, 3 plus
the usual bootstrap on x86-64.)
Comments?
Tobias
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht
München, HRB 106955
c-family/c-format.c: Support HOST_WIDE_INT in __gcc_gfc__
This patch fixes x86 -m32 builds as gcc/fortran now uses HOST_WIDE_INT
with gfc_error.
gcc/c-family/ChangeLog:
* c-format.c (init_dynamic_diag_hwi): New. Moved from ...
(init_dynamic_diag_info): ... here; call it.
(init_dynamic_gfc_info): Call it.
gcc/c-family/c-format.c | 135 ++++++++++++++++++++++++++----------------------
1 file changed, 74 insertions(+), 61 deletions(-)
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 6fd0bb33d21..1db4fd33dbc 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -4843,12 +4843,85 @@ init_dynamic_asm_fprintf_info (void)
}
}
+/* Called by init_dynamic_gfc_info and init_dynamic_diag_info.
+ Determine the type of "HOST_WIDE_INT" in the code being compiled for
+ use in GCC's diagnostic custom format attributes. You
+ must have set dynamic_format_types before calling this function. */
+static void
+init_dynamic_diag_hwi (void)
+{
+ static tree hwi;
+
+ if (!hwi)
+ {
+ static format_length_info *diag_ls;
+ unsigned int i;
+
+ /* Find the underlying type for HOST_WIDE_INT. For the 'w'
+ length modifier to work, one must have issued: "typedef
+ HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
+ prior to using that modifier. */
+ if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
+ {
+ hwi = identifier_global_value (hwi);
+ if (hwi)
+ {
+ if (TREE_CODE (hwi) != TYPE_DECL)
+ {
+ error ("%<__gcc_host_wide_int__%> is not defined as a type");
+ hwi = 0;
+ }
+ else
+ {
+ hwi = DECL_ORIGINAL_TYPE (hwi);
+ gcc_assert (hwi);
+ if (hwi != long_integer_type_node
+ && hwi != long_long_integer_type_node)
+ {
+ error ("%<__gcc_host_wide_int__%> is not defined"
+ " as %<long%> or %<long long%>");
+ hwi = 0;
+ }
+ }
+ }
+ }
+
+ /* Assign the new data for use. */
+
+ /* All the GCC diag formats use the same length specs. */
+ if (!diag_ls)
+ dynamic_format_types[gcc_diag_format_type].length_char_specs =
+ dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
+ dynamic_format_types[gcc_dump_printf_format_type].length_char_specs =
+ diag_ls = (format_length_info *)
+ xmemdup (gcc_diag_length_specs,
+ sizeof (gcc_diag_length_specs),
+ sizeof (gcc_diag_length_specs));
+ if (hwi)
+ {
+ /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
+ i = find_length_info_modifier_index (diag_ls, 'w');
+ if (hwi == long_integer_type_node)
+ diag_ls[i].index = FMT_LEN_l;
+ else if (hwi == long_long_integer_type_node)
+ diag_ls[i].index = FMT_LEN_ll;
+ else
+ gcc_unreachable ();
+ }
+ }
+}
+
+
/* Determine the type of a "locus" in the code being compiled for use
in GCC's __gcc_gfc__ custom format attribute. You must have set
dynamic_format_types before calling this function. */
static void
init_dynamic_gfc_info (void)
{
+ init_dynamic_diag_hwi ();
+
if (!locus)
{
static format_char_info *gfc_fci;
@@ -4985,67 +5058,7 @@ init_dynamic_diag_info (void)
|| local_event_ptr_node == void_type_node)
local_event_ptr_node = get_named_type ("diagnostic_event_id_t");
- static tree hwi;
-
- if (!hwi)
- {
- static format_length_info *diag_ls;
- unsigned int i;
-
- /* Find the underlying type for HOST_WIDE_INT. For the 'w'
- length modifier to work, one must have issued: "typedef
- HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
- prior to using that modifier. */
- if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
- {
- hwi = identifier_global_value (hwi);
- if (hwi)
- {
- if (TREE_CODE (hwi) != TYPE_DECL)
- {
- error ("%<__gcc_host_wide_int__%> is not defined as a type");
- hwi = 0;
- }
- else
- {
- hwi = DECL_ORIGINAL_TYPE (hwi);
- gcc_assert (hwi);
- if (hwi != long_integer_type_node
- && hwi != long_long_integer_type_node)
- {
- error ("%<__gcc_host_wide_int__%> is not defined"
- " as %<long%> or %<long long%>");
- hwi = 0;
- }
- }
- }
- }
-
- /* Assign the new data for use. */
-
- /* All the GCC diag formats use the same length specs. */
- if (!diag_ls)
- dynamic_format_types[gcc_diag_format_type].length_char_specs =
- dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
- dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
- dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
- dynamic_format_types[gcc_dump_printf_format_type].length_char_specs =
- diag_ls = (format_length_info *)
- xmemdup (gcc_diag_length_specs,
- sizeof (gcc_diag_length_specs),
- sizeof (gcc_diag_length_specs));
- if (hwi)
- {
- /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
- i = find_length_info_modifier_index (diag_ls, 'w');
- if (hwi == long_integer_type_node)
- diag_ls[i].index = FMT_LEN_l;
- else if (hwi == long_long_integer_type_node)
- diag_ls[i].index = FMT_LEN_ll;
- else
- gcc_unreachable ();
- }
- }
+ init_dynamic_diag_hwi ();
/* It's safe to "re-initialize these to the same values. */
dynamic_format_types[gcc_diag_format_type].conversion_specs =