From: Jakub Jelinek Date: Mon, 27 Jul 2026 16:54:37 +0000 (+0200) Subject: fortran: Fix ICE with loops with (deprecated) non-integral iterators [PR126303] X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=822ce7e451fdbbeeca2df5d8ddbdf6bccc254abb;p=thirdparty%2Fgcc.git fortran: Fix ICE with loops with (deprecated) non-integral iterators [PR126303] do_subscript contains do_sym = dl->ext.iterator->var->symtree->n.sym; if (do_sym->ts.type != BT_INTEGER) continue; check to ignore loops with non-integral iterator. But r15-11154 PR94978 change has added inner_loop_may_be_skipped function and that happily accesses inner loop iterator's step, start and end if EXPR_CONSTANT with mpz_init_set (..., ...value.integer); Now, given the layout of mpfr_t (usually long, int, long, pointer) and mpz_t (usually int, int, pointer), this sometimes just produces silently garbage (e.g. on 64-bit little-endian, where the second int in mpz_t is the most significant 32-bits of _mpfr_prec and so usually 0 and so _mp_size is 0 and nothing is dereferenced: p loop->ext.iterator->step.value.real $1 = {{_mpfr_prec = 24, _mpfr_sign = 1, _mpfr_exp = 1, _mpfr_d = 0x4eac658}} p loop->ext.iterator->step.value.integer $2 = {{_mp_alloc = 24, _mp_size = 0, _mp_d = 0x1}} or it ICEs somewhere in gmp (on 32-bit little-endian, e.g. i686, or big-endian, e.g. s390x), because _mp_size is in that case _mpfr_sign but _mp_d is _mpfr_exp (32-bit little-endian), or _mp_size is least significant part of _mpfr_prec, in both cases non-zero, but _mp_d is not a usable pointer in either case. The following patch fixes that by punting for inner loops with non-integral iterator. 2026-07-27 Jakub Jelinek PR fortran/126303 * frontend-passes.cc (inner_loop_may_be_skipped): If inner loop iterator is not integral, return true. * gfortran.dg/pr126303.f: New test. Reviewed-by: Jerry DeLisle --- diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc index 5456f6e8bdf..9bf5d40b9cc 100644 --- a/gcc/fortran/frontend-passes.cc +++ b/gcc/fortran/frontend-passes.cc @@ -2778,6 +2778,9 @@ inner_loop_may_be_skipped (int loop_index, gfc_symbol *outer_sym, mpz_t outer_va if (loop == NULL || loop->ext.iterator == NULL || loop->ext.iterator->var == NULL) return true; + if (loop->ext.iterator->var->symtree->n.sym->ts.type != BT_INTEGER) + return true; + if (!evaluate_loop_bound (loop->ext.iterator->step, outer_sym, outer_val, do_step)) return true; diff --git a/gcc/testsuite/gfortran.dg/pr126303.f b/gcc/testsuite/gfortran.dg/pr126303.f new file mode 100644 index 00000000000..0e6f8381c87 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr126303.f @@ -0,0 +1,9 @@ +! PR fortran/126303 +! { dg-do compile } +! { dg-options "-std=legacy" } + COMMON FOO(8) + DO 10 M=1,8 + DO 10 T=0D0,1D0 + FOO(M)=1 + 10 CONTINUE + END