Commit 79441eca by Richard Guenther Committed by Richard Biener

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
parent 6ef41fd0
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> 2009-09-25 Ben Elliston <bje@au.ibm.com>
* doc/invoke.texi (RS/6000 and PowerPC Options): Add missing comma * doc/invoke.texi (RS/6000 and PowerPC Options): Add missing comma
......
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> 2009-09-25 Olivier Hainque <hainque@adacore.com>
* gnat.dg/sse_nolib.adb: New testcase. * gnat.dg/sse_nolib.adb: New testcase.
......
#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, ...@@ -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); HOST_WIDE_INT hthis_offset = TREE_INT_CST_LOW (this_offset);
hthis_offset *= BITS_PER_UNIT; hthis_offset *= BITS_PER_UNIT;
hthis_offset
+= TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
bit_offset += hthis_offset; 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 else
{ {
...@@ -845,40 +872,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -845,40 +872,6 @@ 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. */
...@@ -902,7 +895,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -902,7 +895,6 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
break; break;
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
/* ??? We probably should give up here and bail out. */
break; break;
default: default:
...@@ -925,10 +917,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -925,10 +917,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
that is there for alignment purposes. */ that is there for alignment purposes. */
if (seen_variable_array_ref if (seen_variable_array_ref
&& (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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment