re PR middle-end/41463 (Another get_ref_base_and_extent problem)
2009-09-25 Richard Guenther <rguenther@suse.de> PR middle-end/41463 * tree-dfa.c (get_ref_base_and_extent): Fix issue with trailing arrays again. * gcc.c-torture/execute/pr41463.c: New testcase. From-SVN: r152167
This commit is contained in:
parent
6ef41fd08f
commit
79441eca0e
@ -1,3 +1,9 @@
|
||||
2009-09-25 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/41463
|
||||
* tree-dfa.c (get_ref_base_and_extent): Fix issue with trailing
|
||||
arrays again.
|
||||
|
||||
2009-09-25 Ben Elliston <bje@au.ibm.com>
|
||||
|
||||
* doc/invoke.texi (RS/6000 and PowerPC Options): Add missing comma
|
||||
|
@ -1,3 +1,8 @@
|
||||
2009-09-25 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/41463
|
||||
* gcc.c-torture/execute/pr41463.c: New testcase.
|
||||
|
||||
2009-09-25 Olivier Hainque <hainque@adacore.com>
|
||||
|
||||
* gnat.dg/sse_nolib.adb: New testcase.
|
||||
|
56
gcc/testsuite/gcc.c-torture/execute/pr41463.c
Normal file
56
gcc/testsuite/gcc.c-torture/execute/pr41463.c
Normal file
@ -0,0 +1,56 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
union tree_node;
|
||||
|
||||
struct tree_common
|
||||
{
|
||||
int a;
|
||||
long b;
|
||||
long c;
|
||||
void *p;
|
||||
int d;
|
||||
};
|
||||
|
||||
struct other_tree
|
||||
{
|
||||
struct tree_common common;
|
||||
int arr[14];
|
||||
};
|
||||
|
||||
struct tree_vec
|
||||
{
|
||||
struct tree_common common;
|
||||
int length;
|
||||
union tree_node *a[1];
|
||||
};
|
||||
|
||||
union tree_node
|
||||
{
|
||||
struct other_tree othr;
|
||||
struct tree_vec vec;
|
||||
};
|
||||
|
||||
union tree_node global;
|
||||
|
||||
union tree_node * __attribute__((noinline))
|
||||
foo (union tree_node *p, int i)
|
||||
{
|
||||
union tree_node **q;
|
||||
p->vec.a[i] = (union tree_node *) 0;
|
||||
q = &p->vec.a[1];
|
||||
*q = &global;
|
||||
return p->vec.a[i];
|
||||
}
|
||||
|
||||
extern void abort (void);
|
||||
extern void *malloc (__SIZE_TYPE__);
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
union tree_node *p = malloc (sizeof (union tree_node));
|
||||
if (foo (p, 1) != &global)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
||||
|
@ -799,8 +799,35 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
||||
{
|
||||
HOST_WIDE_INT hthis_offset = TREE_INT_CST_LOW (this_offset);
|
||||
hthis_offset *= BITS_PER_UNIT;
|
||||
hthis_offset
|
||||
+= TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
|
||||
bit_offset += hthis_offset;
|
||||
bit_offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
|
||||
|
||||
/* If we had seen a variable array ref already and we just
|
||||
referenced the last field of a struct or a union member
|
||||
then we have to adjust maxsize by the padding at the end
|
||||
of our field. */
|
||||
if (seen_variable_array_ref
|
||||
&& maxsize != -1)
|
||||
{
|
||||
tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
|
||||
tree next = TREE_CHAIN (field);
|
||||
while (next && TREE_CODE (next) != FIELD_DECL)
|
||||
next = TREE_CHAIN (next);
|
||||
if (!next
|
||||
|| TREE_CODE (stype) != RECORD_TYPE)
|
||||
{
|
||||
tree fsize = DECL_SIZE_UNIT (field);
|
||||
tree ssize = TYPE_SIZE_UNIT (stype);
|
||||
if (host_integerp (fsize, 0)
|
||||
&& host_integerp (ssize, 0))
|
||||
maxsize += ((TREE_INT_CST_LOW (ssize)
|
||||
- TREE_INT_CST_LOW (fsize))
|
||||
* BITS_PER_UNIT - hthis_offset);
|
||||
else
|
||||
maxsize = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -845,40 +872,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
||||
else
|
||||
{
|
||||
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.
|
||||
But we can subtract any constant offset seen so far,
|
||||
because that would get us outside of the array otherwise. */
|
||||
@ -902,7 +895,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
||||
break;
|
||||
|
||||
case VIEW_CONVERT_EXPR:
|
||||
/* ??? We probably should give up here and bail out. */
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -925,10 +917,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
|
||||
that is there for alignment purposes. */
|
||||
|
||||
if (seen_variable_array_ref
|
||||
&& (maxsize != -1
|
||||
&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
|
||||
&& bit_offset + maxsize
|
||||
== (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))
|
||||
&& maxsize != -1
|
||||
&& (!host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
|
||||
|| (bit_offset + maxsize
|
||||
== (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
|
||||
maxsize = -1;
|
||||
|
||||
/* ??? Due to negative offsets in ARRAY_REF we can end up with
|
||||
|
Loading…
Reference in New Issue
Block a user