A -Warray-bounds enhancement committed last year into GCC 9
introduced an assumption that the MEM_REF type argument has
a size.  The test case submitted in PR89662 does pointer
addition on void*, in which the MEM_REF type is void*, which
breaks the assumption.

The attached change removes this assumption and considers such
types to have the size of 1.  (The result is used to scale
the offset in diagnostics after it has been determined to be
out of bounds.)

Martin
PR tree-optimization/89662 - -Warray-bounds ICE on void* arithmetic

gcc/ChangeLog:

	PR tree-optimization/89662
	* tree-vrp.c (vrp_prop::check_mem_ref): Avoid assuming every type
	has a size.

gcc/testsuite/ChangeLog:

	PR tree-optimization/89662
	* gcc.dg/Warray-bounds-41.c: New test.

Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 269445)
+++ gcc/tree-vrp.c	(working copy)
@@ -4718,13 +4718,16 @@ vrp_prop::check_mem_ref (location_t location, tree
 	{
 	  /* Extract the element type out of MEM_REF and use its size
 	     to compute the index to print in the diagnostic; arrays
-	     in MEM_REF don't mean anything.   */
+	     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 size = TYPE_SIZE_UNIT (type);
-	  offrange[0] = offrange[0] / wi::to_offset (size);
-	  offrange[1] = offrange[1] / wi::to_offset (size);
+	  if (tree size = TYPE_SIZE_UNIT (type))
+	    {
+	      offrange[0] = offrange[0] / wi::to_offset (size);
+	      offrange[1] = offrange[1] / wi::to_offset (size);
+	    }
 	}
       else
 	{
Index: gcc/testsuite/gcc.dg/Warray-bounds-41.c
===================================================================
--- gcc/testsuite/gcc.dg/Warray-bounds-41.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/Warray-bounds-41.c	(working copy)
@@ -0,0 +1,33 @@
+/* PR tree-optimization/89662- -Warray-bounds ICE on void* arithmetic
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+void* vptr (void *c)
+{
+  return c;
+}
+
+void sink (void*);
+
+void test_vptr_arith_vla_cst (void)
+{
+  int n = 1;
+  char c[n];
+  sink (vptr (c) - 1);    /* { dg-warning "\\\[-Warray-bounds" } */
+}
+
+void test_vptr_arith_vla_range (int n)
+{
+  if (n < 1 || 4 < n)
+    return;
+
+  char c[n];
+  sink (vptr (c) - 1);    /* { dg-warning "\\\[-Warray-bounds" "pr82608" { xfail *-*-* } } */
+}
+
+void test_vptr_arith_vla_var (int n)
+{
+  char c[n];
+  sink (vptr (c) - 1);    /* { dg-warning "\\\[-Warray-bounds" "pr82608" { xfail *-*-* } } */
+}
+

Reply via email to