-Warray-bounds makes a couple of assumptions about arrays that hold
neither for VLAs of zero-length arrays nor for zero-length arrays
of VLAs.  The attached patch removes these assumptions and simplifies
the code that deals with them in the process.

This resolves a P2 GCC 9-11 regression so I'm looking for approval
to commit this fix to both release branches as well as the trunk.

Tested on x86_64-linux.

Martin
PR tree-optimization/99121 - ICE in -Warray-bounds on a VLA of zero-length array

gcc/ChangeLog:

	PR tree-optimization/99121
	* gimple-array-bounds.cc (array_bounds_checker::check_mem_ref):
	Avoid assuming array element size is constant.  Handle zero-length
	arrays of VLAs.

gcc/testsuite/ChangeLog:

	PR tree-optimization/99121
	* c-c++-common/Warray-bounds-9.c: New test.
	* gcc.dg/Warray-bounds-71.c: New test.

diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 2576556f76b..25b91f6e215 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -594,34 +594,32 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	      || (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 nelts = array_type_nelts (reftype);
+	  if (integer_all_onesp (nelts))
+	    /* Zero length array.  */
+	    eltsize = 0;
+	  else
 	    {
-	      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;
+	      tree esz = TYPE_SIZE_UNIT (TREE_TYPE (reftype));
+	      if (TREE_CODE (esz) == INTEGER_CST)
+		/* Array element is not a VLA.  */
+		eltsize = wi::to_offset (esz);
 	    }
+
+	  if (!array_at_struct_end_p (arg)
+	      && TREE_CODE (nelts) == INTEGER_CST)
+	    arrbounds[1] = (wi::to_offset (nelts) + 1) * eltsize;
 	  else
-	    arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
+	    {
+	      /* 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);
+	      arrbounds[1] = wi::lrshift (maxobjsize, eltsizelog2);
+	    }
 
 	  /* Determine a tighter bound of the non-array element type.  */
 	  tree eltype = TREE_TYPE (reftype);
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..48ad16828f2
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-9.c
@@ -0,0 +1,55 @@
+/* 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 f_2_n_0 (int n)
+{
+  int a[2][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 f_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" }
+}
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..c2af9bef78c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
@@ -0,0 +1,53 @@
+/* PR tree-optimization/99121 - ICE in -Warray-bounds on a multidimensional
+   VLA
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-strict-aliasing -ftrack-macro-expansion=0" } */
+
+#define NOIPA __attribute__ ((noipa))
+
+void sink (void*, ...);
+#define T(a, x) sink (a, x)
+
+
+NOIPA void ma_0_n (int n)
+{
+  struct {
+    int a[0][n];
+  } s;
+
+  sink (&s);
+
+  T (&s, ((int *) s.a)[0]);   // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((char *) s.a)[0]);  // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((float *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+
+  T (&s, ((int *) s.a)[1]);   // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((char *) s.a)[1]);  // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((float *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+
+  T (&s, ((int *) s.a)[n]);   // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+  T (&s, ((char *) s.a)[n]);  // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+  T (&s, ((float *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+}
+
+
+NOIPA void ma_n_0 (int n)
+{
+  struct {
+    int a[n][0];
+  } s;
+
+  sink (&s);
+
+  T (&s, ((int *) s.a)[0]);   // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((char *) s.a)[0]);  // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((float *) s.a)[0]); // { dg-warning "\\\[-Warray-bounds" }
+
+  T (&s, ((int *) s.a)[1]);   // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((char *) s.a)[1]);  // { dg-warning "\\\[-Warray-bounds" }
+  T (&s, ((float *) s.a)[1]); // { dg-warning "\\\[-Warray-bounds" }
+
+  T (&s, ((int *) s.a)[n]);   // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+  T (&s, ((char *) s.a)[n]);  // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+  T (&s, ((float *) s.a)[n]); // { dg-warning "\\\[-Warray-bounds" "pr99129" { xfail *-*-* } }
+}

Reply via email to