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

* [PING][PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  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 ` Martin Sebor
  2021-07-06 15:46   ` PING 2 [PATCH] " Martin Sebor
  0 siblings, 1 reply; 11+ messages in thread
From: Martin Sebor @ 2021-06-28 19:33 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html

On 6/21/21 4:25 PM, Martin Sebor wrote:
> -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


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

* PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-06-28 19:33 ` [PING][PATCH] " Martin Sebor
@ 2021-07-06 15:46   ` Martin Sebor
  2021-07-07  7:38     ` Richard Biener
  0 siblings, 1 reply; 11+ messages in thread
From: Martin Sebor @ 2021-07-06 15:46 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html

On 6/28/21 1:33 PM, Martin Sebor wrote:
> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
> 
> On 6/21/21 4:25 PM, Martin Sebor wrote:
>> -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
> 


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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-06 15:46   ` PING 2 [PATCH] " Martin Sebor
@ 2021-07-07  7:38     ` Richard Biener
  2021-07-07 20:38       ` Martin Sebor
  0 siblings, 1 reply; 11+ messages in thread
From: Richard Biener @ 2021-07-07  7:38 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Tue, Jul 6, 2021 at 5:47 PM Martin Sebor via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html

+  if (TREE_CODE (axstype) != UNION_TYPE)

what about QUAL_UNION_TYPE?  (why constrain union type accesses
here - note you don't seem to constrain accesses of union members here)

+    if (tree access_size = TYPE_SIZE_UNIT (axstype))

+  /* 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);

probably pre-existing but the pointer indirection is definitely confusing
me again and again given the variable is named 'reftype' - obviously
an access to a pointer does not have any element size.  Possibly the
paths arriving here ensure somehow that the only case is when
reftype is not the access type but a pointer to the accessed memory.
"jump-threading" the source might help me avoiding to trip over this
again and again ...

The patch removes a lot of odd code, I like that.  You know this code best
and it's hard to spot errors.

So OK, you'll deal with the fallout.

Thanks,
Richard.

> On 6/28/21 1:33 PM, Martin Sebor wrote:
> > Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
> >
> > On 6/21/21 4:25 PM, Martin Sebor wrote:
> >> -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
> >
>

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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-07  7:38     ` Richard Biener
@ 2021-07-07 20:38       ` Martin Sebor
  2021-07-08  1:48         ` Marek Polacek
  0 siblings, 1 reply; 11+ messages in thread
From: Martin Sebor @ 2021-07-07 20:38 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches

On 7/7/21 1:38 AM, Richard Biener wrote:
> On Tue, Jul 6, 2021 at 5:47 PM Martin Sebor via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>>
>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
> 
> +  if (TREE_CODE (axstype) != UNION_TYPE)
> 
> what about QUAL_UNION_TYPE?  (why constrain union type accesses
> here - note you don't seem to constrain accesses of union members here)

I didn't know a QUAL_UNION_TYPE was a thing.  Removing the test
doesn't seem to cause any regressions so let me do that in a followup.

> 
> +    if (tree access_size = TYPE_SIZE_UNIT (axstype))
> 
> +  /* 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);
> 
> probably pre-existing but the pointer indirection is definitely confusing
> me again and again given the variable is named 'reftype' - obviously
> an access to a pointer does not have any element size.  Possibly the
> paths arriving here ensure somehow that the only case is when
> reftype is not the access type but a pointer to the accessed memory.
> "jump-threading" the source might help me avoiding to trip over this
> again and again ...

I agree (it is confusing).  There's more to simplify here.  It's on
my to do list so let me see about this piece of code then.

> 
> The patch removes a lot of odd code, I like that.  You know this code best
> and it's hard to spot errors.
> 
> So OK, you'll deal with the fallout.

I certainly will.  Pushed in r12-2132.

Thanks
Martin

> 
> Thanks,
> Richard.
> 
>> On 6/28/21 1:33 PM, Martin Sebor wrote:
>>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
>>>
>>> On 6/21/21 4:25 PM, Martin Sebor wrote:
>>>> -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
>>>
>>


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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-07 20:38       ` Martin Sebor
@ 2021-07-08  1:48         ` Marek Polacek
  2021-07-08  3:12           ` Martin Sebor
  2021-07-08 10:41           ` Andreas Schwab
  0 siblings, 2 replies; 11+ messages in thread
From: Marek Polacek @ 2021-07-08  1:48 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Richard Biener, gcc-patches

On Wed, Jul 07, 2021 at 02:38:11PM -0600, Martin Sebor via Gcc-patches wrote:
> On 7/7/21 1:38 AM, Richard Biener wrote:
> > On Tue, Jul 6, 2021 at 5:47 PM Martin Sebor via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> > > 
> > > Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
> > 
> > +  if (TREE_CODE (axstype) != UNION_TYPE)
> > 
> > what about QUAL_UNION_TYPE?  (why constrain union type accesses
> > here - note you don't seem to constrain accesses of union members here)
> 
> I didn't know a QUAL_UNION_TYPE was a thing.  Removing the test
> doesn't seem to cause any regressions so let me do that in a followup.
> 
> > 
> > +    if (tree access_size = TYPE_SIZE_UNIT (axstype))
> > 
> > +  /* 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);
> > 
> > probably pre-existing but the pointer indirection is definitely confusing
> > me again and again given the variable is named 'reftype' - obviously
> > an access to a pointer does not have any element size.  Possibly the
> > paths arriving here ensure somehow that the only case is when
> > reftype is not the access type but a pointer to the accessed memory.
> > "jump-threading" the source might help me avoiding to trip over this
> > again and again ...
> 
> I agree (it is confusing).  There's more to simplify here.  It's on
> my to do list so let me see about this piece of code then.
> 
> > 
> > The patch removes a lot of odd code, I like that.  You know this code best
> > and it's hard to spot errors.
> > 
> > So OK, you'll deal with the fallout.
> 
> I certainly will.  Pushed in r12-2132.

I think this patch breaks bootstrap on x86_64:

In member function ‘availability varpool_node::get_availability(symtab_node*)’,
    inlined from ‘availability symtab_node::get_availability(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3360:63,
    inlined from ‘availability symtab_node::get_availability(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3355:1,
    inlined from ‘symtab_node* symtab_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3199:35,
    inlined from ‘symtab_node* symtab_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3193:1,
    inlined from ‘varpool_node* varpool_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3234:5,
    inlined from ‘availability varpool_node::_ZN12varpool_node16get_availabilityEP11symtab_node.part.0(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/varpool.c:501:29:
/opt/notnfs/polacek/gcc/gcc/varpool.c:490:19: error: array subscript ‘varpool_node[0]’ is partly outside array bounds of ‘varpool_node [0]’ [-Werror=array-bounds]
  490 |   if (!definition && !in_other_partition)
      |       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/notnfs/polacek/gcc/gcc/varpool.c:29:
/opt/notnfs/polacek/gcc/gcc/cgraph.h: In member function ‘availability varpool_node::_ZN12varpool_node16get_availabilityEP11symtab_node.part.0(symtab_node*)’:
/opt/notnfs/polacek/gcc/gcc/cgraph.h:1969:39: note: object ‘varpool_node::<anonymous>’ of size 120
 1969 | struct GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node
      |                                       ^~~~~~~~~~~~
cc1plus: all warnings being treated as errors

Marek


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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  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
  1 sibling, 1 reply; 11+ messages in thread
From: Martin Sebor @ 2021-07-08  3:12 UTC (permalink / raw)
  To: Marek Polacek; +Cc: Richard Biener, gcc-patches

On 7/7/21 7:48 PM, Marek Polacek wrote:
> On Wed, Jul 07, 2021 at 02:38:11PM -0600, Martin Sebor via Gcc-patches wrote:
>> On 7/7/21 1:38 AM, Richard Biener wrote:
>>> On Tue, Jul 6, 2021 at 5:47 PM Martin Sebor via Gcc-patches
>>> <gcc-patches@gcc.gnu.org> wrote:
>>>>
>>>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
>>>
>>> +  if (TREE_CODE (axstype) != UNION_TYPE)
>>>
>>> what about QUAL_UNION_TYPE?  (why constrain union type accesses
>>> here - note you don't seem to constrain accesses of union members here)
>>
>> I didn't know a QUAL_UNION_TYPE was a thing.  Removing the test
>> doesn't seem to cause any regressions so let me do that in a followup.
>>
>>>
>>> +    if (tree access_size = TYPE_SIZE_UNIT (axstype))
>>>
>>> +  /* 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);
>>>
>>> probably pre-existing but the pointer indirection is definitely confusing
>>> me again and again given the variable is named 'reftype' - obviously
>>> an access to a pointer does not have any element size.  Possibly the
>>> paths arriving here ensure somehow that the only case is when
>>> reftype is not the access type but a pointer to the accessed memory.
>>> "jump-threading" the source might help me avoiding to trip over this
>>> again and again ...
>>
>> I agree (it is confusing).  There's more to simplify here.  It's on
>> my to do list so let me see about this piece of code then.
>>
>>>
>>> The patch removes a lot of odd code, I like that.  You know this code best
>>> and it's hard to spot errors.
>>>
>>> So OK, you'll deal with the fallout.
>>
>> I certainly will.  Pushed in r12-2132.
> 
> I think this patch breaks bootstrap on x86_64:
> 
> In member function ‘availability varpool_node::get_availability(symtab_node*)’,
>      inlined from ‘availability symtab_node::get_availability(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3360:63,
>      inlined from ‘availability symtab_node::get_availability(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3355:1,
>      inlined from ‘symtab_node* symtab_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3199:35,
>      inlined from ‘symtab_node* symtab_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3193:1,
>      inlined from ‘varpool_node* varpool_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3234:5,
>      inlined from ‘availability varpool_node::_ZN12varpool_node16get_availabilityEP11symtab_node.part.0(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/varpool.c:501:29:
> /opt/notnfs/polacek/gcc/gcc/varpool.c:490:19: error: array subscript ‘varpool_node[0]’ is partly outside array bounds of ‘varpool_node [0]’ [-Werror=array-bounds]
>    490 |   if (!definition && !in_other_partition)
>        |       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
> In file included from /opt/notnfs/polacek/gcc/gcc/varpool.c:29:
> /opt/notnfs/polacek/gcc/gcc/cgraph.h: In member function ‘availability varpool_node::_ZN12varpool_node16get_availabilityEP11symtab_node.part.0(symtab_node*)’:
> /opt/notnfs/polacek/gcc/gcc/cgraph.h:1969:39: note: object ‘varpool_node::<anonymous>’ of size 120
>   1969 | struct GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node
>        |                                       ^~~~~~~~~~~~
> cc1plus: all warnings being treated as errors

I bootstrapped & regtested it on top of r12-2131 just before pushing
it but let me try with the top of trunk (r12-2135 as of now).

[a bit later]

The bootstrap succeeded with the same configuration settings:

   --enable-languages=ada,c,c++,d,fortran,jit,lto,objc,obj-c++ 
--enable-checking=yes --enable-host-shared --enable-valgrind-annotations

But with --enable-checking=release I was able to reproduce the error
above.  Since there is a simple way to bootstrap I'm not going to
revert the patch tonight.  I'll look into the problem tomorrow and
see if it can be easily fixed.  If not, I'll revert it then.

Martin

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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-08  3:12           ` Martin Sebor
@ 2021-07-08  8:20             ` Richard Biener
  0 siblings, 0 replies; 11+ messages in thread
From: Richard Biener @ 2021-07-08  8:20 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Marek Polacek, gcc-patches

On Thu, Jul 8, 2021 at 5:12 AM Martin Sebor <msebor@gmail.com> wrote:
>
> On 7/7/21 7:48 PM, Marek Polacek wrote:
> > On Wed, Jul 07, 2021 at 02:38:11PM -0600, Martin Sebor via Gcc-patches wrote:
> >> On 7/7/21 1:38 AM, Richard Biener wrote:
> >>> On Tue, Jul 6, 2021 at 5:47 PM Martin Sebor via Gcc-patches
> >>> <gcc-patches@gcc.gnu.org> wrote:
> >>>>
> >>>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573349.html
> >>>
> >>> +  if (TREE_CODE (axstype) != UNION_TYPE)
> >>>
> >>> what about QUAL_UNION_TYPE?  (why constrain union type accesses
> >>> here - note you don't seem to constrain accesses of union members here)
> >>
> >> I didn't know a QUAL_UNION_TYPE was a thing.  Removing the test
> >> doesn't seem to cause any regressions so let me do that in a followup.
> >>
> >>>
> >>> +    if (tree access_size = TYPE_SIZE_UNIT (axstype))
> >>>
> >>> +  /* 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);
> >>>
> >>> probably pre-existing but the pointer indirection is definitely confusing
> >>> me again and again given the variable is named 'reftype' - obviously
> >>> an access to a pointer does not have any element size.  Possibly the
> >>> paths arriving here ensure somehow that the only case is when
> >>> reftype is not the access type but a pointer to the accessed memory.
> >>> "jump-threading" the source might help me avoiding to trip over this
> >>> again and again ...
> >>
> >> I agree (it is confusing).  There's more to simplify here.  It's on
> >> my to do list so let me see about this piece of code then.
> >>
> >>>
> >>> The patch removes a lot of odd code, I like that.  You know this code best
> >>> and it's hard to spot errors.
> >>>
> >>> So OK, you'll deal with the fallout.
> >>
> >> I certainly will.  Pushed in r12-2132.
> >
> > I think this patch breaks bootstrap on x86_64:
> >
> > In member function ‘availability varpool_node::get_availability(symtab_node*)’,
> >      inlined from ‘availability symtab_node::get_availability(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3360:63,
> >      inlined from ‘availability symtab_node::get_availability(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3355:1,
> >      inlined from ‘symtab_node* symtab_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3199:35,
> >      inlined from ‘symtab_node* symtab_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3193:1,
> >      inlined from ‘varpool_node* varpool_node::ultimate_alias_target(availability*, symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/cgraph.h:3234:5,
> >      inlined from ‘availability varpool_node::_ZN12varpool_node16get_availabilityEP11symtab_node.part.0(symtab_node*)’ at /opt/notnfs/polacek/gcc/gcc/varpool.c:501:29:
> > /opt/notnfs/polacek/gcc/gcc/varpool.c:490:19: error: array subscript ‘varpool_node[0]’ is partly outside array bounds of ‘varpool_node [0]’ [-Werror=array-bounds]
> >    490 |   if (!definition && !in_other_partition)
> >        |       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
> > In file included from /opt/notnfs/polacek/gcc/gcc/varpool.c:29:
> > /opt/notnfs/polacek/gcc/gcc/cgraph.h: In member function ‘availability varpool_node::_ZN12varpool_node16get_availabilityEP11symtab_node.part.0(symtab_node*)’:
> > /opt/notnfs/polacek/gcc/gcc/cgraph.h:1969:39: note: object ‘varpool_node::<anonymous>’ of size 120
> >   1969 | struct GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node
> >        |                                       ^~~~~~~~~~~~
> > cc1plus: all warnings being treated as errors
>
> I bootstrapped & regtested it on top of r12-2131 just before pushing
> it but let me try with the top of trunk (r12-2135 as of now).
>
> [a bit later]
>
> The bootstrap succeeded with the same configuration settings:
>
>    --enable-languages=ada,c,c++,d,fortran,jit,lto,objc,obj-c++
> --enable-checking=yes --enable-host-shared --enable-valgrind-annotations
>
> But with --enable-checking=release I was able to reproduce the error
> above.  Since there is a simple way to bootstrap I'm not going to
> revert the patch tonight.  I'll look into the problem tomorrow and
> see if it can be easily fixed.  If not, I'll revert it then.

plain ./configure triggers the failure already, I guess your
--enable-host-shared
hides it.

Richard.

>
> Martin

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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-08  1:48         ` Marek Polacek
  2021-07-08  3:12           ` Martin Sebor
@ 2021-07-08 10:41           ` Andreas Schwab
  2021-07-08 13:48             ` Christophe Lyon
  2021-07-08 18:10             ` Martin Sebor
  1 sibling, 2 replies; 11+ messages in thread
From: Andreas Schwab @ 2021-07-08 10:41 UTC (permalink / raw)
  To: Marek Polacek via Gcc-patches; +Cc: Martin Sebor, Marek Polacek

On Jul 07 2021, Marek Polacek via Gcc-patches wrote:

> On Wed, Jul 07, 2021 at 02:38:11PM -0600, Martin Sebor via Gcc-patches wrote:
>> I certainly will.  Pushed in r12-2132.
>
> I think this patch breaks bootstrap on x86_64:

It also breaks bootstrap on aarch64 and ia64 in stage2.

In file included from ../../gcc/c-family/c-common.h:26,
                 from ../../gcc/cp/cp-tree.h:40,
                 from ../../gcc/cp/module.cc:209:
In function 'tree_node* identifier(const cpp_hashnode*)',
    inlined from 'bool module_state::read_macro_maps()' at ../../gcc/cp/module.cc:16305:10:
../../gcc/tree.h:1089:58: error: array subscript -1 is outside array bounds of 'cpp_hashnode [288230376151711743]' [-Werror=array-bounds]
 1089 |   ((tree) ((char *) (NODE) - sizeof (struct tree_common)))
      |                                                          ^
../../gcc/cp/module.cc:277:10: note: in expansion of macro 'HT_IDENT_TO_GCC_IDENT'
  277 |   return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast<cpp_hashnode *> (node)));
      |          ^~~~~~~~~~~~~~~~~~~~~
In file included from ../../gcc/tree.h:23,
                 from ../../gcc/c-family/c-common.h:26,
                 from ../../gcc/cp/cp-tree.h:40,
                 from ../../gcc/cp/module.cc:209:
../../gcc/tree-core.h: In member function 'bool module_state::read_macro_maps()':
../../gcc/tree-core.h:1445:24: note: at offset -24 into object 'tree_identifier::id' of size 16
 1445 |   struct ht_identifier id;
      |                        ^~

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-08 10:41           ` Andreas Schwab
@ 2021-07-08 13:48             ` Christophe Lyon
  2021-07-08 18:10             ` Martin Sebor
  1 sibling, 0 replies; 11+ messages in thread
From: Christophe Lyon @ 2021-07-08 13:48 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Marek Polacek via Gcc-patches, Marek Polacek

On Thu, 8 Jul 2021 at 12:42, Andreas Schwab <schwab@linux-m68k.org> wrote:
>
> On Jul 07 2021, Marek Polacek via Gcc-patches wrote:
>
> > On Wed, Jul 07, 2021 at 02:38:11PM -0600, Martin Sebor via Gcc-patches wrote:
> >> I certainly will.  Pushed in r12-2132.
> >
> > I think this patch breaks bootstrap on x86_64:
>
> It also breaks bootstrap on aarch64 and ia64 in stage2.
>
> In file included from ../../gcc/c-family/c-common.h:26,
>                  from ../../gcc/cp/cp-tree.h:40,
>                  from ../../gcc/cp/module.cc:209:
> In function 'tree_node* identifier(const cpp_hashnode*)',
>     inlined from 'bool module_state::read_macro_maps()' at ../../gcc/cp/module.cc:16305:10:
> ../../gcc/tree.h:1089:58: error: array subscript -1 is outside array bounds of 'cpp_hashnode [288230376151711743]' [-Werror=array-bounds]
>  1089 |   ((tree) ((char *) (NODE) - sizeof (struct tree_common)))
>       |                                                          ^
> ../../gcc/cp/module.cc:277:10: note: in expansion of macro 'HT_IDENT_TO_GCC_IDENT'
>   277 |   return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast<cpp_hashnode *> (node)));
>       |          ^~~~~~~~~~~~~~~~~~~~~
> In file included from ../../gcc/tree.h:23,
>                  from ../../gcc/c-family/c-common.h:26,
>                  from ../../gcc/cp/cp-tree.h:40,
>                  from ../../gcc/cp/module.cc:209:
> ../../gcc/tree-core.h: In member function 'bool module_state::read_macro_maps()':
> ../../gcc/tree-core.h:1445:24: note: at offset -24 into object 'tree_identifier::id' of size 16
>  1445 |   struct ht_identifier id;
>       |                        ^~
>
> Andreas.
>

on arm-linux-gnueabi, it breaks in:
libatomic/config/linux/arm/host-config.h:42:34: error: array subscript
0 is outside array bounds of 'unsigned int[0]' [-Werror=array-bounds]

Christophe

> --
> Andreas Schwab, schwab@linux-m68k.org
> GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
> "And now for something completely different."

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

* Re: PING 2 [PATCH] correct handling of variable offset minus constant in -Warray-bounds (PR 100137)
  2021-07-08 10:41           ` Andreas Schwab
  2021-07-08 13:48             ` Christophe Lyon
@ 2021-07-08 18:10             ` Martin Sebor
  1 sibling, 0 replies; 11+ messages in thread
From: Martin Sebor @ 2021-07-08 18:10 UTC (permalink / raw)
  To: Andreas Schwab, Marek Polacek via Gcc-patches; +Cc: Marek Polacek

On 7/8/21 4:41 AM, Andreas Schwab wrote:
> On Jul 07 2021, Marek Polacek via Gcc-patches wrote:
> 
>> On Wed, Jul 07, 2021 at 02:38:11PM -0600, Martin Sebor via Gcc-patches wrote:
>>> I certainly will.  Pushed in r12-2132.
>>
>> I think this patch breaks bootstrap on x86_64:
> 
> It also breaks bootstrap on aarch64 and ia64 in stage2.
> 
> In file included from ../../gcc/c-family/c-common.h:26,
>                   from ../../gcc/cp/cp-tree.h:40,
>                   from ../../gcc/cp/module.cc:209:
> In function 'tree_node* identifier(const cpp_hashnode*)',
>      inlined from 'bool module_state::read_macro_maps()' at ../../gcc/cp/module.cc:16305:10:
> ../../gcc/tree.h:1089:58: error: array subscript -1 is outside array bounds of 'cpp_hashnode [288230376151711743]' [-Werror=array-bounds]
>   1089 |   ((tree) ((char *) (NODE) - sizeof (struct tree_common)))
>        |                                                          ^
> ../../gcc/cp/module.cc:277:10: note: in expansion of macro 'HT_IDENT_TO_GCC_IDENT'
>    277 |   return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast<cpp_hashnode *> (node)));
>        |          ^~~~~~~~~~~~~~~~~~~~~
> In file included from ../../gcc/tree.h:23,
>                   from ../../gcc/c-family/c-common.h:26,
>                   from ../../gcc/cp/cp-tree.h:40,
>                   from ../../gcc/cp/module.cc:209:
> ../../gcc/tree-core.h: In member function 'bool module_state::read_macro_maps()':
> ../../gcc/tree-core.h:1445:24: note: at offset -24 into object 'tree_identifier::id' of size 16
>   1445 |   struct ht_identifier id;
>        |                        ^~

Thanks.  This is a different issue than what triggered the other
warnings.  I have temporarily suppressed these two instances until
I root cause them.  Bootstrap should now be restored (at least on
x86_64).  If there are any outstanding warnings that are causing
failures please either update pr101374 or open new bugs.

Martin

^ 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).