https://gcc.gnu.org/g:005358093fd8566824b088d9bf7c8512ef5844fa

commit r15-11154-g005358093fd8566824b088d9bf7c8512ef5844fa
Author: Christopher Albert <[email protected]>
Date:   Sat Mar 28 17:26:05 2026 +0100

    fortran: Avoid bogus do-subscript warnings in skipped inner loops [PR94978]
    
    Do not warn from an outer-loop bound substitution when a nested inner loop 
may
    be zero-trip after that substitution, because the guarded array reference 
may
    then be unreachable.
    
    gcc/fortran/ChangeLog:
    
            PR fortran/94978
            * frontend-passes.cc (evaluate_loop_bound): New helper.
            (inner_loop_may_be_skipped): New helper.
            (do_subscript): Skip outer-loop bound warnings when nested inner 
loops
            may be zero-trip for the substituted bound.
    
    gcc/testsuite/ChangeLog:
    
            PR fortran/94978
            * gfortran.dg/pr94978.f90: New test.
    
    Signed-off-by: Christopher Albert <[email protected]>
    (cherry picked from commit 790671b708400d1fc6bb1abbf1601f3616e8220d)

Diff:
---
 gcc/fortran/frontend-passes.cc        | 69 ++++++++++++++++++++++++++++++++++-
 gcc/testsuite/gfortran.dg/pr94978.f90 | 24 ++++++++++++
 2 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/frontend-passes.cc b/gcc/fortran/frontend-passes.cc
index ef9c80147cc4..496d17352080 100644
--- a/gcc/fortran/frontend-passes.cc
+++ b/gcc/fortran/frontend-passes.cc
@@ -2745,6 +2745,66 @@ insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, 
mpz_t ret)
 
 }
 
+static bool
+evaluate_loop_bound (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
+{
+  if (e->expr_type == EXPR_CONSTANT)
+    {
+      mpz_init_set (ret, e->value.integer);
+      return true;
+    }
+
+  return insert_index (e, sym, val, ret);
+}
+
+/* Return true if any loop nested inside LOOP_INDEX is not provably entered
+   after substituting OUTER_VAL for OUTER_SYM.  In that case the guarded array
+   reference may never be evaluated, so do not warn from the outer loop alone. 
 */
+
+static bool
+inner_loop_may_be_skipped (int loop_index, gfc_symbol *outer_sym, mpz_t 
outer_val)
+{
+  int k;
+  do_t *lp;
+
+  FOR_EACH_VEC_ELT_FROM (doloop_list, k, lp, loop_index + 1)
+    {
+      gfc_code *loop = lp->c;
+      int sgn, cmp;
+      mpz_t do_start, do_end, do_step;
+
+      if (loop == NULL || loop->ext.iterator == NULL || 
loop->ext.iterator->var == NULL)
+       return true;
+
+      if (!evaluate_loop_bound (loop->ext.iterator->step, outer_sym, 
outer_val, do_step))
+       return true;
+
+      sgn = mpz_cmp_ui (do_step, 0);
+      if (sgn == 0)
+       {
+         mpz_clear (do_step);
+         return true;
+       }
+
+      if (!evaluate_loop_bound (loop->ext.iterator->start, outer_sym, 
outer_val, do_start)
+         || !evaluate_loop_bound (loop->ext.iterator->end, outer_sym, 
outer_val, do_end))
+       {
+         mpz_clear (do_step);
+         return true;
+       }
+
+      cmp = mpz_cmp (do_end, do_start);
+      mpz_clear (do_start);
+      mpz_clear (do_end);
+      mpz_clear (do_step);
+
+      if ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0))
+       return true;
+    }
+
+  return false;
+}
+
 /* Check array subscripts for possible out-of-bounds accesses in DO
    loops with constant bounds.  */
 
@@ -2879,10 +2939,15 @@ do_subscript (gfc_expr **e)
                  mpz_clear (rem);
                }
 
+             bool skip_start = have_do_start
+                               && inner_loop_may_be_skipped (j, do_sym, 
do_start);
+             bool skip_end = have_do_end
+                             && inner_loop_may_be_skipped (j, do_sym, do_end);
+
              for (i = 0; i< ar->dimen; i++)
                {
                  mpz_t val;
-                 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start
+                 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start && 
!skip_start
                      && insert_index (ar->start[i], do_sym, do_start, val))
                    {
                      if (ar->as->lower[i]
@@ -2908,7 +2973,7 @@ do_subscript (gfc_expr **e)
                      mpz_clear (val);
                    }
 
-                 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end
+                 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end && 
!skip_end
                      && insert_index (ar->start[i], do_sym, do_end, val))
                    {
                      if (ar->as->lower[i]
diff --git a/gcc/testsuite/gfortran.dg/pr94978.f90 
b/gcc/testsuite/gfortran.dg/pr94978.f90
new file mode 100644
index 000000000000..5d64d227fdc0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr94978.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-options "-Wdo-subscript" }
+
+implicit none
+
+integer(4) :: i, j
+integer(4) :: pascal(0:8, 0:8)
+
+do i = 0, 8
+  pascal(i, 0) = 1
+  do j = 1, i - 1
+    pascal(i, j) = pascal(i - 1, j) + pascal(i - 1, j - 1) ! { dg-bogus "Array 
reference at \\(1\\) out of bounds" }
+  end do
+  do j = i, 8
+    pascal(i, j) = 0
+  end do
+  pascal(i, i) = 1
+end do
+
+do i = 0, 8
+  print '(9I4)', pascal(i, :)
+end do
+
+end

Reply via email to