[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