re PR tree-optimization/83044 (ice in contains_struct_check)
authorJakub Jelinek <jakub@redhat.com>
Wed, 22 Nov 2017 12:35:26 +0000 (13:35 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 22 Nov 2017 12:35:26 +0000 (13:35 +0100)
PR tree-optimization/83044
* tree-vrp.c (vrp_prop::check_array_ref): If eltsize is not
INTEGER_CST or is 0, clear up_bound{,_p1} and later ignore tests
that need the upper bound.  Subtract offset from
get_addr_base_and_unit_offset only if positive and subtract it
before division by eltsize rather than after it.

* gcc.dg/pr83044.c: New test.
* c-c++-common/Warray-bounds.c (fb): Fix up MAX value.

From-SVN: r255054

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Warray-bounds.c
gcc/testsuite/gcc.dg/pr83044.c [new file with mode: 0644]
gcc/tree-vrp.c

index edd3621..e4936c6 100644 (file)
@@ -1,5 +1,12 @@
 2017-11-22  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/83044
+       * tree-vrp.c (vrp_prop::check_array_ref): If eltsize is not
+       INTEGER_CST or is 0, clear up_bound{,_p1} and later ignore tests
+       that need the upper bound.  Subtract offset from
+       get_addr_base_and_unit_offset only if positive and subtract it
+       before division by eltsize rather than after it.
+
        PR debug/83084
        * valtrack.c (propagate_for_debug_subst, propagate_for_debug): Reset
        debug insns if they would contain UNSPEC_VOLATILE or volatile asm.
index 39dd144..b117fa8 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/83044
+       * gcc.dg/pr83044.c: New test.
+       * c-c++-common/Warray-bounds.c (fb): Fix up MAX value.
+
 2017-11-22  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/79072
index bea36fb..4b9d6aa 100644 (file)
@@ -200,7 +200,7 @@ void fb (struct B *p)
 
   T (p->a1x[9].a1[0]);
 
-  enum { MAX = DIFF_MAX / sizeof *p->a1x - sizeof *p };
+  enum { MAX = (DIFF_MAX - sizeof *p) / sizeof *p->a1x };
 
   T (p->a1x[DIFF_MIN].a1);                /* { dg-warning "array subscript -\[0-9\]+ is below array bounds" } */
   T (p->a1x[-1].a1);                      /* { dg-warning "array subscript -1 is below array bounds" } */
diff --git a/gcc/testsuite/gcc.dg/pr83044.c b/gcc/testsuite/gcc.dg/pr83044.c
new file mode 100644 (file)
index 0000000..6681071
--- /dev/null
@@ -0,0 +1,14 @@
+/* PR tree-optimization/83044 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -std=gnu89 -O2" } */
+
+struct A { int b[0]; };
+struct B { struct A c[0]; };
+void bar (int *);
+
+void
+foo (void)
+{
+  struct B d;
+  bar (d.c->b);
+}
index e248f59..ea56e9d 100644 (file)
@@ -4795,24 +4795,30 @@ vrp_prop::check_array_ref (location_t location, tree ref,
         the size of the largest object is PTRDIFF_MAX.  */
       tree eltsize = array_ref_element_size (ref);
 
-      /* FIXME: Handle VLAs.  */
-      if (TREE_CODE (eltsize) != INTEGER_CST)
-       return;
-
-      tree maxbound = TYPE_MAX_VALUE (ptrdiff_type_node);
-
-      up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
-
-      tree arg = TREE_OPERAND (ref, 0);
+      if (TREE_CODE (eltsize) != INTEGER_CST
+         || integer_zerop (eltsize))
+       {
+         up_bound = NULL_TREE;
+         up_bound_p1 = NULL_TREE;
+       }
+      else
+       {
+         tree maxbound = TYPE_MAX_VALUE (ptrdiff_type_node);
+         tree arg = TREE_OPERAND (ref, 0);
+         HOST_WIDE_INT off;
+
+         if (get_addr_base_and_unit_offset (arg, &off) && off > 0)
+           maxbound = wide_int_to_tree (sizetype,
+                                        wi::sub (wi::to_wide (maxbound),
+                                                 off));
+         else
+           maxbound = fold_convert (sizetype, maxbound);
 
-      HOST_WIDE_INT off;
-      if (get_addr_base_and_unit_offset (arg, &off))
-       up_bound_p1 = wide_int_to_tree (sizetype,
-                                       wi::sub (wi::to_wide (up_bound_p1),
-                                                off));
+         up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
 
-      up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
-                                 build_int_cst (ptrdiff_type_node, 1));
+         up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
+                                     build_int_cst (ptrdiff_type_node, 1));
+       }
     }
   else
     up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
@@ -4823,7 +4829,7 @@ vrp_prop::check_array_ref (location_t location, tree ref,
   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
 
   /* Empty array.  */
-  if (tree_int_cst_equal (low_bound, up_bound_p1))
+  if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
     {
       warning_at (location, OPT_Warray_bounds,
                  "array subscript %E is above array bounds of %qT",
@@ -4843,7 +4849,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
 
   if (vr && vr->type == VR_ANTI_RANGE)
     {
-      if (TREE_CODE (up_sub) == INTEGER_CST
+      if (up_bound
+         && TREE_CODE (up_sub) == INTEGER_CST
           && (ignore_off_by_one
              ? tree_int_cst_lt (up_bound, up_sub)
              : tree_int_cst_le (up_bound, up_sub))
@@ -4856,7 +4863,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
           TREE_NO_WARNING (ref) = 1;
         }
     }
-  else if (TREE_CODE (up_sub) == INTEGER_CST
+  else if (up_bound
+          && TREE_CODE (up_sub) == INTEGER_CST
           && (ignore_off_by_one
               ? !tree_int_cst_le (up_sub, up_bound_p1)
               : !tree_int_cst_le (up_sub, up_bound)))