re PR bootstrap/41395 (Revision 151800 failed bootstrap)

2009-09-22  Richard Guenther  <rguenther@suse.de>

	PR middle-end/41395
	* tree-dfa.c (get_ref_base_and_extent): Handle trailing
	arrays really properly.

	* gcc.c-torture/execute/pr41395-1.c: New testcase.
	* gcc.c-torture/execute/pr41395-2.c: Likewise.

From-SVN: r151981
This commit is contained in:
Richard Guenther 2009-09-22 14:58:05 +00:00 committed by Richard Biener
parent cf76ef1a46
commit 2df373c2eb
5 changed files with 116 additions and 18 deletions

View File

@ -1,3 +1,9 @@
2009-09-22 Richard Guenther <rguenther@suse.de>
PR middle-end/41395
* tree-dfa.c (get_ref_base_and_extent): Handle trailing
arrays really properly.
2009-09-22 Jakub Jelinek <jakub@redhat.com> 2009-09-22 Jakub Jelinek <jakub@redhat.com>
* config/rs6000/rs6000.c (bdesc_2arg): Fix CODE_FOR_vector_gt* codes * config/rs6000/rs6000.c (bdesc_2arg): Fix CODE_FOR_vector_gt* codes

View File

@ -1,3 +1,9 @@
2009-09-22 Richard Guenther <rguenther@suse.de>
PR middle-end/41395
* gcc.c-torture/execute/pr41395-1.c: New testcase.
* gcc.c-torture/execute/pr41395-2.c: Likewise.
2009-09-22 Jakub Jelinek <jakub@redhat.com> 2009-09-22 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/20090922-1.c: New test. * gcc.dg/20090922-1.c: New test.

View File

@ -0,0 +1,28 @@
struct VEC_char_base
{
unsigned num;
unsigned alloc;
short vec[1];
};
short __attribute__((noinline))
foo (struct VEC_char_base *p, int i)
{
short *q;
p->vec[i] = 0;
q = &p->vec[8];
*q = 1;
return p->vec[i];
}
extern void abort (void);
extern void *malloc (__SIZE_TYPE__);
int
main()
{
struct VEC_char_base *p = malloc (sizeof (struct VEC_char_base) + 256);
if (foo (p, 8) != 1)
abort ();
return 0;
}

View File

@ -0,0 +1,35 @@
struct VEC_char_base
{
unsigned num;
unsigned alloc;
union {
short vec[1];
struct {
int i;
int j;
int k;
} a;
} u;
};
short __attribute__((noinline))
foo (struct VEC_char_base *p, int i)
{
short *q;
p->u.vec[i] = 0;
q = &p->u.vec[16];
*q = 1;
return p->u.vec[i];
}
extern void abort (void);
extern void *malloc (__SIZE_TYPE__);
int
main()
{
struct VEC_char_base *p = malloc (sizeof (struct VEC_char_base) + 256);
if (foo (p, 16) != 1)
abort ();
return 0;
}

View File

@ -752,7 +752,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
tree size_tree = NULL_TREE; tree size_tree = NULL_TREE;
HOST_WIDE_INT bit_offset = 0; HOST_WIDE_INT bit_offset = 0;
bool seen_variable_array_ref = false; bool seen_variable_array_ref = false;
bool seen_union = false;
/* First get the final access size from just the outermost expression. */ /* First get the final access size from just the outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF) if (TREE_CODE (exp) == COMPONENT_REF)
@ -794,9 +793,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
tree field = TREE_OPERAND (exp, 1); tree field = TREE_OPERAND (exp, 1);
tree this_offset = component_ref_field_offset (exp); tree this_offset = component_ref_field_offset (exp);
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == UNION_TYPE)
seen_union = true;
if (this_offset if (this_offset
&& TREE_CODE (this_offset) == INTEGER_CST && TREE_CODE (this_offset) == INTEGER_CST
&& host_integerp (this_offset, 0)) && host_integerp (this_offset, 0))
@ -849,6 +845,40 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
else else
{ {
tree asize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0))); tree asize = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (exp, 0)));
/* Get at the array size but include trailing padding if
the array is the last element of a struct or union. */
if (maxsize != -1
&& TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF)
{
tree cref = TREE_OPERAND (exp, 0);
tree field = TREE_OPERAND (cref, 1);
tree stype = TREE_TYPE (TREE_OPERAND (cref, 0));
tree next = TREE_CHAIN (field);
while (next && TREE_CODE (next) != FIELD_DECL)
next = TREE_CHAIN (next);
if (!next
|| TREE_CODE (stype) != RECORD_TYPE)
{
/* The size including padding is the size of
the whole structure minus the offset of the
array in it. */
tree field_offset = component_ref_field_offset (cref);
if (field_offset
&& host_integerp (field_offset, 0)
&& host_integerp (TYPE_SIZE_UNIT (stype), 0))
{
unsigned HOST_WIDE_INT as;
as = (((TREE_INT_CST_LOW (TYPE_SIZE_UNIT (stype))
- TREE_INT_CST_LOW (field_offset))
* BITS_PER_UNIT)
- TREE_INT_CST_LOW
(DECL_FIELD_BIT_OFFSET (field)));
asize = build_int_cstu (sizetype, as);
}
else
asize = NULL_TREE;
}
}
/* We need to adjust maxsize to the whole array bitsize. /* We need to adjust maxsize to the whole array bitsize.
But we can subtract any constant offset seen so far, But we can subtract any constant offset seen so far,
because that would get us outside of the array otherwise. */ because that would get us outside of the array otherwise. */
@ -887,25 +917,18 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
struct { int length; int a[1]; } x; x.a[d] struct { int length; int a[1]; } x; x.a[d]
struct { struct { int a; int b; } a[1]; } x; x.a[d].a struct { struct { int a; int b; } a[1]; } x; x.a[d].a
struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0] struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0]
struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
where we do not know maxsize for variable index accesses to where we do not know maxsize for variable index accesses to
the array. The simplest way to conservatively deal with this the array. The simplest way to conservatively deal with this
is to punt in the case that offset + maxsize reaches the is to punt in the case that offset + maxsize reaches the
base type boundary. base type boundary. This needs to include possible trailing padding
that is there for alignment purposes. */
Unfortunately this is difficult to determine reliably when unions are
involved and so we are conservative in such cases.
FIXME: This approach may be too conservative, we probably want to at least
check that the union is the last field/element at its level or even
propagate the calculated offsets back up the access chain and check
there. */
if (seen_variable_array_ref if (seen_variable_array_ref
&& (seen_union && (maxsize != -1
|| (maxsize != -1 && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) && bit_offset + maxsize
&& bit_offset + maxsize == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
== (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
maxsize = -1; maxsize = -1;
/* ??? Due to negative offsets in ARRAY_REF we can end up with /* ??? Due to negative offsets in ARRAY_REF we can end up with