summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-09-25 12:12:51 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-09-25 12:12:51 +0000
commit79441eca0eb2fc14297a09ac73fde9a629a72941 (patch)
tree43b83ef28811075b335e9d3175c045885975e100
parent6ef41fd08f9e000c1842a2309969fb8bb0f347c9 (diff)
downloadgcc-79441eca0eb2fc14297a09ac73fde9a629a72941.tar.gz
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr41463.c56
-rw-r--r--gcc/tree-dfa.c72
4 files changed, 99 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6d4c47b3b6a..331faa147e2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9fcd65db5aa..3ad55f87bdd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr41463.c b/gcc/testsuite/gcc.c-torture/execute/pr41463.c
new file mode 100644
index 00000000000..c410fe0218b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr41463.c
@@ -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;
+}
+
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 3fd8477cf7e..847a6818b1b 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -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