[gcc r13-10444] fortran: Fix ICE with loops with (deprecated) non-integral iterators [PR126303]

Jakub Jelinek via Gcc-cvs <[email protected]> Sat, 1 Aug 2026 10:58:21 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:c5516c9026323e8e67d0229184e7a78ab838a952

commit r13-10444-gc5516c9026323e8e67d0229184e7a78ab838a952
Author: Jakub Jelinek <[email protected]>
Date:   Mon Jul 27 18:54:37 2026 +0200

    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  <[email protected]>
    
            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 <[email protected]>
    (cherry picked from commit 822ce7e451fdbbeeca2df5d8ddbdf6bccc254abb)

Diff:
---
 gcc/fortran/frontend-passes.cc       | 3 +++
 gcc/testsuite/gfortran.dg/pr126303.f | 9 +++++++++
 2 files changed, 12 insertions(+)

diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index f6fc0794abb7..3293b05ddc95 100644
--- a/gcc/fortran/frontend-passes.cc
+++ b/gcc/fortran/frontend-passes.cc
@@ -2816,6 +2816,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 000000000000..0e6f8381c87e
--- /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