[gcc r16-9416] 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:0a9e52931016938c35f9944acc870650f3e8492f

commit r16-9416-g0a9e52931016938c35f9944acc870650f3e8492f
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 1868beb4b6cc..7c838bbd78f8 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.