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

Jakub Jelinek via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:822ce7e451fdbbeeca2df5d8ddbdf6bccc254abb

commit r17-2730-g822ce7e451fdbbeeca2df5d8ddbdf6bccc254abb
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]>

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 5456f6e8bdff..9bf5d40b9cc4 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 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.