/* Array bounds checking.
   Copyright (C) 2005-2026 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "pointer-query.h"
#include "gimple-array-bounds.h"
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "tree-dfa.h"
#include "fold-const.h"
#include "diagnostic-core.h"
#include "diagnostic-context-rich-location.h"
#include "intl.h"
#include "tree-vrp.h"
#include "alloc-pool.h"
#include "vr-values.h"
#include "domwalk.h"
#include "tree-cfg.h"
#include "attribs.h"
#include "tree-pass.h"
#include "gimple-range.h"

// Always use the current range query for the bounds checker.
array_bounds_checker::array_bounds_checker (struct function *func)
  : fun (func), m_ptr_qry (get_range_query (func))
{
  /* No-op.  */
}

void
array_bounds_checker::get_value_range (irange &r, const_tree op, gimple *stmt)
{
  if (m_ptr_qry.rvals->range_of_expr (r, const_cast<tree> (op), stmt))
    return;
  r.set_varying (TREE_TYPE (op));
}

/* Try to determine the DECL that REF refers to.  Return the DECL or
   the expression closest to it.  Used in informational notes pointing
   to referenced objects or function parameters.  */

static tree
get_base_decl (tree ref)
{
  tree base = get_base_address (ref);
  if (DECL_P (base))
    return base;

  if (TREE_CODE (base) == MEM_REF)
    base = TREE_OPERAND (base, 0);

  if (TREE_CODE (base) != SSA_NAME)
    return base;

  do
    {
      gimple *def = SSA_NAME_DEF_STMT (base);
      if (gimple_assign_single_p (def))
	{
	  base = gimple_assign_rhs1 (def);
	  return base;
	}

      if (!gimple_nop_p (def))
	return base;

      break;
    } while (true);

  tree var = SSA_NAME_VAR (base);
  if (TREE_CODE (var) != PARM_DECL)
    return base;

  return var;
}

/* Return the constant byte size of the object or type referenced by
   the MEM_REF ARG.  On success, set *PREF to the DECL or expression
   ARG refers to.  Otherwise return null.  */

static tree
get_ref_size (tree arg, tree *pref)
{
  if (TREE_CODE (arg) != MEM_REF)
    return NULL_TREE;

  arg = TREE_OPERAND (arg, 0);
  tree type = TREE_TYPE (arg);
  if (!POINTER_TYPE_P (type))
    return NULL_TREE;

  type = TREE_TYPE (type);
  if (TREE_CODE (type) != ARRAY_TYPE)
    return NULL_TREE;

  tree nbytes = TYPE_SIZE_UNIT (type);
  if (!nbytes || TREE_CODE (nbytes) != INTEGER_CST)
    return NULL_TREE;

  *pref = get_base_decl (arg);
  return nbytes;
}

/* Return true if REF is (likely) an ARRAY_REF to a trailing array member
   of a struct.  It refines array_ref_flexible_size_p by detecting a pointer
   to an array and an array parameter declared using the [N] syntax (as
   opposed to a pointer) and returning false.  Set *PREF to the decl or
   expression REF refers to.  */

static bool
trailing_array (tree arg, tree *pref)
{
  tree ref = arg;
  tree base = get_base_decl (arg);
  while (TREE_CODE (ref) == ARRAY_REF || TREE_CODE (ref) == MEM_REF)
    ref = TREE_OPERAND (ref, 0);

  if (TREE_CODE (ref) == COMPONENT_REF)
    {
      *pref = TREE_OPERAND (ref, 1);
      tree type = TREE_TYPE (*pref);
      if (TREE_CODE (type) == ARRAY_TYPE)
	{
	  /* A multidimensional trailing array is not considered special
	     no matter what its major bound is.  */
	  type = TREE_TYPE (type);
	  if (TREE_CODE (type) == ARRAY_TYPE)
	    return false;
	}
    }
  else
    *pref = base;

  tree basetype = TREE_TYPE (base);
  if (TREE_CODE (base) == PARM_DECL
      && POINTER_TYPE_P (basetype))
    {
      tree ptype = TREE_TYPE (basetype);
      if (TREE_CODE (ptype) == ARRAY_TYPE)
	return false;
    }

  return array_ref_flexible_size_p (arg);
}

/* Acquire the upper bound and upper bound plus one for the array
   reference REF and record them into UP_BOUND and UP_BOUND_P1.
   Set *DECL to the decl or expresssion REF refers to.  */

static void
get_up_bounds_for_array_ref (tree ref, tree *decl,
			     tree *up_bound, tree *up_bound_p1)
{
  if (!(*up_bound)
      || TREE_CODE (*up_bound) != INTEGER_CST
      || trailing_array (ref, decl))
    {
      /* Accesses to trailing arrays via pointers may access storage
	 beyond the types array bounds.  For such arrays, or for flexible
	 array members, as well as for other arrays of an unknown size,
	 replace the upper bound with a more permissive one that assumes
	 the size of the largest object is PTRDIFF_MAX.  */
      tree eltsize = array_ref_element_size (ref);

      if (TREE_CODE (eltsize) != INTEGER_CST
	  || integer_zerop (eltsize))
	{
	  *up_bound = NULL_TREE;
	  *up_bound_p1 = NULL_TREE;
	}
      else
	{
	  tree ptrdiff_max = TYPE_MAX_VALUE (ptrdiff_type_node);
	  tree maxbound = ptrdiff_max;
	  tree arg = TREE_OPERAND (ref, 0);

	  const bool compref = TREE_CODE (arg) == COMPONENT_REF;
	  if (compref)
	    {
	      /* Try to determine the size of the trailing array from
		 its initializer (if it has one).  */
	      if (tree refsize = component_ref_size (arg))
		if (TREE_CODE (refsize) == INTEGER_CST)
		  maxbound = refsize;
	    }

	  if (maxbound == ptrdiff_max)
	    {
	      /* Try to determine the size of the base object.  Avoid
		 COMPONENT_REF already tried above.  Using its DECL_SIZE
		 size wouldn't necessarily be correct if the reference is
		 to its flexible array member initialized in a different
		 translation unit.  */
	      poly_int64 off;
	      if (tree base = get_addr_base_and_unit_offset (arg, &off))
		{
		  if (TREE_CODE (base) == MEM_REF)
		    {
		      /* Try to determine the size from a pointer to
			 an array if BASE is one.  */
		      if (tree size = get_ref_size (base, decl))
			maxbound = size;
		    }
		  else if (!compref && DECL_P (base))
		    if (tree basesize = DECL_SIZE_UNIT (base))
		      if (TREE_CODE (basesize) == INTEGER_CST)
			{
			  maxbound = basesize;
			  *decl = base;
			}

		  if (known_gt (off, 0))
		    maxbound = wide_int_to_tree (sizetype,
						 wi::sub (wi::to_wide (maxbound),
							  off));
		}
	    }
	  else
	    maxbound = fold_convert (sizetype, maxbound);

	  *up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);

	  if (*up_bound_p1 != NULL_TREE)
	    *up_bound = int_const_binop (MINUS_EXPR, *up_bound_p1,
					build_int_cst (ptrdiff_type_node, 1));
	  else
	    *up_bound = NULL_TREE;
	}
    }
  else
    *up_bound_p1 = int_const_binop (PLUS_EXPR, *up_bound,
				   build_int_cst (TREE_TYPE (*up_bound), 1));
  return;
}

/* Given the LOW_SUB_ORG, LOW_SUB and UP_SUB, and the computed UP_BOUND
   and UP_BOUND_P1, check whether the array reference REF is out of bound.
   When out of bounds, set OUT_OF_BOUND to true.
   Issue warnings if FOR_ARRAY_BOUND is true.
   return TRUE if warnings are issued.  */

static bool
check_out_of_bounds_and_warn (location_t location, tree ref,
			      gimple *stmt,
			      tree low_sub_org, tree low_sub, tree up_sub,
			      tree up_bound, tree up_bound_p1,
			      const irange *vr,
			      bool ignore_off_by_one, bool for_array_bound,
			      bool *out_of_bound)
{
  tree min, max;
  tree low_bound = array_ref_low_bound (ref);
  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));

  bool warned = false;
  *out_of_bound = false;

  rich_location_with_details richloc (location, stmt);
  /* Empty array.  */
  if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
    {
      *out_of_bound = true;
      if (for_array_bound)
	warned = warning_at (&richloc, OPT_Warray_bounds_,
			     "array subscript %E is outside array"
			     " bounds of %qT", low_sub_org, artype);
    }

  if (warned)
    ; /* Do nothing.  */
  else if (get_legacy_range (*vr, min, max) == VR_ANTI_RANGE)
    {
      if (up_bound
	  && TREE_CODE (up_sub) == INTEGER_CST
	  && (ignore_off_by_one
	      ? tree_int_cst_lt (up_bound, up_sub)
	      : tree_int_cst_le (up_bound, up_sub))
	  && TREE_CODE (low_sub) == INTEGER_CST
	  && tree_int_cst_le (low_sub, low_bound))
	{
	  *out_of_bound = true;
	  if (for_array_bound)
	    warned = warning_at (&richloc, OPT_Warray_bounds_,
				 "array subscript [%E, %E] is outside "
				 "array bounds of %qT",
				 low_sub, up_sub, artype);
	}
    }
  else if (up_bound
	   && TREE_CODE (up_sub) == INTEGER_CST
	   && (ignore_off_by_one
	       ? !tree_int_cst_le (up_sub, up_bound_p1)
	       : !tree_int_cst_le (up_sub, up_bound)))
    {
      *out_of_bound = true;
      if (for_array_bound)
	warned = warning_at (&richloc, OPT_Warray_bounds_,
			     "array subscript %E is above array bounds of %qT",
			     up_sub, artype);
    }
  else if (TREE_CODE (low_sub) == INTEGER_CST
	   && tree_int_cst_lt (low_sub, low_bound))
    {
      *out_of_bound = true;
      if (for_array_bound)
	warned = warning_at (&richloc, OPT_Warray_bounds_,
			     "array subscript %E is below array bounds of %qT",
			     low_sub, artype);
    }
  return warned;
}

/* Checks one ARRAY_REF in REF, located at LOCUS.  Ignores flexible
   arrays and "struct" hacks.  If VRP can determine that the array
   subscript is a constant, check if it is outside valid range.  If
   the array subscript is a RANGE, warn if it is non-overlapping with
   valid range.  IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
   a ADDR_EXPR.  Return  true if a warning has been issued or if
   no-warning is set.  */

bool
array_bounds_checker::check_array_ref (location_t location, tree ref,
				       gimple *stmt, bool ignore_off_by_one)
{
  if (warning_suppressed_p (ref, OPT_Warray_bounds_))
    /* Return true to have the caller prevent warnings for enclosing
       refs.  */
    return true;

  /* Upper bound and Upper bound plus one for -Warray-bounds.  */
  tree up_bound = array_ref_up_bound (ref);
  tree up_bound_p1 = NULL_TREE;

  /* Referenced decl if one can be determined.  */
  tree decl = NULL_TREE;

  /* Set to the type of the special array member for a COMPONENT_REF.  */
  special_array_member sam{ };
  tree afield_decl = NULL_TREE;
  tree arg = TREE_OPERAND (ref, 0);

  if (TREE_CODE (arg) == COMPONENT_REF)
    {
      /* Try to determine special array member type for this COMPONENT_REF.  */
      sam = component_ref_sam_type (arg);
      afield_decl = TREE_OPERAND (arg, 1);
    }

  get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1);

  bool warned = false;
  bool out_of_bound = false;

  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
  tree low_sub_org = TREE_OPERAND (ref, 1);
  tree up_sub = low_sub_org;
  tree low_sub = low_sub_org;

  int_range_max vr;
  if (TREE_CODE (low_sub_org) == SSA_NAME)
    {
      get_value_range (vr, low_sub_org, stmt);
      if (!vr.undefined_p () && !vr.varying_p ())
	{
	  tree min, max;
	  value_range_kind kind = get_legacy_range (vr, min, max);
	  low_sub = kind == VR_RANGE ? max : min;
	  up_sub = kind == VR_RANGE ? min : max;
	}
    }

  warned = check_out_of_bounds_and_warn (location, ref, stmt,
					 low_sub_org, low_sub, up_sub,
					 up_bound, up_bound_p1, &vr,
					 ignore_off_by_one, warn_array_bounds,
					 &out_of_bound);

  rich_location_with_details richloc (location, stmt);

  if (!warned && sam == special_array_member::int_0)
    warned = warning_at (&richloc, OPT_Wzero_length_bounds,
			 (TREE_CODE (low_sub) == INTEGER_CST
			  ? G_("array subscript %E is outside the bounds "
			       "of an interior zero-length array %qT")
			  : G_("array subscript %qE is outside the bounds "
			       "of an interior zero-length array %qT")),
			 low_sub, artype);

  if (warned && dump_file && (dump_flags & TDF_DETAILS))
    {
      fprintf (dump_file, "Array bound warning for ");
      dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
      fprintf (dump_file, "\n");
    }

   /* Issue warnings for -Wstrict-flex-arrays according to the level of
      flag_strict_flex_arrays.  */
  if (out_of_bound && warn_strict_flex_arrays
      && (sam == special_array_member::trail_0
	  || sam == special_array_member::trail_1
	  || sam == special_array_member::trail_n)
      && DECL_NOT_FLEXARRAY (afield_decl))
    {
      bool warned1
	= warning_at (&richloc, OPT_Wstrict_flex_arrays,
		      "trailing array %qT should not be used as "
		      "a flexible array member",
		      artype);

      if (warned1 && dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "Trailing non flexible-like array bound warning for ");
	  dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
	  fprintf (dump_file, "\n");
	}
      warned |= warned1;
    }

  if (warned)
    {
      /* Avoid more warnings when checking more significant subscripts
	 of the same expression.  */
      ref = TREE_OPERAND (ref, 0);
      suppress_warning (ref, OPT_Warray_bounds_);
      suppress_warning (ref, OPT_Wstrict_flex_arrays);

      if (decl)
	ref = decl;

      tree rec = NULL_TREE;
      if (TREE_CODE (ref) == COMPONENT_REF)
	{
	  /* For a reference to a member of a struct object also mention
	     the object if it's known.  It may be defined in a different
	     function than the out-of-bounds access.  */
	  rec = TREE_OPERAND (ref, 0);
	  if (!VAR_P (rec))
	    rec = NULL_TREE;
	  ref = TREE_OPERAND (ref, 1);
	}

      if (DECL_P (ref))
	inform (DECL_SOURCE_LOCATION (ref), "while referencing %qD", ref);
      if (rec && DECL_P (rec))
	inform (DECL_SOURCE_LOCATION (rec), "defined here %qD", rec);
    }

  return warned;
}

/* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
   references to string constants.  If VRP can determine that the array
   subscript is a constant, check if it is outside valid range.
   If the array subscript is a RANGE, warn if it is non-overlapping
   with valid range.
   IGNORE_OFF_BY_ONE is true if the MEM_REF is inside an ADDR_EXPR
   (used to allow one-past-the-end indices for code that takes
   the address of the just-past-the-end element of an array).
   Returns true if a warning has been issued.  */

bool
array_bounds_checker::check_mem_ref (location_t location, tree ref,
				     gimple *stmt,
				     bool ignore_off_by_one)
{
  if (warning_suppressed_p (ref, OPT_Warray_bounds_))
    return false;

  /* The statement used to allocate the array or null.  */
  gimple *alloc_stmt = NULL;
  /* For an allocation statement, the low bound of the size range.  */
  offset_int minbound = 0;
  /* The type and size of the access.  */
  tree axstype = TREE_TYPE (ref);
  offset_int axssize = 0;
  if (tree access_size = TYPE_SIZE_UNIT (axstype))
    if (TREE_CODE (access_size) == INTEGER_CST)
      axssize = wi::to_offset (access_size);

  access_ref aref;
  if (!m_ptr_qry.get_ref (ref, m_stmt, &aref, 0))
    return false;

  if (aref.offset_in_range (axssize))
    return false;

  if (TREE_CODE (aref.ref) == SSA_NAME)
    {
      gimple *def = SSA_NAME_DEF_STMT (aref.ref);
      if (is_gimple_call (def))
	{
	  /* Save the allocation call and the low bound on the size.  */
	  alloc_stmt = def;
	  minbound = aref.sizrng[0];
	}
    }

  /* The range of the byte offset into the reference.  Adjusted below.  */
  offset_int offrange[2] = { aref.offrng[0], aref.offrng[1] };

  /* The type of the referenced object.  */
  tree reftype = TREE_TYPE (aref.ref);
  /* The size of the referenced array element.  */
  offset_int eltsize = 1;
  if (POINTER_TYPE_P (reftype))
    reftype = TREE_TYPE (reftype);

  if (TREE_CODE (reftype) == FUNCTION_TYPE)
    /* Restore the original (pointer) type and avoid trying to create
       an array of functions (done below).  */
    reftype = TREE_TYPE (aref.ref);
  else
    {
      /* The byte size of the array has already been determined above
	 based on a pointer ARG.  Set ELTSIZE to the size of the type
	 it points to and REFTYPE to the array with the size, rounded
	 down as necessary.  */
      if (TREE_CODE (reftype) == ARRAY_TYPE)
	reftype = TREE_TYPE (reftype);
      if (tree refsize = TYPE_SIZE_UNIT (reftype))
	if (TREE_CODE (refsize) == INTEGER_CST)
	  eltsize = wi::to_offset (refsize);

      const offset_int nelts = aref.sizrng[1] / eltsize;
      reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
    }

  /* Compute the more permissive upper bound when IGNORE_OFF_BY_ONE
     is set (when taking the address of the one-past-last element
     of an array) but always use the stricter bound in diagnostics. */
  offset_int ubound = aref.sizrng[1];
  if (ignore_off_by_one)
    ubound += eltsize;

  /* Set if the lower bound of the subscript is out of bounds.  */
  const bool lboob = (aref.sizrng[1] == 0
		      || offrange[0] >= ubound
		      || offrange[1] < 0);
  /* Set if only the upper bound of the subscript is out of bounds.
     This can happen when using a bigger type to index into an array
     of a smaller type, as is common with unsigned char.  */
  const bool uboob = !lboob && offrange[0] + axssize > ubound;
  if (lboob || uboob)
    {
      /* Treat a reference to a non-array object as one to an array
	 of a single element.  */
      if (TREE_CODE (reftype) != ARRAY_TYPE)
	reftype = build_printable_array_type (reftype, 1);

      /* Extract the element type out of MEM_REF and use its size
	 to compute the index to print in the diagnostic; arrays
	 in MEM_REF don't mean anything.  A type with no size like
	 void is as good as having a size of 1.  */
      tree type = strip_array_types (TREE_TYPE (ref));
      if (tree size = TYPE_SIZE_UNIT (type))
	{
	  offrange[0] = offrange[0] / wi::to_offset (size);
	  offrange[1] = offrange[1] / wi::to_offset (size);
	}
    }

  rich_location_with_details richloc (location, stmt);
  bool warned = false;
  if (lboob)
    {
      if (offrange[0] == offrange[1])
	warned = warning_at (&richloc, OPT_Warray_bounds_,
			     "array subscript %wi is outside array bounds "
			     "of %qT",
			     offrange[0].to_shwi (), reftype);
      else
	warned = warning_at (&richloc, OPT_Warray_bounds_,
			     "array subscript [%wi, %wi] is outside "
			     "array bounds of %qT",
			     offrange[0].to_shwi (),
			     offrange[1].to_shwi (), reftype);
    }
  else if (uboob && !ignore_off_by_one)
    {
      tree backtype = reftype;
      if (alloc_stmt)
	/* If the memory was dynamically allocated refer to it as if
	   it were an untyped array of bytes.  */
	backtype = build_array_type_nelts (unsigned_char_type_node,
					   aref.sizrng[1].to_uhwi ());
      warned = warning_at (&richloc, OPT_Warray_bounds_,
			   "array subscript %<%T[%wi]%> is partly "
			   "outside array bounds of %qT",
			   axstype, offrange[0].to_shwi (), backtype);
    }

  if (warned)
    {
      /* TODO: Determine the access from the statement and use it.  */
      aref.inform_access (access_none);
      suppress_warning (ref, OPT_Warray_bounds_);
      return true;
    }

  if (warn_array_bounds < 2)
    return false;

  /* At level 2 check also intermediate offsets.  */
  int i = 0;
  if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
    {
      HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi ();

      if (warning_at (&richloc, OPT_Warray_bounds_,
		      "intermediate array offset %wi is outside array bounds "
		      "of %qT", tmpidx, reftype))
	{
	  suppress_warning (ref, OPT_Warray_bounds_);
	  return true;
	}
    }

  return false;
}

/* Searches if the expr T, located at LOCATION computes
   address of an ARRAY_REF, and call check_array_ref on it.  */

void
array_bounds_checker::check_addr_expr (location_t location, tree t,
				       gimple *stmt)
{
  /* For the most significant subscript only, accept taking the address
     of the just-past-the-end element.  */
  bool ignore_off_by_one = true;

  /* Check each ARRAY_REF and MEM_REF in the reference chain. */
  do
    {
      bool warned = false;
      if (TREE_CODE (t) == ARRAY_REF)
	{
	  warned = check_array_ref (location, t, stmt, ignore_off_by_one);
	  ignore_off_by_one = false;
	}
      else if (TREE_CODE (t) == MEM_REF)
	warned = check_mem_ref (location, t, stmt, ignore_off_by_one);

      if (warned)
	suppress_warning (t, OPT_Warray_bounds_);

      t = TREE_OPERAND (t, 0);
    }
  while (handled_component_p (t) || TREE_CODE (t) == MEM_REF);

  if (TREE_CODE (t) != MEM_REF
      || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
      || warning_suppressed_p (t, OPT_Warray_bounds_))
    return;

  tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
  tree low_bound, up_bound, el_sz;
  if (TREE_CODE (TREE_TYPE (tem)) != ARRAY_TYPE
      || TREE_CODE (TREE_TYPE (TREE_TYPE (tem))) == ARRAY_TYPE
      || !TYPE_DOMAIN (TREE_TYPE (tem)))
    return;

  low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
  up_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (tem)));
  el_sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (tem)));
  if (!low_bound
      || TREE_CODE (low_bound) != INTEGER_CST
      || !up_bound
      || TREE_CODE (up_bound) != INTEGER_CST
      || !el_sz
      || TREE_CODE (el_sz) != INTEGER_CST)
    return;

  offset_int idx;
  if (!mem_ref_offset (t).is_constant (&idx))
    return;

  rich_location_with_details richloc (location, stmt);
  bool warned = false;
  idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz));
  if (idx < 0)
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "Array bound warning for ");
	  dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
	  fprintf (dump_file, "\n");
	}
      warned = warning_at (&richloc, OPT_Warray_bounds_,
			   "array subscript %wi is below "
			   "array bounds of %qT",
			   idx.to_shwi (), TREE_TYPE (tem));
    }
  else if (idx > (wi::to_offset (up_bound)
		  - wi::to_offset (low_bound) + 1))
    {
      if (dump_file && (dump_flags & TDF_DETAILS))
	{
	  fprintf (dump_file, "Array bound warning for ");
	  dump_generic_expr (MSG_NOTE, TDF_SLIM, t);
	  fprintf (dump_file, "\n");
	}
      warned = warning_at (&richloc, OPT_Warray_bounds_,
			   "array subscript %wu is above "
			   "array bounds of %qT",
			   idx.to_uhwi (), TREE_TYPE (tem));
    }

  if (warned)
    {
      if (DECL_P (t))
	inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);

      suppress_warning (t, OPT_Warray_bounds_);
    }
}

/* Return true if T is a reference to a member of a base class that's within
   the bounds of the enclosing complete object.  The function "hacks" around
   problems discussed in pr98266 and pr97595.  */

static bool
inbounds_memaccess_p (tree t, gimple *stmt)
{
  if (TREE_CODE (t) != COMPONENT_REF)
    return false;

  tree mref = TREE_OPERAND (t, 0);
  if (TREE_CODE (mref) != MEM_REF)
    return false;

  /* Consider the access if its type is a derived class.  */
  tree mreftype = TREE_TYPE (mref);
  if (!RECORD_OR_UNION_TYPE_P (mreftype)
      || !TYPE_BINFO (mreftype))
    return false;

  /* Compute the size of the referenced object (it could be dynamically
     allocated).  */
  access_ref aref;   // unused
  tree refop = TREE_OPERAND (mref, 0);
  tree refsize = compute_objsize (refop, stmt, 1, &aref);
  if (!refsize || TREE_CODE (refsize) != INTEGER_CST)
    return false;

  /* Compute the byte offset of the member within its enclosing class.  */
  tree fld = TREE_OPERAND (t, 1);
  tree fldpos = byte_position (fld);
  if (TREE_CODE (fldpos) != INTEGER_CST)
    return false;

  /* Compute the byte offset of the member with the outermost complete
     object by adding its offset computed above to the MEM_REF offset.  */
  tree refoff = TREE_OPERAND (mref, 1);
  tree fldoff = int_const_binop (PLUS_EXPR, fldpos, refoff);
  /* Return false if the member offset is greater or equal to the size
     of the complete object.  */
  if (!tree_int_cst_lt (fldoff, refsize))
    return false;

  tree fldsiz = DECL_SIZE_UNIT (fld);
  if (!fldsiz || TREE_CODE (fldsiz) != INTEGER_CST)
    return false;

  /* Return true if the offset just past the end of the member is less
     than or equal to the size of the complete object.  */
  tree fldend = int_const_binop (PLUS_EXPR, fldoff, fldsiz);
  return tree_int_cst_le (fldend, refsize);
}

/* Callback for walk_tree to check a tree for out of bounds array
   accesses.  The array_bounds_checker class is passed in DATA.  */

tree
array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
					  void *data)
{
  tree t = *tp;
  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;

  location_t location;

  if (EXPR_HAS_LOCATION (t))
    location = EXPR_LOCATION (t);
  else
    location = gimple_location (wi->stmt);

  *walk_subtree = true;

  bool warned = false;
  array_bounds_checker *checker = (array_bounds_checker *) wi->info;
  gcc_assert (checker->m_stmt == wi->stmt);

  if (TREE_CODE (t) == ARRAY_REF)
    warned = checker->check_array_ref (location, t, wi->stmt,
				       false/*ignore_off_by_one*/);
  else if (TREE_CODE (t) == MEM_REF)
    warned = checker->check_mem_ref (location, t, wi->stmt,
				     false /*ignore_off_by_one*/);
  else if (TREE_CODE (t) == ADDR_EXPR)
    {
      checker->check_addr_expr (location, t, wi->stmt);
      *walk_subtree = false;
    }
  else if (inbounds_memaccess_p (t, wi->stmt))
    /* Hack: Skip MEM_REF checks in accesses to a member of a base class
       at an offset that's within the bounds of the enclosing object.
       See pr98266 and pr97595.  */
    *walk_subtree = false;

  /* Propagate the no-warning bit to the outer statement to avoid also
     issuing -Wstringop-overflow/-overread for the out-of-bounds accesses.  */
  if (warned)
    suppress_warning (wi->stmt, OPT_Warray_bounds_);

  return NULL_TREE;
}

/* A dom_walker subclass for use by check_all_array_refs, to walk over
   all statements of all reachable BBs and call check_array_bounds on
   them.  */

class check_array_bounds_dom_walker : public dom_walker
{
public:
  check_array_bounds_dom_walker (array_bounds_checker *checker)
    : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS),
    checker (checker) { }
  ~check_array_bounds_dom_walker () {}

  edge before_dom_children (basic_block) final override;

private:
  array_bounds_checker *checker;
};

/* Implementation of dom_walker::before_dom_children.

   Walk over all statements of BB and call check_array_bounds on them,
   and determine if there's a unique successor edge.  */

edge
check_array_bounds_dom_walker::before_dom_children (basic_block bb)
{
  gimple_stmt_iterator si;
  for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
    {
      gimple *stmt = gsi_stmt (si);
      if (!gimple_has_location (stmt)
	  || is_gimple_debug (stmt))
	continue;

      struct walk_stmt_info wi{ };
      wi.info = checker;
      checker->m_stmt = stmt;

      walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
    }

  /* Determine if there's a unique successor edge, and if so, return
     that back to dom_walker, ensuring that we don't visit blocks that
     became unreachable during the VRP propagation
     (PR tree-optimization/83312).  */
  return find_taken_edge (bb, NULL_TREE);
}

void
array_bounds_checker::check ()
{
  check_array_bounds_dom_walker w (this);
  w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
}

const pass_data pass_data_array_bounds =
{
  GIMPLE_PASS, /* type */
  "bounds", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_TREE_ARRAY_BOUNDS, /* tv_id */
  PROP_ssa, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  ( 0 ),  /* No TODOs */
};

class pass_array_bounds : public gimple_opt_pass
{
public:
  pass_array_bounds (gcc::context *ctxt, const pass_data &data_)
    : gimple_opt_pass (data_, ctxt), data (data_)
    { }

  /* opt_pass methods: */
  opt_pass * clone () final override
    { return new pass_array_bounds (m_ctxt, data); }
  bool gate (function *) final override
    {
      // Gate on the VRP pass to preserve previous behavior.
      return flag_tree_vrp && (warn_array_bounds || warn_strict_flex_arrays);
    }
  unsigned int execute (function *fun) final override
    {
      calculate_dominance_info (CDI_DOMINATORS);
      // Enable ranger as the current range query.
      enable_ranger (fun, false);
      array_bounds_checker array_checker (fun);
      array_checker.check ();
      disable_ranger (fun);
      return 0;
    }

 private:
  const pass_data &data;
}; // class pass_array_bounds

gimple_opt_pass *
make_pass_array_bounds (gcc::context *ctxt)
{
  return new pass_array_bounds (ctxt, pass_data_array_bounds);
}
