[committed] Backport folding fix (PR middle-end/40946)

Jakub Jelinek jakub@redhat.com
Mon Nov 9 19:55:00 GMT 2009


Hi!

Richi's PR41317 fix fixed also PR40946.  I've been testing the backport
on redhat/gcc-4_4-branch for a month and today I've bootstrapped/regtested
it on x86_64-linux and i686-linux on branches/gcc-4_4-branch.
Committed to 4.4 branch after ack from richi in the PR, the new testcase
added to trunk as well.

2009-11-09  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/40946
	Backport from mainline
	2009-09-09  Richard Guenther  <rguenther@suse.de>

	PR middle-end/41317
	* tree-ssa-ccp.c (maybe_fold_offset_to_component_ref): Remove
	code dealing with plain pointer bases.
	(maybe_fold_offset_to_reference): Likewise.
	(maybe_fold_stmt_addition): Adjust.

	PR middle-end/40946
	* gcc.dg/pr40946.c: New test.

	Backport from mainline
	2009-09-09  Richard Guenther  <rguenther@suse.de>

	PR middle-end/41317
	* gcc.c-torture/execute/pr41317.c: New testcase.

--- gcc/tree-ssa-ccp.c	(revision 152552)
+++ gcc/tree-ssa-ccp.c	(revision 152553)
@@ -1735,7 +1735,7 @@ maybe_fold_offset_to_array_ref (tree bas
 
 static tree
 maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
-				    tree orig_type, bool base_is_ptr)
+				    tree orig_type)
 {
   tree f, t, field_type, tail_array_field, field_offset;
   tree ret;
@@ -1787,8 +1787,6 @@ maybe_fold_offset_to_component_ref (tree
       if (cmp == 0
 	  && useless_type_conversion_p (orig_type, field_type))
 	{
-	  if (base_is_ptr)
-	    base = build1 (INDIRECT_REF, record_type, base);
 	  t = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
 	  return t;
 	}
@@ -1813,11 +1811,7 @@ maybe_fold_offset_to_component_ref (tree
 
       /* If we matched, then set offset to the displacement into
 	 this field.  */
-      if (base_is_ptr)
-	new_base = build1 (INDIRECT_REF, record_type, base);
-      else
-	new_base = base;
-      new_base = build3 (COMPONENT_REF, field_type, new_base, f, NULL_TREE);
+      new_base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
 
       /* Recurse to possibly find the match.  */
       ret = maybe_fold_offset_to_array_ref (new_base, t, orig_type,
@@ -1825,7 +1819,7 @@ maybe_fold_offset_to_component_ref (tree
       if (ret)
 	return ret;
       ret = maybe_fold_offset_to_component_ref (field_type, new_base, t,
-						orig_type, false);
+						orig_type);
       if (ret)
 	return ret;
     }
@@ -1839,8 +1833,6 @@ maybe_fold_offset_to_component_ref (tree
 
   /* If we get here, we've got an aggregate field, and a possibly 
      nonzero offset into them.  Recurse and hope for a valid match.  */
-  if (base_is_ptr)
-    base = build1 (INDIRECT_REF, record_type, base);
   base = build3 (COMPONENT_REF, field_type, base, f, NULL_TREE);
 
   t = maybe_fold_offset_to_array_ref (base, offset, orig_type,
@@ -1848,7 +1840,7 @@ maybe_fold_offset_to_component_ref (tree
   if (t)
     return t;
   return maybe_fold_offset_to_component_ref (field_type, base, offset,
-					     orig_type, false);
+					     orig_type);
 }
 
 /* Attempt to express (ORIG_TYPE)BASE+OFFSET as BASE->field_of_orig_type
@@ -1862,57 +1854,44 @@ maybe_fold_offset_to_reference (tree bas
 {
   tree ret;
   tree type;
-  bool base_is_ptr = true;
 
   STRIP_NOPS (base);
-  if (TREE_CODE (base) == ADDR_EXPR)
-    {
-      base_is_ptr = false;
+  if (TREE_CODE (base) != ADDR_EXPR)
+    return NULL_TREE;
 
-      base = TREE_OPERAND (base, 0);
+  base = TREE_OPERAND (base, 0);
 
-      /* Handle case where existing COMPONENT_REF pick e.g. wrong field of union,
-	 so it needs to be removed and new COMPONENT_REF constructed.
-	 The wrong COMPONENT_REF are often constructed by folding the
-	 (type *)&object within the expression (type *)&object+offset  */
-      if (handled_component_p (base))
+  /* Handle case where existing COMPONENT_REF pick e.g. wrong field of union,
+     so it needs to be removed and new COMPONENT_REF constructed.
+     The wrong COMPONENT_REF are often constructed by folding the
+     (type *)&object within the expression (type *)&object+offset  */
+  if (handled_component_p (base))
+    {
+      HOST_WIDE_INT sub_offset, size, maxsize;
+      tree newbase;
+      newbase = get_ref_base_and_extent (base, &sub_offset,
+					 &size, &maxsize);
+      gcc_assert (newbase);
+      if (size == maxsize
+	  && size != -1
+	  && !(sub_offset & (BITS_PER_UNIT - 1)))
 	{
-          HOST_WIDE_INT sub_offset, size, maxsize;
-	  tree newbase;
-	  newbase = get_ref_base_and_extent (base, &sub_offset,
-					     &size, &maxsize);
-	  gcc_assert (newbase);
-	  if (size == maxsize
-	      && size != -1
-	      && !(sub_offset & (BITS_PER_UNIT - 1)))
-	    {
-	      base = newbase;
-	      if (sub_offset)
-		offset = int_const_binop (PLUS_EXPR, offset,
-					  build_int_cst (TREE_TYPE (offset),
-					  sub_offset / BITS_PER_UNIT), 1);
-	    }
+	  base = newbase;
+	  if (sub_offset)
+	    offset = int_const_binop (PLUS_EXPR, offset,
+				      build_int_cst (TREE_TYPE (offset),
+					     sub_offset / BITS_PER_UNIT), 1);
 	}
-      if (useless_type_conversion_p (orig_type, TREE_TYPE (base))
-	  && integer_zerop (offset))
-	return base;
-      type = TREE_TYPE (base);
     }
-  else
-    {
-      base_is_ptr = true;
-      if (!POINTER_TYPE_P (TREE_TYPE (base)))
-	return NULL_TREE;
-      type = TREE_TYPE (TREE_TYPE (base));
-    }
-  ret = maybe_fold_offset_to_component_ref (type, base, offset,
-					    orig_type, base_is_ptr);
+  if (useless_type_conversion_p (orig_type, TREE_TYPE (base))
+      && integer_zerop (offset))
+    return base;
+  type = TREE_TYPE (base);
+
+  ret = maybe_fold_offset_to_component_ref (type, base, offset, orig_type);
   if (!ret)
-    {
-      if (base_is_ptr)
-	base = build1 (INDIRECT_REF, type, base);
-      ret = maybe_fold_offset_to_array_ref (base, offset, orig_type, true);
-    }
+    ret = maybe_fold_offset_to_array_ref (base, offset, orig_type, true);
+
   return ret;
 }
 
@@ -2151,7 +2130,7 @@ maybe_fold_stmt_addition (tree res_type,
   t = maybe_fold_offset_to_array_ref (op0, op1, ptd_type, true);
   if (!t)
     t = maybe_fold_offset_to_component_ref (TREE_TYPE (op0), op0, op1,
-					    ptd_type, false);
+					    ptd_type);
   if (t)
     t = build1 (ADDR_EXPR, res_type, t);
 
--- gcc/testsuite/gcc.c-torture/execute/pr41317.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/pr41317.c	(revision 152553)
@@ -0,0 +1,28 @@
+extern void abort (void);
+
+struct A
+{
+  int i;
+};
+struct B
+{
+  struct A a;
+  int j;
+};
+
+static void
+foo (struct B *p)
+{
+  ((struct A *)p)->i = 1;
+}
+
+int main()
+{
+  struct A a;
+  a.i = 0;
+  foo ((struct B *)&a);
+  if (a.i != 1)
+    abort ();
+  return 0;
+}
+
--- gcc/testsuite/gcc.dg/pr40946.c	2009-10-22 14:21:31.171146893 +0200
+++ gcc/testsuite/gcc.dg/pr40946.c	2009-11-09 17:03:52.000000000 +0100
@@ -0,0 +1,33 @@
+/* PR middle-end/40946 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+struct A
+{
+  unsigned char a1[8];
+  unsigned short a2, a3, a4, a5, a6, a7;
+};
+
+int bar (void *, const char *, int);
+char *foo (void *, int);
+
+char *
+baz (const char *x, const char *y)
+{
+  int a = sizeof (struct A) + 2 * (__builtin_strlen (y)
+				   + __builtin_strlen (x) + 24) + 16;
+  struct A *b = __builtin_malloc (a);
+  char *c;
+  int d;
+
+  b->a4 = sizeof (struct A);
+  c = ((char *) b) + b->a4;
+  d = ((char *) b) + a - c;
+  b->a2 = b->a3 = (unsigned short) bar (c, y, d); /* { dg-bogus "array subscript is above array bounds" } */
+  c += b->a2;
+  d = ((char *) b) + a - c;
+  b->a7 = b->a4 + b->a2;
+  b->a5 = b->a6 = (unsigned short) bar (c, x, d);
+  c = foo (b, a);
+  return c;
+}

	Jakub



More information about the Gcc-patches mailing list