+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;
+}
+