[PATCH] array-bounds: Fix up ICE on overaligned variables [PR99109]

Jakub Jelinek jakub@redhat.com
Wed Feb 17 10:12:34 GMT 2021


Hi!

check_mem_ref builds artificial arrays for variables that don't have
array type.
The C standard says:
"For the purposes of these operators, a pointer to an object that is not an element of an
array behaves the same as a pointer to the first element of an array of length one with the
type of the object as its element type."
so it isn't completely wrong and does simplify the function.
But, layout_type can fail if the size of the element type is not a multiple
of its alignment (i.e. overaligned types) and we then ICE because of that.

The following patch uses TYPE_MAIN_VARIANT in those cases instead, but only
for the types that need it, as for the diagnostics it is better to use the
typedef names etc. that were really used in the source if possible.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-02-17  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/99109
	* gimple-array-bounds.cc (overaligned_type_p): New function.
	(array_bounds_checker::check_mem_ref): For overaligned types use
	TYPE_MAIN_VARIANT of reftype as element type of a new array.

	* g++.dg/warn/Warray-bounds-17.C: New test.

--- gcc/gimple-array-bounds.cc.jj	2021-01-04 10:25:37.471249246 +0100
+++ gcc/gimple-array-bounds.cc	2021-02-16 17:00:41.961750114 +0100
@@ -386,6 +386,21 @@ build_zero_elt_array_type (tree eltype)
   return arrtype;
 }
 
+/* Return true if it is not possible to build an array with element type
+   ELTYPE, because either ELTYPE has alignment larger than its size
+   or its size is not a multiple of its alignment.  */
+
+static bool
+overaligned_type_p (tree eltype)
+{
+  return (TYPE_SIZE_UNIT (eltype)
+	  && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
+	  && !integer_zerop (TYPE_SIZE_UNIT (eltype))
+	  && TYPE_ALIGN_UNIT (eltype) > 1
+	  && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
+		       ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0);
+}
+
 /* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
    references to string constants.  If VRP can determine that the array
    subscript is a constant, check if it is outside valid range.
@@ -553,6 +568,8 @@ array_bounds_checker::check_mem_ref (loc
       reftype = TREE_TYPE (TREE_TYPE (arg));
       if (TREE_CODE (reftype) == ARRAY_TYPE)
 	reftype = TREE_TYPE (reftype);
+      else if (overaligned_type_p (reftype))
+	reftype = TYPE_MAIN_VARIANT (reftype);
       if (tree refsize = TYPE_SIZE_UNIT (reftype))
 	if (TREE_CODE (refsize) == INTEGER_CST)
 	  eltsize = wi::to_offset (refsize);
@@ -675,7 +692,11 @@ array_bounds_checker::check_mem_ref (loc
       /* Treat a reference to a non-array object as one to an array
 	 of a single element.  */
       if (TREE_CODE (reftype) != ARRAY_TYPE)
-	reftype = build_array_type_nelts (reftype, 1);
+	{
+	  if (overaligned_type_p (reftype))
+	    reftype = TYPE_MAIN_VARIANT (reftype);
+	  reftype = build_array_type_nelts (reftype, 1);
+	}
 
       /* Extract the element type out of MEM_REF and use its size
 	 to compute the index to print in the diagnostic; arrays
--- gcc/testsuite/g++.dg/warn/Warray-bounds-17.C.jj	2021-02-16 17:24:14.178813304 +0100
+++ gcc/testsuite/g++.dg/warn/Warray-bounds-17.C	2021-02-16 17:23:35.305251062 +0100
@@ -0,0 +1,15 @@
+// PR middle-end/99109
+// { dg-do compile }
+// { dg-options "-O2 -Warray-bounds" }
+
+typedef int A __attribute__((aligned (64)));
+void foo (int *);
+
+void
+bar (void)
+{
+  A b;			// { dg-message "while referencing" }
+  int *p = &b;
+  int *x = (p - 1);	// { dg-warning "outside array bounds" }
+  foo (x);
+}

	Jakub



More information about the Gcc-patches mailing list