re PR middle-end/40946 (Spurious array subscript is above bounds warning)

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.

From-SVN: r154046
This commit is contained in:
Jakub Jelinek 2009-11-09 20:38:29 +01:00 committed by Jakub Jelinek
parent 456910e1fb
commit 09399dec30
5 changed files with 120 additions and 57 deletions

View File

@ -1,3 +1,15 @@
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.
2009-11-08 Uros Bizjak <ubizjak@gmail.com>
Backport from mainline:

View File

@ -1,3 +1,14 @@
2009-11-09 Jakub Jelinek <jakub@redhat.com>
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.
2009-11-08 Uros Bizjak <ubizjak@gmail.com>
Backport from mainline:

View File

@ -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;
}

View File

@ -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;
}

View File

@ -1727,7 +1727,7 @@ maybe_fold_offset_to_array_ref (tree base, tree offset, tree orig_type,
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;
@ -1779,8 +1779,6 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
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;
}
@ -1805,11 +1803,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
/* 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,
@ -1817,7 +1811,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
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;
}
@ -1831,8 +1825,6 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
/* 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,
@ -1840,7 +1832,7 @@ maybe_fold_offset_to_component_ref (tree record_type, tree base, tree offset,
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
@ -1854,57 +1846,44 @@ maybe_fold_offset_to_reference (tree base, tree offset, tree orig_type)
{
tree ret;
tree type;
bool base_is_ptr = true;
STRIP_NOPS (base);
if (TREE_CODE (base) == ADDR_EXPR)
if (TREE_CODE (base) != ADDR_EXPR)
return NULL_TREE;
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))
{
base_is_ptr = false;
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))
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;
}
@ -2143,7 +2122,7 @@ maybe_fold_stmt_addition (tree res_type, tree op0, tree op1)
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);