public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
@ 2021-06-21 22:25 Martin Sebor
  2021-06-28 19:33 ` [PING][PATCH] " Martin Sebor
  0 siblings, 1 reply; 11+ messages in thread
From: Martin Sebor @ 2021-06-21 22:25 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1041 bytes --]

-Warray-bounds relies on similar logic as -Wstringop-overflow et al.,
but using its own algorithm, including its own bugs such as PR 100137.
The attached patch takes the first step toward unifying the logic
between the warnings.  It changes a subset of -Warray-bounds to call
compute_objsize() to detect out-of-bounds indices.  Besides fixing
the bug this also nicely simplifies the code and improves
the consistency between the informational messages printed by both
classes of warnings.

The changes to the test suite are extensive mainly because of
the different format of the diagnostics resulting from slightly
tighter bounds of offsets computed by the new algorithm, and in
smaller part because the change lets -Warray-bounds diagnose some
problems it previously missed due to the limitations of its own
solution.

The false positive reported in PR 100137 is a 10/11/12 regression
but this change is too intrusive to backport.  I have a smaller
and more targeted patch I plan to backport in its stead.

Tested on x86_64-linux.

Martin

[-- Attachment #2: gcc-100137.diff --]
[-- Type: text/x-patch, Size: 78960 bytes --]

Correct handling of variable offset minus constant in -Warray-bounds [PR100137]

Resolves:
PR tree-optimization/100137 - -Warray-bounds false positive on varying offset plus negative
PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
PR tree-optimization/97027 - missing warning on buffer overflow storing a larger scalar into a smaller array

gcc/ChangeLog:

	* builtins.c (access_ref::access_ref): Also set offmax.
	(access_ref::offset_in_range): Define new function.
	(access_ref::add_offset): Set offmax.
	(access_ref::inform_access): Handle access_none.
	(handle_mem_ref): Clear ostype.
	(compute_objsize_r): Handle ASSERT_EXPR.
	* builtins.h (struct access_ref): Add offmax member.
	* gimple-array-bounds.cc (array_bounds_checker::check_mem_ref): Use
	compute_objsize() and simplify.

gcc/testsuite/ChangeLog:

	* c-c++-common/Warray-bounds-3.c: Remove xfail
	* c-c++-common/Warray-bounds-4.c: Add an expected warning.
	* g++.dg/warn/Warray-bounds-10.C: Adjust text of expected messages.
	* g++.dg/warn/Warray-bounds-11.C: Same.
	* g++.dg/warn/Warray-bounds-12.C: Same.
	* g++.dg/warn/Warray-bounds-13.C: Same.
	* g++.dg/warn/Warray-bounds-17.C: Same.
	* g++.dg/warn/Warray-bounds-20.C: Same.
	* gcc.dg/Warray-bounds-29.c: Same.
	* gcc.dg/Warray-bounds-30.c: Add xfail.
	* gcc.dg/Warray-bounds-31.c: Adjust text of expected messages.
	* gcc.dg/Warray-bounds-32.c: Same.
	* gcc.dg/Warray-bounds-52.c: Same.
	* gcc.dg/Warray-bounds-53.c: Same.
	* gcc.dg/Warray-bounds-58.c: Remove xfail.
	* gcc.dg/Warray-bounds-63.c: Adjust text of expected messages.
	* gcc.dg/Warray-bounds-66.c: Same.
	* gcc.dg/Warray-bounds-69.c: Same.
	* gcc.dg/Wstringop-overflow-34.c: Same.
	* gcc.dg/Wstringop-overflow-47.c: Same.
	* gcc.dg/Wstringop-overflow-61.c: Same.
	* gcc.dg/Warray-bounds-71.c: New test.
	* gcc.dg/Warray-bounds-72.c: New test.
	* gcc.dg/Warray-bounds-73.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 855ad1eb6bb..f39a7fd93e7 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -206,6 +206,7 @@ access_ref::access_ref (tree bound /* = NULL_TREE */,
 {
   /* Set to valid.  */
   offrng[0] = offrng[1] = 0;
+  offmax[0] = offmax[1] = 0;
   /* Invalidate.   */
   sizrng[0] = sizrng[1] = -1;
 
@@ -457,6 +458,21 @@ access_ref::size_remaining (offset_int *pmin /* = NULL */) const
   return sizrng[1] - or0;
 }
 
+/* Return true if the offset and object size are in range for SIZE.  */
+
+bool
+access_ref::offset_in_range (const offset_int &size) const
+{
+  if (size_remaining () < size)
+    return false;
+
+  if (base0)
+    return offmax[0] >= 0 && offmax[1] <= sizrng[1];
+
+  offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
+  return offmax[0] > -maxoff && offmax[1] < maxoff;
+}
+
 /* Add the range [MIN, MAX] to the offset range.  For known objects (with
    zero-based offsets) at least one of whose offset's bounds is in range,
    constrain the other (or both) to the bounds of the object (i.e., zero
@@ -493,6 +509,8 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max)
       if (max >= 0)
 	{
 	  offrng[0] = 0;
+	  if (offmax[0] > 0)
+	    offmax[0] = 0;
 	  return;
 	}
 
@@ -509,6 +527,12 @@ void access_ref::add_offset (const offset_int &min, const offset_int &max)
 	offrng[0] = 0;
     }
 
+  /* Set the minimum and maximmum computed so far. */
+  if (offrng[1] < 0 && offrng[1] < offmax[0])
+    offmax[0] = offrng[1];
+  if (offrng[0] > 0 && offrng[0] > offmax[1])
+    offmax[1] = offrng[0];
+
   if (!base0)
     return;
 
@@ -4575,23 +4599,46 @@ access_ref::inform_access (access_mode mode) const
       return;
     }
 
+  if (mode == access_read_only)
+    {
+      if (allocfn == NULL_TREE)
+	{
+	  if (*offstr)
+	    inform (loc, "at offset %s into source object %qE of size %s",
+		    offstr, ref, sizestr);
+	  else
+	    inform (loc, "source object %qE of size %s", ref, sizestr);
+
+	  return;
+	}
+
+      if (*offstr)
+	inform (loc,
+		"at offset %s into source object of size %s allocated by %qE",
+		offstr, sizestr, allocfn);
+      else
+	inform (loc, "source object of size %s allocated by %qE",
+		sizestr, allocfn);
+      return;
+    }
+
   if (allocfn == NULL_TREE)
     {
       if (*offstr)
-	inform (loc, "at offset %s into source object %qE of size %s",
+	inform (loc, "at offset %s into object %qE of size %s",
 		offstr, ref, sizestr);
       else
-	inform (loc, "source object %qE of size %s", ref, sizestr);
+	inform (loc, "object %qE of size %s", ref, sizestr);
 
       return;
     }
 
   if (*offstr)
     inform (loc,
-	    "at offset %s into source object of size %s allocated by %qE",
+	    "at offset %s into object of size %s allocated by %qE",
 	    offstr, sizestr, allocfn);
   else
-    inform (loc, "source object of size %s allocated by %qE",
+    inform (loc, "object of size %s allocated by %qE",
 	    sizestr, allocfn);
 }
 
@@ -5433,16 +5480,16 @@ handle_mem_ref (tree mref, int ostype, access_ref *pref,
 
   if (VECTOR_TYPE_P (TREE_TYPE (mref)))
     {
-      /* Hack: Give up for MEM_REFs of vector types; those may be
-	 synthesized from multiple assignments to consecutive data
-	 members (see PR 93200 and 96963).
+      /* Hack: Handle MEM_REFs of vector types as those to complete
+	 objects; those may be synthesized from multiple assignments
+	 to consecutive data members (see PR 93200 and 96963).
 	 FIXME: Vectorized assignments should only be present after
 	 vectorization so this hack is only necessary after it has
 	 run and could be avoided in calls from prior passes (e.g.,
 	 tree-ssa-strlen.c).
 	 FIXME: Deal with this more generally, e.g., by marking up
 	 such MEM_REFs at the time they're created.  */
-      return false;
+      ostype = 0;
     }
 
   tree mrefop = TREE_OPERAND (mref, 0);
@@ -5796,6 +5843,12 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref,
 
       tree rhs = gimple_assign_rhs1 (stmt);
 
+      if (code == ASSERT_EXPR)
+	{
+	  rhs = TREE_OPERAND (rhs, 0);
+	  return compute_objsize_r (rhs, ostype, pref, snlim, qry);
+	}
+
       if (code == POINTER_PLUS_EXPR
 	  && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE)
 	{
diff --git a/gcc/builtins.h b/gcc/builtins.h
index e71f40c300a..a64ece3f1cd 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -222,6 +222,9 @@ struct access_ref
      argument to the minimum.  */
   offset_int size_remaining (offset_int * = NULL) const;
 
+/* Return true if the offset and object size are in range for SIZE.  */
+  bool offset_in_range (const offset_int &) const;
+
   /* Return true if *THIS is an access to a declared object.  */
   bool ref_declared () const
   {
@@ -261,6 +264,8 @@ struct access_ref
   /* Range of byte offsets into and sizes of the object(s).  */
   offset_int offrng[2];
   offset_int sizrng[2];
+  /* The minimum and maximum offset computed.  */
+  offset_int offmax[2];
   /* Range of the bound of the access: denotes that the access
      is at least BNDRNG[0] bytes but no more than BNDRNG[1].
      For string functions the size of the actual access is
diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 199d9f5d216..668c3beb912 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -414,269 +414,72 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
   if (TREE_NO_WARNING (ref))
     return false;
 
-  tree arg = TREE_OPERAND (ref, 0);
-  /* The constant and variable offset of the reference.  */
-  tree cstoff = TREE_OPERAND (ref, 1);
-  tree varoff = NULL_TREE;
-
-  const offset_int maxobjsize = tree_to_shwi (max_object_size ());
-
-  /* The zero-based array or string constant bounds in bytes.  Initially
-     set to [-MAXOBJSIZE - 1, MAXOBJSIZE]  until a tighter bound is
-     determined.  */
-  offset_int arrbounds[2] = { -maxobjsize - 1, maxobjsize };
-
-  /* The minimum and maximum intermediate offset.  For a reference
-     to be valid, not only does the final offset/subscript must be
-     in bounds but all intermediate offsets should be as well.
-     GCC may be able to deal gracefully with such out-of-bounds
-     offsets so the checking is only enabled at -Warray-bounds=2
-     where it may help detect bugs in uses of the intermediate
-     offsets that could otherwise not be detectable.  */
-  offset_int ioff = wi::to_offset (fold_convert (ptrdiff_type_node, cstoff));
-  offset_int extrema[2] = { 0, wi::abs (ioff) };
-
-  /* The range of the byte offset into the reference.  */
-  offset_int offrange[2] = { 0, 0 };
-
   /* 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_CODE (axstype) != UNION_TYPE)
+    if (tree access_size = TYPE_SIZE_UNIT (axstype))
+      if (TREE_CODE (access_size) == INTEGER_CST)
+	axssize = wi::to_offset (access_size);
 
-  /* Determine the offsets and increment OFFRANGE for the bounds of each.
-     The loop computes the range of the final offset for expressions such
-     as (A + i0 + ... + iN)[CSTOFF] where i0 through iN are SSA_NAMEs in
-     some range.  */
-  const unsigned limit = param_ssa_name_def_chain_limit;
-  for (unsigned n = 0; TREE_CODE (arg) == SSA_NAME && n < limit; ++n)
-    {
-      gimple *def = SSA_NAME_DEF_STMT (arg);
-      if (is_gimple_call (def))
-	{
-	  /* Determine the byte size of the array from an allocation call.  */
-	  wide_int sizrng[2];
-	  if (gimple_call_alloc_size (def, sizrng))
-	    {
-	      arrbounds[0] = 0;
-	      arrbounds[1] = offset_int::from (sizrng[1], UNSIGNED);
-	      minbound = offset_int::from (sizrng[0], UNSIGNED);
-	      alloc_stmt = def;
-	    }
-	  break;
-	}
-
-      if (gimple_nop_p (def))
-	{
-	  /* For a function argument try to determine the byte size
-	     of the array from the current function declaratation
-	     (e.g., attribute access or related).  */
-	  wide_int wr[2];
-	  tree ref = gimple_parm_array_size (arg, wr);
-	  if (!ref)
-	    break;
-	  arrbounds[0] = offset_int::from (wr[0], UNSIGNED);
-	  arrbounds[1] = offset_int::from (wr[1], UNSIGNED);
-	  arg = ref;
-	  break;
-	}
-
-      if (!is_gimple_assign (def))
-	break;
-
-      tree_code code = gimple_assign_rhs_code (def);
-      if (code == POINTER_PLUS_EXPR)
-	{
-	  arg = gimple_assign_rhs1 (def);
-	  varoff = gimple_assign_rhs2 (def);
-	}
-      else if (code == ASSERT_EXPR)
-	{
-	  arg = TREE_OPERAND (gimple_assign_rhs1 (def), 0);
-	  continue;
-	}
-      else
-	return false;
-
-      /* VAROFF should always be a SSA_NAME here (and not even
-	 INTEGER_CST) but there's no point in taking chances.  */
-      if (TREE_CODE (varoff) != SSA_NAME)
-	break;
-
-      const value_range* const vr = get_value_range (varoff);
-      if (!vr || vr->undefined_p () || vr->varying_p ())
-	break;
-
-      if (!vr->constant_p ())
-	break;
-
-      if (vr->kind () == VR_RANGE)
-	{
-	  offset_int min
-	    = wi::to_offset (fold_convert (ptrdiff_type_node, vr->min ()));
-	  offset_int max
-	    = wi::to_offset (fold_convert (ptrdiff_type_node, vr->max ()));
-	  if (min < max)
-	    {
-	      offrange[0] += min;
-	      offrange[1] += max;
-	    }
-	  else
-	    {
-	      /* When MIN >= MAX, the offset is effectively in a union
-		 of two ranges: [-MAXOBJSIZE -1, MAX] and [MIN, MAXOBJSIZE].
-		 Since there is no way to represent such a range across
-		 additions, conservatively add [-MAXOBJSIZE -1, MAXOBJSIZE]
-		 to OFFRANGE.  */
-	      offrange[0] += arrbounds[0];
-	      offrange[1] += arrbounds[1];
-	    }
-	}
-      else
-	{
-	  /* For an anti-range, analogously to the above, conservatively
-	     add [-MAXOBJSIZE -1, MAXOBJSIZE] to OFFRANGE.  */
-	  offrange[0] += arrbounds[0];
-	  offrange[1] += arrbounds[1];
-	}
-
-      /* Keep track of the minimum and maximum offset.  */
-      if (offrange[1] < 0 && offrange[1] < extrema[0])
-	extrema[0] = offrange[1];
-      if (offrange[0] > 0 && offrange[0] > extrema[1])
-	extrema[1] = offrange[0];
-
-      if (offrange[0] < arrbounds[0])
-	offrange[0] = arrbounds[0];
-
-      if (offrange[1] > arrbounds[1])
-	offrange[1] = arrbounds[1];
-    }
+  access_ref aref;
+  if (!compute_objsize (ref, 1, &aref, ranges))
+    return false;
 
-  tree reftype = NULL_TREE;
-  offset_int eltsize = -1;
-  if (arrbounds[0] >= 0)
-    {
-      /* 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.  */
-      reftype = TREE_TYPE (TREE_TYPE (arg));
-      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);
-
-      if (eltsize < 0)
-	return false;
+  if (aref.offset_in_range (axssize))
+    return false;
 
-      offset_int nelts = arrbounds[1] / eltsize;
-      reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
-    }
-  else if (TREE_CODE (arg) == ADDR_EXPR)
+  if (TREE_CODE (aref.ref) == SSA_NAME)
     {
-      arg = TREE_OPERAND (arg, 0);
-      if (TREE_CODE (arg) != STRING_CST
-	  && TREE_CODE (arg) != PARM_DECL
-	  && TREE_CODE (arg) != VAR_DECL)
-	return false;
-
-      /* The type of the object being referred to.  It can be an array,
-	 string literal, or a non-array type when the MEM_REF represents
-	 a reference/subscript via a pointer to an object that is not
-	 an element of an array.  Incomplete types are excluded as well
-	 because their size is not known.  */
-      reftype = TREE_TYPE (arg);
-      if (POINTER_TYPE_P (reftype)
-	  || !COMPLETE_TYPE_P (reftype)
-	  || TREE_CODE (TYPE_SIZE_UNIT (reftype)) != INTEGER_CST)
-	return false;
-
-      /* Except in declared objects, references to trailing array members
-	 of structs and union objects are excluded because MEM_REF doesn't
-	 make it possible to identify the member where the reference
-	 originated.  */
-      if (RECORD_OR_UNION_TYPE_P (reftype)
-	  && (!VAR_P (arg)
-	      || (DECL_EXTERNAL (arg) && array_at_struct_end_p (ref))))
-	return false;
-
-      /* FIXME: Should this be 1 for Fortran?  */
-      arrbounds[0] = 0;
-
-      if (TREE_CODE (reftype) == ARRAY_TYPE)
-	{
-	  /* Set to the size of the array element (and adjust below).  */
-	  eltsize = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (reftype)));
-	  /* Use log2 of size to convert the array byte size in to its
-	     upper bound in elements.  */
-	  const offset_int eltsizelog2 = wi::floor_log2 (eltsize);
-	  if (tree dom = TYPE_DOMAIN (reftype))
-	    {
-	      tree bnds[] = { TYPE_MIN_VALUE (dom), TYPE_MAX_VALUE (dom) };
-	      if (TREE_CODE (arg) == COMPONENT_REF)
-		{
-		  offset_int size = maxobjsize;
-		  if (tree fldsize = component_ref_size (arg))
-		    size = wi::to_offset (fldsize);
-		  arrbounds[1] = wi::lrshift (size, eltsizelog2);
-		}
-	      else if (array_at_struct_end_p (arg) || !bnds[0] || !bnds[1])
-		arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
-	      else
-		arrbounds[1] = (wi::to_offset (bnds[1]) - wi::to_offset (bnds[0])
-				+ 1) * eltsize;
-	    }
-	  else
-	    arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
-
-	  /* Determine a tighter bound of the non-array element type.  */
-	  tree eltype = TREE_TYPE (reftype);
-	  while (TREE_CODE (eltype) == ARRAY_TYPE)
-	    eltype = TREE_TYPE (eltype);
-	  eltsize = wi::to_offset (TYPE_SIZE_UNIT (eltype));
-	}
-      else
+      gimple *def = SSA_NAME_DEF_STMT (aref.ref);
+      if (is_gimple_call (def))
 	{
-	  eltsize = 1;
-	  tree size = TYPE_SIZE_UNIT (reftype);
-	  if (VAR_P (arg))
-	    if (tree initsize = DECL_SIZE_UNIT (arg))
-	      if (tree_int_cst_lt (size, initsize))
-		size = initsize;
-
-	  arrbounds[1] = wi::to_offset (size);
+	  /* Save the allocation call and the low bound on the size.  */
+	  alloc_stmt = def;
+	  minbound = aref.sizrng[0];
 	}
     }
-  else
-    return false;
-
-  offrange[0] += ioff;
-  offrange[1] += ioff;
+			
+  /* 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;
+  /* 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 (POINTER_TYPE_P (reftype))
+    reftype = TREE_TYPE (reftype);
+  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 = arrbounds[1];
+  offset_int ubound = aref.sizrng[1];
   if (ignore_off_by_one)
     ubound += eltsize;
 
-  bool warned = false;
   /* Set if the lower bound of the subscript is out of bounds.  */
-  const bool lboob = (arrbounds[0] == arrbounds[1]
+  const bool lboob = (aref.sizrng[1] == 0
 		      || offrange[0] >= ubound
-		      || offrange[1] < arrbounds[0]);
+		      || 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.  */
-  tree axstype = TREE_TYPE (ref);
-  offset_int axssize = 0;
-  if (TREE_CODE (axstype) != UNION_TYPE)
-    if (tree access_size = TYPE_SIZE_UNIT (axstype))
-      if (TREE_CODE (access_size) == INTEGER_CST)
-	axssize = wi::to_offset (access_size);
-
   const bool uboob = !lboob && offrange[0] + axssize > ubound;
   if (lboob || uboob)
     {
@@ -689,9 +492,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	 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 = TREE_TYPE (ref);
-      while (TREE_CODE (type) == ARRAY_TYPE)
-	type = TREE_TYPE (type);
+      tree type = strip_array_types (TREE_TYPE (ref));
       if (tree size = TYPE_SIZE_UNIT (type))
 	{
 	  offrange[0] = offrange[0] / wi::to_offset (size);
@@ -699,6 +500,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	}
     }
 
+  bool warned = false;
   if (lboob)
     {
       if (offrange[0] == offrange[1])
@@ -720,7 +522,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	/* 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,
-					   arrbounds[1].to_uhwi ());
+					   aref.sizrng[1].to_uhwi ());
 
       warned = warning_at (location, OPT_Warray_bounds,
 			   "array subscript %<%T[%wi]%> is partly "
@@ -730,46 +532,8 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 
   if (warned)
     {
-      if (DECL_P (arg))
-	inform (DECL_SOURCE_LOCATION (arg), "while referencing %qD", arg);
-      else if (alloc_stmt)
-	{
-	  location_t loc = gimple_location (alloc_stmt);
-	  if (gimple_call_builtin_p (alloc_stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
-	    {
-	      if (minbound == arrbounds[1])
-		inform (loc, "referencing a variable length array "
-			"of size %wu", minbound.to_uhwi ());
-	      else
-		inform (loc, "referencing a variable length array "
-			"of size between %wu and %wu",
-			minbound.to_uhwi (), arrbounds[1].to_uhwi ());
-	    }
-	  else if (tree fndecl = gimple_call_fndecl (alloc_stmt))
-	    {
-	      if (minbound == arrbounds[1])
-		inform (loc, "referencing an object of size %wu "
-			"allocated by %qD",
-			minbound.to_uhwi (), fndecl);
-	      else
-		inform (loc, "referencing an object of size between "
-			"%wu and %wu allocated by %qD",
-			minbound.to_uhwi (), arrbounds[1].to_uhwi (), fndecl);
-	    }
-	  else
-	    {
-	      tree fntype = gimple_call_fntype (alloc_stmt);
-	      if (minbound == arrbounds[1])
-		inform (loc, "referencing an object of size %wu "
-			"allocated by %qT",
-			minbound.to_uhwi (), fntype);
-	      else
-		inform (loc, "referencing an object of size between "
-			"%wu and %wu allocated by %qT",
-			minbound.to_uhwi (), arrbounds[1].to_uhwi (), fntype);
-	    }
-	}
-
+      /* TODO: Determine the access from the statement and use it.  */
+      aref.inform_access (access_none);
       TREE_NO_WARNING (ref) = 1;
       return true;
     }
@@ -779,9 +543,9 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 
   /* At level 2 check also intermediate offsets.  */
   int i = 0;
-  if (extrema[i] < -arrbounds[1] || extrema[i = 1] > ubound)
+  if (aref.offmax[i] < -aref.sizrng[1] || aref.offmax[i = 1] > ubound)
     {
-      HOST_WIDE_INT tmpidx = extrema[i].to_shwi () / eltsize.to_shwi ();
+      HOST_WIDE_INT tmpidx = aref.offmax[i].to_shwi () / eltsize.to_shwi ();
 
       if (warning_at (location, OPT_Warray_bounds,
 		      "intermediate array offset %wi is outside array bounds "
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-10.c b/gcc/testsuite/c-c++-common/Warray-bounds-10.c
new file mode 100644
index 00000000000..cfe9a383410
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-10.c
@@ -0,0 +1,114 @@
+/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array
+   element of empty structs
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+struct S
+{
+#if SOME_CONFIG_MACRO
+  /* Suppose the contents are empty in the development configuration
+     but non-empty in others.  Out of bounds accesses to elements of
+     the arrays below should be diagnosed in all configurations,
+     including when S is empty, even if they are folded away.  */
+  int member;
+#endif
+};
+
+extern struct S sa3[3];
+extern struct S sa2_3[2][3];
+extern struct S sa3_4_5[3][4][5];
+
+void sink (void*);
+
+
+void access_sa3 (struct S s)
+{
+  sa3[0] = s;
+  sa3[1] = s;
+  sa3[2] = s;
+  sa3[3] = s;       // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+void access_sa3_ptr (struct S s)
+{
+  struct S *p = &sa3[0];
+
+  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[3] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+void access_sa2_3_ptr (struct S s)
+{
+  struct S *p = &sa2_3[0][0];
+
+  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[6] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+void access_sa3_4_5_ptr (struct S s, int i)
+{
+  struct S *p = &sa3_4_5[0][0][0];
+
+  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[60] = s;        // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+
+void access_vla3 (struct S s, unsigned n)
+{
+  struct S vla3[3 < n ? 3 : n];
+
+  vla3[0] = s;
+  vla3[1] = s;
+  vla3[2] = s;
+  vla3[3] = s;       // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla3);
+}
+
+void access_vla3_ptr (struct S s, unsigned n)
+{
+  struct S vla3[3 < n ? 3 : n];
+  struct S *p = &vla3[0];
+
+  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[3] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla3);
+}
+
+void access_vla2_3_ptr (struct S s, unsigned n)
+{
+  struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n];
+  struct S *p = &vla2_3[0][0];
+
+  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[6] = s;         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla2_3);
+}
+
+void access_vla3_4_5_ptr (struct S s, unsigned n)
+{
+  struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n];
+  struct S *p = &vla3_4_5[0][0][0];
+
+  p[0] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = s;         // { dg-bogus "\\\[-Warray-bounds" }
+  p[60] = s;        // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla3_4_5);
+}
+
+// { dg-prune-output "empty struct has size 0 in C" }
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
index aae4999ea13..3d7c7687374 100644
--- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
@@ -158,7 +158,7 @@ void test_memcpy_overflow (char *d, const char *s, size_t n)
      but known access size is detected.  This works except with small
      sizes that are powers of 2 due to bug .  */
   T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 1);
-  T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2);  /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 2 accessing array " "bug " { xfail non_strict_align } } */
+  T (char, 1, arr + SR (DIFF_MAX - 1, DIFF_MAX), s, 2);  /* { dg-warning "\\\[-Warray-bounds" } */
   T (char, 1, arr + SR (DIFF_MAX - 2, DIFF_MAX), s, 3);  /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 3 accessing array " "memcpy" } */
   T (char, 1, arr + SR (DIFF_MAX - 4, DIFF_MAX), s, 5);  /* { dg-warning "pointer overflow between offset \\\[\[0-9\]+, \[0-9\]+] and size 5 accessing array " "memcpy" } */
 }
@@ -178,7 +178,7 @@ void test_memcpy_bounds_memarray_range (void)
 
   TM (ma.a5, ma.a5 + i, ma.a5, 1);
   TM (ma.a5, ma.a5 + i, ma.a5, 3);
-  TM (ma.a5, ma.a5 + i, ma.a5, 5);
+  TM (ma.a5, ma.a5 + i, ma.a5, 5);     /* { dg-warning "\\\[-Warray-bounds" } */
   TM (ma.a5, ma.a5 + i, ma.a5, 7);     /* diagnosed with -Warray-bounds=2 */
 }
 
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-4.c b/gcc/testsuite/c-c++-common/Warray-bounds-4.c
index 22a23a12651..1f73f11943f 100644
--- a/gcc/testsuite/c-c++-common/Warray-bounds-4.c
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-4.c
@@ -43,7 +43,17 @@ void test_memcpy_bounds_memarray_range (void)
 
   TM (ma.a5, ma.a5 + j, ma.a5, 1);
   TM (ma.a5, ma.a5 + j, ma.a5, 3);
-  TM (ma.a5, ma.a5 + j, ma.a5, 5);
+
+  /* The copy below is invalid for two reasons: 1) it overlaps and 2) it
+     writes past the end of ma.a5.  The warning is a little cryptic here
+     because the GIMPLE is:
+       _4 = &ma.a5 + prephitmp_14;
+       MEM <unsigned char[5]> [(char * {ref-all})_4]
+         = MEM <unsigned char[5]> [(char * {ref-all})&ma];
+     and could be improved.  Just verify that one is issued but not its
+     full text.  */
+  TM (ma.a5, ma.a5 + j, ma.a5, 5);        /* { dg-warning "\\\[-Warray-bounds" } */
+
   TM (ma.a5, ma.a5 + j, ma.a5, 7);        /* { dg-warning "offset \\\[5, 7] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */
   TM (ma.a5, ma.a5 + j, ma.a5, 9);        /* { dg-warning "offset \\\[5, 9] from the object at .ma. is out of the bounds of referenced subobject .\(MA::\)?a5. with type .char ?\\\[5]. at offset 0" } */
 }
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-9.c b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
new file mode 100644
index 00000000000..8ff592b363c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
@@ -0,0 +1,144 @@
+/* PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
+   VLA
+   { dg-do compile }
+   { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */
+
+#define NOIPA __attribute__ ((noipa))
+
+void sink (void*, ...);
+#define T(a, x) sink (a, x)
+
+
+NOIPA void a_0_n (int n)
+{
+  int a[0][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_0 (int n)
+{
+  int a[n][0];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+NOIPA void a_1_n_0 (int n)
+{
+  int a[1][n][0];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_1_0_n (int n)
+{
+  int a[1][0][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_1_n (int n)
+{
+  int a[0][1][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_n_1 (int n)
+{
+  int a[0][n][1];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_0_n (int n)
+{
+  int a[n][0][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_n_0 (int n)
+{
+  int a[n][n][0];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_n_n (int n)
+{
+  int a[0][n][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_0_0_n (int n)
+{
+  int a[0][0][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_0_0 (int n)
+{
+  int a[n][0][0];
+
+  sink (a);
+
+  T (a, ((int *) a)[0]);      // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((char *) a)[1]);     // { dg-warning "\\\[-Warray-bounds" }
+  T (a, ((float *) a)[n]);    // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void a_n_n_n (int n)
+{
+  int a[n][n][n];
+
+  sink (a);
+
+  T (a, ((int *) a)[-1]);     // { dg-warning "\\\[-Warray-bounds" "pr99140" { xfail *-*-* } }
+  T (a, ((int *) a)[0]);
+  T (a, ((char *) a)[1]);
+  T (a, ((float *) a)[n]);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C
index 4deea31fae0..4b758aadaa1 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-10.C
@@ -18,7 +18,7 @@ void sink (void*);
 void warn_op_new ()
 {
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
@@ -44,7 +44,7 @@ void warn_op_array_new ()
 #define OP_NEW(n)  operator new[] (n)
 
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C
index 45d271948e8..70b39122f78 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-11.C
@@ -20,7 +20,7 @@ void sink (void*);
 void warn_op_new ()
 {
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(std::size_t, const std::nothrow_t.\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
@@ -46,7 +46,7 @@ void warn_op_array_new ()
 #define OP_NEW(n)  operator new[] (n, std::nothrow)
 
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(std::size_t, const std::nothrow_t&\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C
index 3f1555b9e1b..07fa351a86c 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-12.C
@@ -20,7 +20,7 @@ void sink (void*);
 void warn_new ()
 {
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
@@ -46,7 +46,7 @@ void warn_array_new ()
 #define NEW(n)  new char [n]
 
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(\(long \)?unsigned int\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C
index 890620dc70a..2d3e9dcfd68 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-13.C
@@ -24,7 +24,7 @@ void sink (void*);
 void warn_nothrow_new ()
 {
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new\\\(std::size_t, const std::nothrow_t.\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
@@ -50,7 +50,7 @@ void warn_nothrow_array_new ()
 #define NEW(n)  new (std::nothrow) char [n]
 
   T (int32_t, 0, 0);          // { dg-warning "array subscript 0 is outside array bounds of 'int32_t \\\[0]'" }
-                              // { dg-message "referencing an object of size \\d allocated by 'void\\\* operator new \\\[]\\\(std::size_t, const std::nothrow_t&\\\)'" "note" { target *-*-* } .-1 }
+                              // { dg-message "object of size \\d allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" { target *-*-* } .-1 }
   T (int32_t, 1, 0);          // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[1]'" }
   T (int32_t, 2, 0);         //  { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[2]'" }
   T (int32_t, 3, 0);         // { dg-warning "array subscript 'int32_t {aka (long )?int}\\\[0]' is partly outside array bounds of 'unsigned char \\\[3]'" }
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C
index 64fbd080123..518f9bb26fa 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C
@@ -8,7 +8,7 @@ void foo (int *);
 void
 bar (void)
 {
-  A b;			// { dg-message "while referencing" }
+  A b;			// { dg-message "at offset -\\d into object 'b' of size 4" "note" }
   int *p = &b;
   int *x = (p - 1);	// { dg-warning "outside array bounds" }
   foo (x);
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C
index e142ea16787..a65b29e6269 100644
--- a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C
@@ -35,7 +35,7 @@ void sink (void*);
 
 void warn_derived_ctor_access_new_decl ()
 {
-  char a[sizeof (D1)];        // { dg-message "referencing 'a'" "note" }
+  char a[sizeof (D1)];        // { dg-message "at offset 1 into object 'a' of size 40" "note" }
   char *p = a;
   ++p;
   D1 *q = new (p) D1;
@@ -44,7 +44,7 @@ void warn_derived_ctor_access_new_decl ()
 
 void warn_derived_ctor_access_new_alloc ()
 {
-  char *p = (char*)operator new (sizeof (D1));    // { dg-message "referencing an object of size \\d+ allocated by 'void\\\* operator new\\\(" "note" }
+  char *p = (char*)operator new (sizeof (D1));    // { dg-message "at offset 1 into object of size \\d+ allocated by '\[^\n\r]*operator new\[^\n\r]*'" "note" }
   ++p;
   D1 *q = new (p) D1;
   sink (q);
@@ -52,7 +52,7 @@ void warn_derived_ctor_access_new_alloc ()
 
 void warn_derived_ctor_access_new_array_decl ()
 {
-  char b[sizeof (D1) * 2];    // { dg-message "referencing 'b'" "note" }
+  char b[sizeof (D1) * 2];    // { dg-message "at offset \\d+ into object 'b' of size 80" "note" }
   char *p = b;
   ++p;
   D1 *q = new (p) D1[2];
@@ -61,7 +61,7 @@ void warn_derived_ctor_access_new_array_decl ()
 
 void warn_derived_ctor_access_new_array_alloc ()
 {
-  char *p = new char[sizeof (D1) * 2];            // { dg-message "referencing an object of size \\d+ allocated by 'void\\\* operator new \\\[]\\\(" "note" }
+  char *p = new char[sizeof (D1) * 2];            // { dg-message "at offset \\d+ into object of size \\d+ allocated by '\[^\n\r]*operator new\[^\n\r]*" "note" }
   ++p;
   D1 *q = new (p) D1[2];
   sink (q);
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-29.c b/gcc/testsuite/gcc.dg/Warray-bounds-29.c
index 72c5d1cecf8..44e5bd36127 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-29.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-29.c
@@ -44,7 +44,7 @@ void test_narrow (void)
   T (p1[-1]);
   T (p1[ 0]);
   T (p1[ 1]);
-  T (p1[ 2]);                 /* { dg-warning "array subscript \\\[3, 4] is outside array bounds of .char\\\[3]." } */
+  T (p1[ 2]);                 /* { dg-warning "array subscript 3 is outside array bounds of .char\\\[3]." } */
   T (p1[ 3]);                 /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .char\\\[3]." } */
 
   T (&p1[-3]);                /* { dg-warning "array subscript \\\[-2, -1] is outside array bounds of .char\\\[3]." "bug" { xfail *-*-* } } */
@@ -55,7 +55,7 @@ void test_narrow (void)
   T (&p1[ 2]);
   T (&p1[ 3]);                /* { dg-warning "array subscript \\\[4, 6] is outside array bounds of .char\\\[3]." "bug" { xfail *-*-* } } */
 
-  T (p2[-4]);                 /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */
+  T (p2[-4]);                 /* { dg-warning "subscript \\\[-2, -1\\\] is outside array bounds of .char\\\[3]." } */
   T (p2[-3]);
   T (p2[-2]);
   T (p2[-1]);
@@ -64,19 +64,19 @@ void test_narrow (void)
   /* Even though the lower bound of p3's offsets is in bounds, in order
      to subtract 4 from p3 and get a dereferenceable pointer its value
      would have to be out-of-bounds.  */
-  T (p3[-4]);                 /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */
+  T (p3[-4]);                 /* { dg-warning "array subscript -1 is outside array bounds of .char\\\[3]." } */
   T (p3[-3]);
   T (p3[-2]);
   T (p3[-1]);
-  T (p3[ 0]);                 /* { dg-warning "array subscript \\\[3, 6] is outside array bounds of .char\\\[3]." } */
+  T (p3[ 0]);                 /* { dg-warning "array subscript 3 is outside array bounds of .char\\\[3]." } */
 
   T (p4[-4]);                 /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */
   T (p4[-3]);                 /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */
   T (p4[-2]);                 /* { dg-warning "intermediate array offset 4 is outside array bounds of .char\\\[3]." } */
 
   /* The final subscripts below are invalid.  */
-  T (p4[-1]);                 /* { dg-warning "array subscript \\\[3, 7] is outside array bounds of .char\\\[3]." } */
-  T (p4[ 0]);                 /* { dg-warning "array subscript \\\[4, 8] is outside array bounds of .char\\\[3]." } */
+  T (p4[-1]);                 /* { dg-warning "array subscript 3 is outside array bounds of .char\\\[3]." } */
+  T (p4[ 0]);                 /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .char\\\[3]." } */
 }
 
 
@@ -114,7 +114,7 @@ void test_wide (void)
   T (p1[ 0]);
   T (p1[ 1]);
   T (p1[ 2]);
-  T (p1[ 3]);                  /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .\[a-z \]+\\\[4]." } */
+  T (p1[ 3]);                  /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */
 
   T (&p1[-1]);
   T (&p1[ 0]);
@@ -133,18 +133,18 @@ void test_wide (void)
   /* Even though the lower bound of p3's offsets is in bounds, in order
      to subtract 5 from p3 and get a dereferenceable pointer its value
      would have to be out-of-bounds.  */
-  T (p3[-5]);                 /* { dg-warning "intermediate array offset 5 is outside array bounds of .\[a-z \]+\\\[4]." } */
+  T (p3[-5]);                 /* { dg-warning "array subscript \\\[-2, -1\\\] is outside array bounds of .\[a-z \]+\\\[4]." } */
   T (p3[-4]);
   T (p3[-3]);
   T (p3[-2]);
   T (p3[-1]);
   T (p3[ 0]);
-  T (p3[ 1]);                 /* { dg-warning "array subscript \\\[4, 7] is outside array bounds of .\[a-z \]+\\\[4]." } */
+  T (p3[ 1]);                 /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */
 
-  T (p4[-5]);                 /* { dg-warning "intermediate array offset 5 is outside array bounds of .\[a-z \]+\\\[4]." } */
+  T (p4[-5]);                 /* { dg-warning "array subscript -1 is outside array bounds of .\[a-z \]+\\\[4]." } */
   T (p4[-4]);
   T (p4[-3]);
   T (p4[-2]);
   T (p4[-1]);
-  T (p4[ 0]);                 /* { dg-warning "array subscript \\\[4, 8] is outside array bounds of .\[a-z \]+\\\[4]." } */
+  T (p4[ 0]);                 /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */
 }
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-30.c b/gcc/testsuite/gcc.dg/Warray-bounds-30.c
index 048a95d6dcf..b837ad0c36c 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-30.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-30.c
@@ -120,7 +120,7 @@ void test_global_short_2dim_array (void)
   T (&p[1]);
   T (&p[2]);
   T (&p[3]);
-  T (&p[16]);       /* { dg-warning "subscript 16 is \(above|outside\) array bounds of .short int\\\[3]" } */
+  T (&p[16]);       /* { dg-warning "subscript 16 is \(above|outside\) array bounds of .short int\\\[3]" "pr??????" { xfail *-*-* } } */
   T (&p[MAX]);      /* { dg-warning "subscript -?\[0-9\]+ is \(above|outside\) array bounds of .short int\\\[3]" } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-31.c b/gcc/testsuite/gcc.dg/Warray-bounds-31.c
index 389afaf045d..921461a549d 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-31.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-31.c
@@ -174,7 +174,7 @@ void narrow_ptr_deref_range (ptrdiff_t i, size_t j)
   T (*p);
 
   p = S1 + SR (2, 3);
-  T (*p);                     /* { dg-warning "array subscript \\\[2, 3] is outside array bounds of .char\\\[2]." } */
+  T (*p);                     /* { dg-warning "array subscript 2 is outside array bounds of .char\\\[2]." } */
 
   p = S1 + SR (9, 99);
   T (*p);                     /* { dg-warning "array subscript \\\[9, 99] is outside array bounds of .char\\\[2]." } */
@@ -198,7 +198,7 @@ void narrow_ptr_deref_range (ptrdiff_t i, size_t j)
   T (*p);
 
   p = S8 + SR (9, 123);
-  T (*p);                     /* { dg-warning "array subscript \\\[9, 123] is outside array bounds of .char\\\[9]." } */
+  T (*p);                     /* { dg-warning "array subscript 9 is outside array bounds of .char\\\[9]." } */
 
   {
     const char *p1 = S3 + i;
@@ -226,7 +226,7 @@ void narrow_ptr_deref_range (ptrdiff_t i, size_t j)
     T (*p1);
     T (*p2);
     T (*p3);
-    T (*p4);                  /* { dg-warning "array subscript \\\[4, \[0-9\]+] is outside array bounds of .char\\\[4]." } */
+    T (*p4);                  /* { dg-warning "array subscript 4 is outside array bounds of .char\\\[4]." } */
     T (*p5);                  /* { dg-warning "array subscript \\\[5, \[0-9\]+] is outside array bounds of .char\\\[4]." } */
   }
 }
@@ -241,7 +241,7 @@ void narrow_ptr_index_range (void)
   T (p[SR (-8, 0)]);
   T (p[SR (0, MAX)]);
   T (p[SR (1, 9)]);
-  T (p[SR (8, 9)]);           /* { dg-warning "array subscript \\\[8, 9] is outside array bounds of .char\\\[8]." } */
+  T (p[SR (8, 9)]);           /* { dg-warning "array subscript 8 is outside array bounds of .char\\\[8]." } */
 
   p = S7 + SR (4, 6);
   T (p[5]);                   /* { dg-warning "array subscript \\\[9, 11] is outside array bounds of .char\\\[8]." } */
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-32.c b/gcc/testsuite/gcc.dg/Warray-bounds-32.c
index 9b5f3331735..02dac652211 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-32.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-32.c
@@ -87,7 +87,7 @@ void wide_ptr_deref_range (ptrdiff_t i, size_t j)
   T (*p);
 
   p = W8 + SR (9, 123);
-  T (*p);                     /* { dg-warning "array subscript \\\[9, 123] is outside array bounds of .\[a-z \]+\\\[9]." } */
+  T (*p);                     /* { dg-warning "array subscript 9 is outside array bounds of .\[a-z \]+\\\[9]." } */
 }
 
 void wide_ptr_index_range (void)
@@ -99,7 +99,7 @@ void wide_ptr_index_range (void)
   T (p[SR (-8, 0)]);
   T (p[SR (0, MAX)]);
   T (p[SR (1, 9)]);
-  T (p[SR (8, 9)]);           /* { dg-warning "array subscript \\\[8, 9] is outside array bounds of .\[a-z \]+\\\[8]." } */
+  T (p[SR (8, 9)]);           /* { dg-warning "array subscript 8 is outside array bounds of .\[a-z \]+\\\[8]." } */
 
   p = W7 + SR (4, 6);
   T (p[5]);                   /* { dg-warning "array subscript \\\[9, 11] is outside array bounds of .\[a-z \]+\\\[8]." } */
@@ -123,7 +123,7 @@ void wide_ptr_index_range_1 (void)
     int i = SR (1, 2);
     const wchar_t *p1 = W2 + i;
 
-    T (p1[2]);                /* { dg-warning "array subscript \\\[3, 4] is outside array bounds of .\[a-z \]+\\\[3]." } */
+    T (p1[2]);                /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */
   }
 }
 
@@ -140,17 +140,17 @@ void wide_ptr_index_range_chain (void)
     T (p1[-1]);
     T (p1[0]);
     T (p1[1]);
-    T (p1[2]);                /* { dg-warning "array subscript \\\[3, 4] is outside array bounds of .\[a-z \]+\\\[3]." } */
+    T (p1[2]);                /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */
 
-    T (p2[-5]);               /* { dg-warning "array subscript \\\[-3, -1] is outside array bounds of .\[a-z \]+\\\[3]." } */
-    T (p2[-4]);
+    T (p2[-5]);               /* { dg-warning "array subscript \\\[-3, -2] is outside array bounds of .\[a-z \]+\\\[3]." } */
+    T (p2[-4]);               /* { dg-warning "array subscript \\\[-2, -1] is outside array bounds of .\[a-z \]+\\\[3]." } */
     T (p2[-1]);
     T (p2[0]);
-    T (p2[1]);                /* { dg-warning "array subscript \\\[3, 5] is outside array bounds of .\[a-z \]+\\\[3]." } */
+    T (p2[1]);                /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */
 
-    T (p3[0]);                /* { dg-warning "array subscript \\\[3, 6] is outside array bounds of .\[a-z \]+\\\[3]." } */
-    T (p3[1]);                /* { dg-warning "array subscript \\\[4, 7] is outside array bounds of .\[a-z \]+\\\[3]." } */
-    T (p3[9999]);             /* { dg-warning "array subscript \\\[10002, 10005] is outside array bounds of .\[a-z \]+\\\[3]." "" { target size20plus} } */
+    T (p3[0]);                /* { dg-warning "array subscript 3 is outside array bounds of .\[a-z \]+\\\[3]." } */
+    T (p3[1]);                /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[3]." } */
+    T (p3[9999]);             /* { dg-warning "array subscript 10002 is outside array bounds of .\[a-z \]+\\\[3]." "" { target size20plus} } */
     /* { dg-warning "array subscript \\\[-6382, -6379] is outside array bounds of .\[a-z \]+\\\[3]." "" { target { ! size20plus } } .-1 } */
     /* Large offsets are indistinguishable from negative values.  */
     T (p3[DIFF_MAX]);         /* { dg-warning "array subscript" "bug" { xfail *-*-* } } */
@@ -166,9 +166,9 @@ void wide_ptr_index_range_chain (void)
     T (p1[-2]);
     T (p1[1]);
     T (p1[2]);
-    T (p1[3]);                /* { dg-warning "array subscript \\\[4, 5] is outside array bounds of .\[a-z \]+\\\[4]." } */
+    T (p1[3]);                /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */
 
-    T (p3[1]);                /* { dg-warning "array subscript \\\[4, 7] is outside array bounds of .\[a-z \]+\\\[4]." } */
+    T (p3[1]);                /* { dg-warning "array subscript 4 is outside array bounds of .\[a-z \]+\\\[4]." } */
   }
 }
 
@@ -180,5 +180,5 @@ void wide_ptr_index_range_4 (void)
   const wchar_t *p3 = p2 + i;
   const wchar_t *p4 = p3 + i;
 
-  T (p4[1]);                  /* { dg-warning "array subscript \\\[5, 9] is outside array bounds of .\[a-z \]+\\\[5]." } */
+  T (p4[1]);                  /* { dg-warning "array subscript 5 is outside array bounds of .\[a-z \]+\\\[5]." } */
 }
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-52.c b/gcc/testsuite/gcc.dg/Warray-bounds-52.c
index 729ad45d6ac..c7217ad4f7b 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-52.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-52.c
@@ -83,17 +83,17 @@ void ptr_idx_range (void)
 
   i = SR (0, 1);
 
-  T (i, (int[]){ });            // { dg-warning "array subscript \\\[0, 1] is outside array bounds of 'int\\\[0]'" }
+  T (i, (int[]){ });            // { dg-warning "array subscript 0 is outside array bounds of 'int\\\[0]'" }
   T (i, (int[]){ 1 });
 
   i = SR (1, 2);
-  T (i, (int[]){ 1 });          // { dg-warning "array subscript \\\[1, 2] is outside array bounds of 'int\\\[1]'" }
+  T (i, (int[]){ 1 });          // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[1]'" }
 
   i = SR (2, 3);
   T (i, (int[]){ 1, 2, 3 });
 
   i = SR (3, 4);
-  T (i, (int[]){ 2, 3, 4 });          // { dg-warning "array subscript \\\[3, 4] is outside array bounds of 'int\\\[3]'" }
+  T (i, (int[]){ 2, 3, 4 });          // { dg-warning "array subscript 3 is outside array bounds of 'int\\\[3]'" }
 }
 
 /* Some of the invalid accesses above also trigger -Wuninitialized.
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-53.c b/gcc/testsuite/gcc.dg/Warray-bounds-53.c
index 80db314b393..591cca28d27 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-53.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-53.c
@@ -83,17 +83,17 @@ void ptr_idx_range (void)
 
   i = SR (0, 1);
 
-  T (i, (int[]){ });            // { dg-warning "array subscript \\\[0, 1] is outside array bounds of 'int\\\[0]'" }
+  T (i, (int[]){ });            // { dg-warning "array subscript 0 is outside array bounds of 'int\\\[0]'" }
   T (i, (int[]){ 1 });
 
   i = SR (1, 2);
-  T (i, (int[]){ 1 });          // { dg-warning "array subscript \\\[1, 2] is outside array bounds of 'int\\\[1]'" }
+  T (i, (int[]){ 1 });          // { dg-warning "array subscript 1 is outside array bounds of 'int\\\[1]'" }
 
   i = SR (2, 3);
   T (i, (int[]){ 1, 2, 3 });
 
   i = SR (3, 4);
-  T (i, (int[]){ 2, 3, 4 });          // { dg-warning "array subscript \\\[3, 4] is outside array bounds of 'int\\\[3]'" }
+  T (i, (int[]){ 2, 3, 4 });          // { dg-warning "array subscript 3 is outside array bounds of 'int\\\[3]'" }
 }
 
 /* Some of the invalid accesses above also trigger -Wuninitialized.
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-58.c b/gcc/testsuite/gcc.dg/Warray-bounds-58.c
index 849457e559f..616145b65a6 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-58.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-58.c
@@ -36,7 +36,7 @@ extern struct Ax ax;
 
 void fax_extern (void)
 {
-  sink (strlen (ax.a - 2));     // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
+  sink (strlen (ax.a - 2));     // { dg-warning "\\\[-Warray-bounds" "pr93514" }
   sink (strlen (ax.a - 1));     // { dg-warning "\\\[-Warray-bounds" "pr93514" { xfail *-*-* } }
   sink (strlen (ax.a));
   sink (strlen (ax.a + 123));
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-63.c b/gcc/testsuite/gcc.dg/Warray-bounds-63.c
index a3fc9188211..530e2c56452 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-63.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-63.c
@@ -14,7 +14,7 @@ void sink (void*);
 
 void byte_store_to_decl (void)
 {
-  struct S6 { char a[6]; } s;   // { dg-message "referencing 's'" }
+  struct S6 { char a[6]; } s;   // { dg-message "at offset 6 into object 's' of size 6" "note" }
 
   char *p = (char*)&s;
 
@@ -27,7 +27,7 @@ void byte_store_to_decl (void)
 
 void word_store_to_decl (void)
 {
-  struct S6 { char a[6]; } s;   // { dg-message "referencing 's'" }
+  struct S6 { char a[6]; } s;   // { dg-message "at offset 5 into object 's' of size 6" "note" }
 
   char *p = (char*)&s;
 
@@ -43,7 +43,7 @@ void word_store_to_decl (void)
 void word_store_to_alloc (void)
 {
   struct S6 { char a[6]; } *p;
-  p = alloca (sizeof *p);       // { dg-message "referencing an object of size 6 allocated by 'alloca'" }
+  p = alloca (sizeof *p);       // { dg-message "at offset 5 into object of size 6 allocated by 'alloca'" "note" }
 
   int16_t *q = (int16_t*)((char*)p + 1);
 
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-66.c b/gcc/testsuite/gcc.dg/Warray-bounds-66.c
index c61891f5c07..6ab3398c762 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-66.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-66.c
@@ -117,14 +117,14 @@ void test_alloca_int16_range (unsigned n)
   }
 
   {
-    p = alloca (UR (0, 1));   // { dg-message "object of size between 0 and 1 allocated by '__builtin_alloca'" }
+    p = alloca (UR (0, 1));   // { dg-message "at offset \\d+ into object of size \\\[0, 1] allocated by '__builtin_alloca'" "note" }
     sink (p);
     T (p[0]);                 // { dg-warning "subscript 'int16_t {aka short int}\\\[0\\\]' is partly outside array bounds of 'unsigned char\\\[1]'" }
     T (p[1]);                 // { dg-warning "subscript 1 is outside array bounds of 'int16_t\\\[0]'" }
   }
 
   {
-    p = alloca (UR (0, 2));   // { dg-message "object of size between 0 and 2 allocated by '__builtin_alloca'" }
+    p = alloca (UR (0, 2));   // { dg-message "at offset \\d+ into object of size \\\[0, 2] allocated by '__builtin_alloca'" "note" }
     sink (p);
     sink (p[0]);
     sink (p[1]);              // { dg-warning "subscript 1 is outside array bounds of 'int16_t\\\[1]'" }
@@ -132,7 +132,7 @@ void test_alloca_int16_range (unsigned n)
   }
 
   {
-    p = alloca (UR (0, 3));   // { dg-message "object of size between 0 and 3 allocated by '__builtin_alloca'" }
+    p = alloca (UR (0, 3));   // { dg-message "at offset \\d+ into object of size \\\[0, 3] allocated by '__builtin_alloca'" "note" }
     sink (p);
     T (p[0]);
     T (p[1]);                 // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" }
@@ -141,7 +141,7 @@ void test_alloca_int16_range (unsigned n)
   }
 
   {
-    p = alloca (UR (1, 3));    // { dg-message "object of size between 1 and 3 allocated by '__builtin_alloca'" }
+    p = alloca (UR (1, 3));    // { dg-message "at offset 1|2|3 into object of size \\\[1, 3] allocated by '__builtin_alloca'" "note" }
     sink (p);
     T (p[0]);
     T (p[1]);                 // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" }
@@ -150,7 +150,7 @@ void test_alloca_int16_range (unsigned n)
   }
 
   {
-    p = alloca (UR (2, 3));    // { dg-message "object of size between 2 and 3 allocated by '__builtin_alloca'" }
+    p = alloca (UR (2, 3));    // { dg-message "at offset 2|4 into object of size \\\[2, 3] allocated by '__builtin_alloca'" "note" }
     sink (p);
     T (p[0]);
     T (p[1]);                 // { dg-warning "subscript 'int16_t {aka short int}\\\[1\\\]' is partly outside array bounds of 'unsigned char\\\[3]'" }
@@ -159,7 +159,7 @@ void test_alloca_int16_range (unsigned n)
   }
 
   {
-    p = alloca (UR (3, 4));    // { dg-message "object of size between 3 and 4 allocated by '__builtin_alloca'" }
+    p = alloca (UR (3, 4));    // { dg-message "at offset 4|6 into object of size \\\[3, 4] allocated by '__builtin_alloca'" "note" }
     sink (p);
     T (p[0]);
     T (p[1]);
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-69.c b/gcc/testsuite/gcc.dg/Warray-bounds-69.c
index 5a955774124..80503f8d217 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-69.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-69.c
@@ -1,6 +1,6 @@
 /* Verify that storing a bigger vector into smaller space is diagnosed.
    { dg-do compile }
-   { dg-options "-O2 -Warray-bounds" } */
+   { dg-options "-O2 -Warray-bounds -Wno-stringop-overflow" } */
 
 typedef __INT16_TYPE__                         int16_t;
 typedef __attribute__ ((__vector_size__ (32))) char C32;
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.c b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
new file mode 100644
index 00000000000..6487613374d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
@@ -0,0 +1,135 @@
+/* PR middle-end/100137 - -Warray-bounds false positive on varying offset
+   plus negative
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+extern char ax[], a1[1], a2[2], a3[3], a4[4], a5[5];
+
+int* ptr;
+#define X (*ptr++)
+
+
+__attribute__ ((noipa)) void
+array_plus_var_minus_cstint (int i, int j)
+{
+  {
+    const char *p = ax;
+    p += i;
+    X = p[-1];
+    X = p[-123];
+  }
+
+  {
+    const char *p = a1;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a2;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a3;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-5];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a4;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-5];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-6];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a5;
+    p += i;
+    p += j;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-5];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-6];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+}
+
+
+__attribute__ ((noipa)) void
+array_plus_var_minus_cstlong (long i, long j)
+{
+  {
+    const char *p = ax;
+    p += i;
+    X = p[-1];
+    X = p[-123];
+  }
+
+  {
+    const char *p = a1;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a2;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a3;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-5];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a4;
+    p += i;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-5];      // { dg-warning "\\\[-Warray-bounds" }
+    X = p[-6];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+
+  {
+    const char *p = a5;
+    p += i;
+    p += j;
+    X = p[-1];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-2];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-3];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-4];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-5];      // { dg-bogus "\\\[-Warray-bounds" }
+    X = p[-6];      // { dg-warning "\\\[-Warray-bounds" }
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-72.c b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
new file mode 100644
index 00000000000..b44ac9d3aa2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
@@ -0,0 +1,112 @@
+/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array
+   element of empty structs
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+struct S
+{
+#if SOME_CONFIG_MACRO
+  /* Suppose the contents are empty in the development configuration
+     but non-empty in others.  Out of bounds accesses to elements of
+     the arrays below should be diagnosed in all configurations,
+     including when S is empty, even if they are folded away.  */
+  int member;
+#endif
+};
+
+extern struct S sa3[3];
+extern struct S sa2_3[2][3];
+extern struct S sa3_4_5[3][4][5];
+
+void sink (void*);
+
+
+void access_sa3 (void)
+{
+  sa3[0] = (struct S){ };
+  sa3[1] = (struct S){ };
+  sa3[2] = (struct S){ };
+  sa3[3] = (struct S){ };       // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+void access_sa3_ptr (void)
+{
+  struct S *p = &sa3[0];
+
+  p[0] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[3] = (struct S){ };         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+void access_sa2_3_ptr (void)
+{
+  struct S *p = &sa2_3[0][0];
+
+  p[0] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[6] = (struct S){ };         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+void access_sa3_4_5_ptr (struct S s, int i)
+{
+  struct S *p = &sa3_4_5[0][0][0];
+
+  p[0] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[60] = (struct S){ };        // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+}
+
+
+void access_vla3 (struct S s, unsigned n)
+{
+  struct S vla3[3 < n ? 3 : n];
+
+  vla3[0] = (struct S){ };
+  vla3[1] = (struct S){ };
+  vla3[2] = (struct S){ };
+  vla3[3] = (struct S){ };       // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla3);
+}
+
+void access_vla3_ptr (struct S s, unsigned n)
+{
+  struct S vla3[3 < n ? 3 : n];
+  struct S *p = &vla3[0];
+
+  p[0] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[3] = (struct S){ };         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla3);
+}
+
+void access_vla2_3_ptr (struct S s, unsigned n)
+{
+  struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n];
+  struct S *p = &vla2_3[0][0];
+
+  p[0] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[6] = (struct S){ };         // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla2_3);
+}
+
+void access_vla3_4_5_ptr (struct S s, unsigned n)
+{
+  struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n];
+  struct S *p = &vla3_4_5[0][0][0];
+
+  p[0] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[1] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[2] = (struct S){ };         // { dg-bogus "\\\[-Warray-bounds" }
+  p[60] = (struct S){ };        // { dg-warning "\\\[-Warray-bounds" "pr?????" { xfail *-*-* } }
+
+  sink (vla3_4_5);
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-73.c b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
new file mode 100644
index 00000000000..73c335fd8a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
@@ -0,0 +1,109 @@
+/* PR tree-optimization/99475 - bogus -Warray-bounds accessing an array
+   element of empty structs
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-strict-aliasing" } */
+
+typedef _Bool bool;
+
+#define NOIPA __attribute__ ((noipa))
+
+struct S { };
+
+extern struct S sa3[3];
+extern struct S sa2_3[2][3];
+extern struct S sa3_4_5[3][4][5];
+
+void sink (void*);
+
+
+NOIPA void access_sa3 (void)
+{
+  ((bool*)sa3)[0] = __LINE__;     // { dg-warning "\\\[-Warray-bounds" }
+  ((bool*)sa3)[1] = __LINE__;     // { dg-warning "\\\[-Warray-bounds" }
+  ((bool*)sa3)[2] = __LINE__;     // { dg-warning "\\\[-Warray-bounds" }
+  ((bool*)sa3)[3] = __LINE__;     // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void access_sa3_ptr (void)
+{
+  bool *p = (bool*)&sa3[0];
+
+  p[0] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[1] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[2] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[3] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void access_sa2_3_ptr (void)
+{
+  bool *p = (bool*)&sa2_3[0][0];
+
+  p[0] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[1] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[2] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[6] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+}
+
+NOIPA void access_sa3_4_5_ptr (struct S s, int i)
+{
+  bool *p = (bool*)&sa3_4_5[0][0][0];
+
+  p[0] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[1] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[2] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[60] = __LINE__;       // { dg-warning "\\\[-Warray-bounds" }
+}
+
+
+NOIPA void access_vla3 (struct S s, unsigned n)
+{
+  struct S vla3[3 < n ? 3 : n];
+
+  ((bool*)vla3)[0] = __LINE__;    // { dg-warning "\\\[-Warray-bounds" }
+  ((bool*)vla3)[1] = __LINE__;    // { dg-warning "\\\[-Warray-bounds" }
+  ((bool*)vla3)[2] = __LINE__;    // { dg-warning "\\\[-Warray-bounds" }
+  ((bool*)vla3)[3] = __LINE__;    // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (vla3);
+}
+
+NOIPA void access_vla3_ptr (struct S s, unsigned n)
+{
+  struct S vla3[3 < n ? 3 : n];
+  bool *p = (bool*)&vla3[0];
+
+  p[0] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[1] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[2] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[3] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (vla3);
+}
+
+NOIPA void access_vla2_3_ptr (struct S s, unsigned n)
+{
+  struct S vla2_3[2 < n ? 2 : n][3 < n ? 3 : n];
+  bool *p = (bool*)&vla2_3[0][0];
+
+  p[0] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[1] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[2] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[6] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (vla2_3);
+}
+
+NOIPA void access_vla3_4_5_ptr (struct S s, unsigned n)
+{
+  struct S vla3_4_5[3 < n ? 3 : n][4 < n ? 4 : n][5 < n ? 5 : n];
+  bool *p = (bool*)&vla3_4_5[0][0][0];
+
+  p[0] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[1] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[2] = __LINE__;        // { dg-warning "\\\[-Warray-bounds" }
+  p[60] = __LINE__;       // { dg-warning "\\\[-Warray-bounds" }
+
+  sink (vla3_4_5);
+}
+
+// { dg-prune-output "empty struct has size 0 in C" }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c
index a1b103918cf..d9ca3447eb9 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-34.c
@@ -112,7 +112,7 @@ void s2_warn_cstoff_cstidx (struct S2 *p)
 void s2_warn_varoff_cstdix (struct S2 *p, int i)
 {
   char *q = p->a + i;
-  q[2] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" }
+  q[2] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
 }
 
 void s2_warn_cstoff_varidx (struct S2 *p, int i)
@@ -235,8 +235,8 @@ void si0_warn_cstoff_cstidx (struct Si0 *p)
 void si0_warn_varoff_cstdix (struct Si0 *p, int i)
 {
   char *q = p->a + i;
-  q[1] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" }
-  q[9] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" }
+  q[1] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
+  q[9] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
 }
 
 void si0_warn_cstoff_varidx (struct Si0 *p, int i)
@@ -248,5 +248,5 @@ void si0_warn_cstoff_varidx (struct Si0 *p, int i)
 void si0_warn_varoff_varidx (struct Si0 *p, int i, int j)
 {
   char *q = p->a + i;
-  q[j] = __LINE__;            // { dg-warning "\\\[-Wstringop-overflow" }
+  q[j] = __LINE__;            // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
 }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c
index 9bfc84af569..6412874e2f9 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-47.c
@@ -24,22 +24,22 @@ void nowarn_c32 (char c)
   sink (p);
 }
 
-/* The tests below fail as a result of the hack for PR 96963.  However,
-   with -Wall, the invalid stores are diagnosed by -Warray-bounds which
-   runs before vectorization and so doesn't need the hack.  If/when
-   -Warray changes to use compute_objsize() this will need adjusting.  */
+/* The tests below failed as a result of the hack for PR 96963.  However,
+   with -Wall, the invalid stores were diagnosed by -Warray-bounds which
+   runs before vectorization and so doesn't need the hack.  Now that
+   -Warray-bounds has changed to use compute_objsize() the tests pass.  */
 
 void warn_c32 (char c)
 {
-  extern char warn_a32[32];   // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "pr97027" { xfail *-*-* } }
+  extern char warn_a32[32];   // { dg-message "at offset 32 into destination object 'warn_a32' of size 32" "pr97027" }
 
   void *p = warn_a32 + 1;
-  *(C32*)p = (C32){ c };      // { dg-warning "writing 1 byte into a region of size 0" "pr97027" { xfail *-*-* } }
+  *(C32*)p = (C32){ c };      // { dg-warning "writing 1 byte into a region of size 0" "pr97027" }
 
   /* Verify a local variable too. */
   char a32[32];
   p = a32 + 1;
-  *(C32*)p = (C32){ c };      // { dg-warning "writing 1 byte into a region of size 0" "pr97027" { xfail *-*-* } }
+  *(C32*)p = (C32){ c };      // { dg-warning "writing 1 byte into a region of size 0" "pr97027" }
   sink (p);
 }
 
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c
index 7601679fac3..93c54c646c0 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-61.c
@@ -65,7 +65,7 @@ void nowarn_cond_escape (int c, int *x)
 void warn_cond_escape (int c, int *x)
 {
   extern char a3_2[3];
-  extern char a5_2[5];        // { dg-message "at offset 5 into destination object 'a5_2'" }
+  extern char a5_2[5];        // { dg-message "at offset 5 into object 'a5_2'" }
 
   char *p;
   if (c)
@@ -84,5 +84,5 @@ void warn_cond_escape (int c, int *x)
   if (*x == 2)
     p[2] = 0;
   else if (*x == 5)
-    p[5] = 0;                 // { dg-warning "\\\[-Wstringop-overflow" }
+    p[5] = 0;                 // { dg-warning "\\\[-Warray-bounds|-Wstringop-overflow" }
 }

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-07-08 18:10 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-21 22:25 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137) Martin Sebor
2021-06-28 19:33 ` [PING][PATCH] " Martin Sebor
2021-07-06 15:46   ` PING 2 [PATCH] " Martin Sebor
2021-07-07  7:38     ` Richard Biener
2021-07-07 20:38       ` Martin Sebor
2021-07-08  1:48         ` Marek Polacek
2021-07-08  3:12           ` Martin Sebor
2021-07-08  8:20             ` Richard Biener
2021-07-08 10:41           ` Andreas Schwab
2021-07-08 13:48             ` Christophe Lyon
2021-07-08 18:10             ` Martin Sebor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).