diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07e73eaa0fa779c9cd3291b24b087f87a4fbca62..6bc0bd6809bec612ebf71b78a3101f515b8dccc4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-10-12 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/50700 + * tree-object-size.c (addr_object_size): Simplify and treat + MEM_REF bases consistently. + 2011-10-12 Bernd Schmidt <bernds@codesourcery.com> * function.c (prepare_shrink_wrap, bb_active_p): New function. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 70f89f9330cd27c3286b38fde585129e030fa5e0..827aa2dced8565171aa9088b605c8882de7f5ccb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-10-12 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/50700 + * gcc.dg/builtin-object-size-12.c: New testcase. + 2011-10-12 Joseph Myers <joseph@codesourcery.com> PR c/50565 diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-12.c b/gcc/testsuite/gcc.dg/builtin-object-size-12.c new file mode 100644 index 0000000000000000000000000000000000000000..b21eb0071b340325360e0f4922d41276cf3b7642 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-12.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void); +struct S { + int len; + char s[0]; +}; +int main() +{ + char buf[sizeof (struct S) + 32]; + if (__builtin_object_size (((struct S *)&buf[0])->s, 1) != 32) + abort (); + if (__builtin_object_size (((struct S *)&buf[1])->s, 1) != 31) + abort (); + if (__builtin_object_size (((struct S *)&buf[64])->s, 0) != 0) + abort (); + return 0; +} diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 2998fb59da05edf6f56f64b2a11c24c5ee2904ea..017f8c5e933c9c1b9ed54b9c71c3ef4baf8e26c5 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -166,24 +166,19 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, gcc_assert (TREE_CODE (ptr) == ADDR_EXPR); pt_var = TREE_OPERAND (ptr, 0); - if (REFERENCE_CLASS_P (pt_var)) - pt_var = get_base_address (pt_var); + while (handled_component_p (pt_var)) + pt_var = TREE_OPERAND (pt_var, 0); if (pt_var - && TREE_CODE (pt_var) == MEM_REF - && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME - && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0)))) + && TREE_CODE (pt_var) == MEM_REF) { unsigned HOST_WIDE_INT sz; - if (!osi || (object_size_type & 1) != 0) + if (!osi || (object_size_type & 1) != 0 + || TREE_CODE (pt_var) != SSA_NAME) { sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0), object_size_type & ~1); - if (host_integerp (TREE_OPERAND (pt_var, 1), 0)) - sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1)); - else - sz = offset_limit; } else { @@ -195,10 +190,17 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)]; else sz = unknown[object_size_type]; - if (host_integerp (TREE_OPERAND (pt_var, 1), 0)) - sz -= TREE_INT_CST_LOW (TREE_OPERAND (pt_var, 1)); + } + if (sz != unknown[object_size_type]) + { + double_int dsz = double_int_sub (uhwi_to_double_int (sz), + mem_ref_offset (pt_var)); + if (double_int_negative_p (dsz)) + sz = 0; + else if (double_int_fits_in_uhwi_p (dsz)) + sz = double_int_to_uhwi (dsz); else - sz = offset_limit; + sz = unknown[object_size_type]; } if (sz != unknown[object_size_type] && sz < offset_limit) @@ -211,7 +213,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, tree_low_cst (DECL_SIZE_UNIT (pt_var), 1) < offset_limit) pt_var_size = DECL_SIZE_UNIT (pt_var); else if (pt_var - && (SSA_VAR_P (pt_var) || TREE_CODE (pt_var) == STRING_CST) + && TREE_CODE (pt_var) == STRING_CST && TYPE_SIZE_UNIT (TREE_TYPE (pt_var)) && host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) && (unsigned HOST_WIDE_INT)