diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr49079.c | 31 | ||||
-rw-r--r-- | gcc/tree-dfa.c | 28 |
4 files changed, 64 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a14e54f3978..821c0dd18ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2011-05-20 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/49079 + * tree-dfa.c (get_ref_base_and_extent): Handle view-converting + MEM_REFs correctly for the trailing array access detection. + Special case constants the same way as decls for overall size + constraining. + 2011-05-20 Uros Bizjak <ubizjak@gmail.com> * config/i386/mingw32.h (OUTPUT_QUOTED_STRING): Fix macro diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5e2bffedcc6..2bdb809c11f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-05-20 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/49079 + * gcc.dg/torture/pr49079.c: New testcase. + 2011-05-20 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/49073 diff --git a/gcc/testsuite/gcc.dg/torture/pr49079.c b/gcc/testsuite/gcc.dg/torture/pr49079.c new file mode 100644 index 00000000000..1b53d3c3126 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr49079.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +extern void abort (void); + +struct Ustr +{ + unsigned char data[1]; +}; + +static unsigned int +ustr_xi__embed_val_get(const unsigned char *data) +{ + return (unsigned int)data[0]; +} + +int __attribute__((noinline)) zero(void) { return 0; } + +static unsigned int +ustr_len(const struct Ustr *s1) +{ + return ustr_xi__embed_val_get(s1->data + 1 + zero()); +} + +int +main() +{ + if (ustr_len (((struct Ustr *) "\x01" "\x0002" "s2")) != 2) + abort (); + + return 0; +} diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 70e3c1d35cd..9791bccecae 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -714,6 +714,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, tree size_tree = NULL_TREE; HOST_WIDE_INT bit_offset = 0; bool seen_variable_array_ref = false; + tree base_type; /* First get the final access size from just the outermost expression. */ if (TREE_CODE (exp) == COMPONENT_REF) @@ -744,6 +745,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, and find the ultimate containing object. */ while (1) { + base_type = TREE_TYPE (exp); + switch (TREE_CODE (exp)) { case BIT_FIELD_REF: @@ -931,9 +934,16 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, the array. The simplest way to conservatively deal with this is to punt in the case that offset + maxsize reaches the base type boundary. This needs to include possible trailing padding - that is there for alignment purposes. + that is there for alignment purposes. */ + + if (seen_variable_array_ref + && maxsize != -1 + && (!host_integerp (TYPE_SIZE (base_type), 1) + || (bit_offset + maxsize + == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type))))) + maxsize = -1; - That is of course only true if the base object is not a decl. */ + /* In case of a decl or constant base object we can do better. */ if (DECL_P (exp)) { @@ -943,12 +953,14 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, && host_integerp (DECL_SIZE (exp), 1)) maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - bit_offset; } - else 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; + else if (CONSTANT_CLASS_P (exp)) + { + /* If maxsize is unknown adjust it according to the size of the + base type constant. */ + if (maxsize == -1 + && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)) + maxsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) - bit_offset; + } /* ??? Due to negative offsets in ARRAY_REF we can end up with negative bit_offset here. We might want to store a zero offset |