[gcc r11-7275] array-bounds: Fix up ICE on overaligned variables [PR99109]

Jakub Jelinek jakub@gcc.gnu.org
Thu Feb 18 08:46:10 GMT 2021


https://gcc.gnu.org/g:f72e3d8c9ffb81d25d4fdba10056cd2197e22d64

commit r11-7275-gf72e3d8c9ffb81d25d4fdba10056cd2197e22d64
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Feb 18 09:45:19 2021 +0100

    array-bounds: Fix up ICE on overaligned variables [PR99109]
    
    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.
    
    2021-02-18  Jakub Jelinek  <jakub@redhat.com>
    
            PR middle-end/99109
            * gimple-array-bounds.cc (build_zero_elt_array_type): Rename to ...
            (build_printable_array_type): ... this.  Add nelts argument.  For
            overaligned eltype, use TYPE_MAIN_VARIANT (eltype) instead.  If
            nelts, call build_array_type_nelts.
            (array_bounds_checker::check_mem_ref): Use build_printable_array_type
            instead of build_zero_elt_array_type and build_array_type_nelts.
    
            * g++.dg/warn/Warray-bounds-17.C: New test.

Diff:
---
 gcc/gimple-array-bounds.cc                   | 24 ++++++++++++++++--------
 gcc/testsuite/g++.dg/warn/Warray-bounds-17.C | 15 +++++++++++++++
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 2576556f76b..d7fd2c74111 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -372,12 +372,23 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
   return warned;
 }
 
-/* Hack around the internal representation constraints and build a zero
-   element array type that actually renders as T[0] in diagnostcs.  */
+/* Wrapper around build_array_type_nelts that makes sure the array
+   can be created at all and handles zero sized arrays specially.  */
 
 static tree
-build_zero_elt_array_type (tree eltype)
+build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
 {
+  if (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)
+    eltype = TYPE_MAIN_VARIANT (eltype);
+
+  if (nelts)
+    return build_array_type_nelts (eltype, nelts);
+
   tree idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
   tree arrtype = build_array_type (eltype, idxtype);
   arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
@@ -561,10 +572,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	return false;
 
       offset_int nelts = arrbounds[1] / eltsize;
-      if (nelts == 0)
-	reftype = build_zero_elt_array_type (reftype);
-      else
-	reftype = build_array_type_nelts (reftype, nelts.to_uhwi ());
+      reftype = build_printable_array_type (reftype, nelts.to_uhwi ());
     }
   else if (TREE_CODE (arg) == ADDR_EXPR)
     {
@@ -675,7 +683,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
       /* 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);
+	reftype = build_printable_array_type (reftype, 1);
 
       /* Extract the element type out of MEM_REF and use its size
 	 to compute the index to print in the diagnostic; arrays
diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C
new file mode 100644
index 00000000000..64fbd080123
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-17.C
@@ -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);
+}


More information about the Gcc-cvs mailing list