r16-1905-g7165ca43caf470 incorrectly returned the size of *_1 for a GIMPLE_ASSIGN of type:
ptr = *_1; This is only OK when _1 is set to .ACCESS_WITH_SIZE, since that builtin expresses the size of *_1 in the form of _1. gcc/ChangeLog: * tree-object-size.cc (is_access_with_size): New function. (collect_object_sizes_for): Use it. gcc/testsuite/ChangeLog: * gcc.dg/pr120929.c: New test case. Signed-off-by: Siddhesh Poyarekar <siddh...@gotplt.org> --- Bootstraps in progress. gcc/testsuite/gcc.dg/pr120929.c | 57 +++++++++++++++++++++++++++++++++ gcc/tree-object-size.cc | 40 ++++++++++++++++------- 2 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr120929.c diff --git a/gcc/testsuite/gcc.dg/pr120929.c b/gcc/testsuite/gcc.dg/pr120929.c new file mode 100644 index 00000000000..2730ca79062 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr120929.c @@ -0,0 +1,57 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +#include "builtin-object-size-common.h" + +typedef __SIZE_TYPE__ size_t; + +void +__attribute__ ((noinline)) +pin_pointer(void *) +{ +} + +struct magic_ { + char unused[9]; // at least 9 +}; + +struct magic_map { + struct magic_ *magic; +}; + +static int +coalesce_entries(struct magic_ **ma) +{ + size_t slen; + + slen = sizeof (**ma); + *ma = __builtin_malloc (slen); + + for (unsigned i = 0; i < 1; i++) + { + char b[1024] = {}; + struct magic_ *ptr = *ma; + /* It should either give the correct size or fail graciously. */ + if (__builtin_dynamic_object_size (ptr, 0) != sizeof (**ma) + && __builtin_dynamic_object_size (ptr, 0) != (size_t) -1) + FAIL (); + } + return 0; +} + +int +main (void) +{ + char buf[128]; // did not shrink, but needs to be more than 100 + struct magic_map *map2; + + map2 = __builtin_malloc (sizeof (*map2)); + + pin_pointer(&buf); + coalesce_entries(&map2->magic); + pin_pointer(map2); + + DONE (); + + return 0; +} diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index a551f2b4068..bfb0379430e 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -1858,6 +1858,20 @@ phi_dynamic_object_size (struct object_size_info *osi, tree var) object_sizes_set (osi, varno, sizes, wholesizes); } +/* Return true if PTR is defined with .ACCESS_WITH_SIZE. */ + +static bool +is_access_with_size (tree ptr) +{ + gcc_assert (TREE_CODE (ptr) == SSA_NAME); + + gimple *stmt = SSA_NAME_DEF_STMT (ptr); + if (gimple_code (stmt) != GIMPLE_CALL) + return false; + + return gimple_call_internal_p (as_a <gcall *> (stmt), IFN_ACCESS_WITH_SIZE); +} + /* Compute object sizes for VAR. For ADDR_EXPR an object size is the number of remaining bytes to the end of the object (where what is considered an object depends on @@ -1941,20 +1955,24 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) else if (gimple_assign_single_p (stmt) || gimple_assign_unary_nop_p (stmt)) { + /* If RHS is a MEM_REF of PTR with zero offset, the size may be + expressed with the .ACCESS_WITH_SIZE builtin in the form of + &PTR, so look for that if available. This is the sample IR of + this situation: + 1 _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B); + 2 _5 = *_1; + 3 _6 = __builtin_dynamic_object_size (_5, 1); + */ + if (TREE_CODE (rhs) == MEM_REF + && POINTER_TYPE_P (TREE_TYPE (rhs)) + && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME + && integer_zerop (TREE_OPERAND (rhs, 1)) + && is_access_with_size (TREE_OPERAND (rhs, 0))) + rhs = TREE_OPERAND (rhs, 0); + if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) reexamine = merge_object_sizes (osi, var, rhs); - /* Handle the following stmt #2 to propagate the size from the - stmt #1 to #3: - 1 _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B); - 2 _5 = *_1; - 3 _6 = __builtin_dynamic_object_size (_5, 1); - */ - else if (TREE_CODE (rhs) == MEM_REF - && POINTER_TYPE_P (TREE_TYPE (rhs)) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME - && integer_zerop (TREE_OPERAND (rhs, 1))) - reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, 0)); else expr_object_size (osi, var, rhs); } -- 2.50.0