tree-object-size: Dynamic sizes for ADDR_EXPR

Allow returning dynamic expressions from ADDR_EXPR for
__builtin_dynamic_object_size and also allow offsets to be dynamic.

gcc/ChangeLog:

	PR middle-end/70090
	* tree-object-size.c (size_valid_p): New function.
	(size_for_offset): Remove OFFSET constness assertion.
	(addr_object_size): Build dynamic expressions for object
	sizes and use size_valid_p to decide if it is valid for the
	given OBJECT_SIZE_TYPE.
	(compute_builtin_object_size): Allow dynamic offsets when
	computing size at O0.
	(call_object_size): Call size_valid_p.
	(plus_stmt_object_size): Allow non-constant offset and use
	size_valid_p to decide if it is valid for the given
	OBJECT_SIZE_TYPE.

gcc/testsuite/ChangeLog:

	PR middle-end/70090
	* gcc.dg/builtin-dynamic-object-size-0.c: Add new tests.
	* gcc.dg/builtin-object-size-1.c (test1)
	[__builtin_object_size]: Adjust expected output for dynamic
	object sizes.
	* gcc.dg/builtin-object-size-2.c (test1)
	[__builtin_object_size]: Likewise.
	* gcc.dg/builtin-object-size-3.c (test1)
	[__builtin_object_size]: Likewise.
	* gcc.dg/builtin-object-size-4.c (test1)
	[__builtin_object_size]: Likewise.

Signed-off-by: Siddhesh Poyarekar <siddhesh@gotplt.org>
This commit is contained in:
Siddhesh Poyarekar 2022-01-11 08:08:27 +05:30
parent 1f07810659
commit 06bc1b0c53
6 changed files with 299 additions and 66 deletions

View File

@ -250,6 +250,79 @@ test_deploop (size_t sz, size_t cond)
return __builtin_dynamic_object_size (bin, 0);
}
/* Address expressions. */
struct dynarray_struct
{
long a;
char c[16];
int b;
};
size_t
__attribute__ ((noinline))
test_dynarray_struct (size_t sz, size_t off)
{
struct dynarray_struct bin[sz];
return __builtin_dynamic_object_size (&bin[off].c, 0);
}
size_t
__attribute__ ((noinline))
test_dynarray_struct_subobj (size_t sz, size_t off)
{
struct dynarray_struct bin[sz];
return __builtin_dynamic_object_size (&bin[off].c[4], 1);
}
size_t
__attribute__ ((noinline))
test_dynarray_struct_subobj2 (size_t sz, size_t off, size_t *objsz)
{
struct dynarray_struct2
{
long a;
int b;
char c[sz];
};
struct dynarray_struct2 bin;
*objsz = sizeof (bin);
return __builtin_dynamic_object_size (&bin.c[off], 1);
}
size_t
__attribute__ ((noinline))
test_substring (size_t sz, size_t off)
{
char str[sz];
return __builtin_dynamic_object_size (&str[off], 0);
}
size_t
__attribute__ ((noinline))
test_substring_ptrplus (size_t sz, size_t off)
{
int str[sz];
return __builtin_dynamic_object_size (str + off, 0);
}
size_t
__attribute__ ((noinline))
test_substring_ptrplus2 (size_t sz, size_t off, size_t off2)
{
int str[sz];
int *ptr = &str[off];
return __builtin_dynamic_object_size (ptr + off2, 0);
}
size_t
__attribute__ ((access (__read_write__, 1, 2)))
__attribute__ ((noinline))
@ -258,6 +331,14 @@ test_parmsz_simple (void *obj, size_t sz)
return __builtin_dynamic_object_size (obj, 0);
}
size_t
__attribute__ ((noinline))
__attribute__ ((access (__read_write__, 1, 2)))
test_parmsz (void *obj, size_t sz, size_t off)
{
return __builtin_dynamic_object_size (obj + off, 0);
}
size_t
__attribute__ ((access (__read_write__, 1, 2)))
__attribute__ ((noinline))
@ -266,6 +347,14 @@ test_parmsz_scaled (int *obj, size_t sz)
return __builtin_dynamic_object_size (obj, 0);
}
size_t
__attribute__ ((noinline))
__attribute__ ((access (__read_write__, 1, 2)))
test_parmsz_scaled_off (int *obj, size_t sz, size_t off)
{
return __builtin_dynamic_object_size (obj + off, 0);
}
size_t
__attribute__ ((access (__read_write__, 1, 3)))
__attribute__ ((noinline))
@ -274,6 +363,23 @@ test_parmsz_unknown (void *obj, void *unknown, size_t sz, int cond)
return __builtin_dynamic_object_size (cond ? obj : unknown, 0);
}
size_t
__attribute__ ((noinline))
__attribute__ ((access (__read_write__, 1, 2)))
test_loop (int *obj, size_t sz, size_t start, size_t end, int incr)
{
int *ptr = obj + start;
for (int i = start; i != end; i = i + incr)
{
ptr = ptr + incr;
if (__builtin_dynamic_object_size (ptr, 0) == 0)
return 0;
}
return __builtin_dynamic_object_size (ptr, 0);
}
unsigned nfails = 0;
#define FAIL() ({ \
@ -333,6 +439,32 @@ main (int argc, char **argv)
FAIL ();
if (test_dynarray (__builtin_strlen (argv[0])) != __builtin_strlen (argv[0]))
FAIL ();
if (test_dynarray_struct (42, 4) !=
((42 - 4) * sizeof (struct dynarray_struct)
- __builtin_offsetof (struct dynarray_struct, c)))
FAIL ();
if (test_dynarray_struct (42, 48) != 0)
FAIL ();
if (test_substring (128, 4) != 128 - 4)
FAIL ();
if (test_substring (128, 142) != 0)
FAIL ();
if (test_dynarray_struct_subobj (42, 4) != 16 - 4)
FAIL ();
if (test_dynarray_struct_subobj (42, 48) != 0)
FAIL ();
size_t objsz = 0;
if (test_dynarray_struct_subobj2 (42, 4, &objsz)
!= objsz - 4 - sizeof (long) - sizeof (int))
FAIL ();
if (test_substring_ptrplus (128, 4) != (128 - 4) * sizeof (int))
FAIL ();
if (test_substring_ptrplus (128, 142) != 0)
FAIL ();
if (test_substring_ptrplus2 (128, 4, 4) != (128 - 8) * sizeof (int))
FAIL ();
if (test_substring_ptrplus2 (128, 4, -3) != (128 - 1) * sizeof (int))
FAIL ();
if (test_dynarray_cond (0) != 16)
FAIL ();
if (test_dynarray_cond (1) != 8)
@ -349,6 +481,30 @@ main (int argc, char **argv)
FAIL ();
if (test_parmsz_unknown (argv[0], argv[0], __builtin_strlen (argv[0]) + 1, 0)
!= -1)
if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, -1) != 0)
FAIL ();
if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1, 0)
!= __builtin_strlen (argv[0]) + 1)
FAIL ();
if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1,
__builtin_strlen (argv[0])) != 1)
FAIL ();
if (test_parmsz (argv[0], __builtin_strlen (argv[0]) + 1,
__builtin_strlen (argv[0]) + 2) != 0)
FAIL ();
if (test_parmsz_scaled_off (arr, 42, 2) != 40 * sizeof (int))
FAIL ();
if (test_loop (arr, 42, 0, 32, 1) != 10 * sizeof (int))
FAIL ();
if (test_loop (arr, 42, 32, -1, -1) != 0)
FAIL ();
if (test_loop (arr, 42, 32, 10, -1) != 32 * sizeof (int))
FAIL ();
if (test_loop (arr, 42, 42, 0, -1) != 42 * sizeof (int))
FAIL ();
if (test_loop (arr, 42, 44, 0, -1) != 0)
FAIL ();
if (test_loop (arr, 42, 20, 52, 1) != 0)
FAIL ();
if (nfails > 0)

View File

@ -81,30 +81,56 @@ test1 (void *q, int x)
r = malloc (30);
else
r = calloc (2, 16);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 16))
abort ();
#else
/* We may duplicate this test onto the two exit paths. On one path
the size will be 32, the other it will be 30. If we don't duplicate
this test, then the size will be 32. */
if (__builtin_object_size (r, 0) != 2 * 16
&& __builtin_object_size (r, 0) != 30)
abort ();
#endif
if (x < 20)
r = malloc (30);
else
r = calloc (2, 14);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 0) != (x < 20 ? 30 : 2 * 14))
abort ();
#else
if (__builtin_object_size (r, 0) != 30)
abort ();
#endif
if (x < 30)
r = malloc (sizeof (a));
else
r = &a.a[3];
#ifdef __builtin_object_size
if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3))
abort ();
#else
if (__builtin_object_size (r, 0) != sizeof (a))
abort ();
#endif
r = memcpy (r, "a", 2);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 0) != (x < 30 ? sizeof (a) : sizeof (a) - 3))
abort ();
#else
if (__builtin_object_size (r, 0) != sizeof (a))
abort ();
#endif
r = memcpy (r + 2, "b", 2) + 2;
#ifdef __builtin_object_size
if (__builtin_object_size (r, 0)
!= (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7))
abort ();
#else
if (__builtin_object_size (r, 0) != sizeof (a) - 4)
abort ();
#endif
r = &a.a[4];
r = memset (r, 'a', 2);
if (__builtin_object_size (r, 0)
@ -140,14 +166,16 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (var + 10, 0) != x)
abort ();
if (__builtin_object_size (&var[5], 0) != x + 5)
abort ();
#else
if (__builtin_object_size (var, 0) != (size_t) -1)
abort ();
if (__builtin_object_size (var + 10, 0) != (size_t) -1)
abort ();
#endif
if (__builtin_object_size (&var[5], 0) != (size_t) -1)
abort ();
#endif
if (__builtin_object_size (zerol, 0) != 0)
abort ();
if (__builtin_object_size (&zerol, 0) != 0)

View File

@ -75,30 +75,56 @@ test1 (void *q, int x)
r = malloc (30);
else
r = calloc (2, 16);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 1) != (x < 20 ? 30 : 2 * 16))
abort ();
#else
/* We may duplicate this test onto the two exit paths. On one path
the size will be 32, the other it will be 30. If we don't duplicate
this test, then the size will be 32. */
if (__builtin_object_size (r, 1) != 2 * 16
&& __builtin_object_size (r, 1) != 30)
abort ();
#endif
if (x < 20)
r = malloc (30);
else
r = calloc (2, 14);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 1) != (x < 20 ? 30 : 2 * 14))
abort ();
#else
if (__builtin_object_size (r, 1) != 30)
abort ();
#endif
if (x < 30)
r = malloc (sizeof (a));
else
r = &a.a[3];
#ifdef __builtin_object_size
if (__builtin_object_size (r, 1) != (x < 30 ? sizeof (a) : sizeof (a) - 3))
abort ();
#else
if (__builtin_object_size (r, 1) != sizeof (a))
abort ();
#endif
r = memcpy (r, "a", 2);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 1) != (x < 30 ? sizeof (a) : sizeof (a) - 3))
abort ();
#else
if (__builtin_object_size (r, 1) != sizeof (a))
abort ();
#endif
r = memcpy (r + 2, "b", 2) + 2;
#ifdef __builtin_object_size
if (__builtin_object_size (r, 0)
!= (x < 30 ? sizeof (a) - 4 : sizeof (a) - 7))
abort ();
#else
if (__builtin_object_size (r, 1) != sizeof (a) - 4)
abort ();
#endif
r = &a.a[4];
r = memset (r, 'a', 2);
if (__builtin_object_size (r, 1) != sizeof (a.a) - 4)
@ -142,27 +168,28 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (var + 10, 1) != x)
abort ();
if (__builtin_object_size (&var[5], 1) != x + 5)
abort ();
if (__builtin_object_size (vara, 1) != (x + 10) * sizeof (struct A))
abort ();
if (__builtin_object_size (vara + 10, 1) != x * sizeof (struct A))
abort ();
if (__builtin_object_size (&vara[5], 1) != (x + 5) * sizeof (struct A))
abort ();
#else
if (__builtin_object_size (var, 1) != (size_t) -1)
abort ();
if (__builtin_object_size (var + 10, 1) != (size_t) -1)
abort ();
#endif
if (__builtin_object_size (&var[5], 1) != (size_t) -1)
abort ();
#ifdef __builtin_object_size
if (__builtin_object_size (vara, 1) != (x + 10) * sizeof (struct A))
abort ();
if (__builtin_object_size (vara + 10, 1) != x * sizeof (struct A))
abort ();
#else
if (__builtin_object_size (vara, 1) != (size_t) -1)
abort ();
if (__builtin_object_size (vara + 10, 1) != (size_t) -1)
abort ();
#endif
if (__builtin_object_size (&vara[5], 1) != (size_t) -1)
abort ();
#endif
if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a))
abort ();
if (__builtin_object_size (&vara[10].a[0], 1) != sizeof (vara[0].a))

View File

@ -42,9 +42,17 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (q, 2) != 0)
abort ();
#ifdef __builtin_object_size
if (__builtin_object_size (r, 2)
!= (x < 0
? sizeof (a) - __builtin_offsetof (struct A, a) - 9
: sizeof (a) - __builtin_offsetof (struct A, c) - 1))
abort ();
#else
if (__builtin_object_size (r, 2)
!= sizeof (a) - __builtin_offsetof (struct A, c) - 1)
abort ();
#endif
if (x < 6)
r = &w[2].a[1];
else
@ -58,15 +66,28 @@ test1 (void *q, int x)
if (__builtin_object_size (&y.b, 2)
!= sizeof (a) - __builtin_offsetof (struct A, b))
abort ();
#ifdef __builtin_object_size
if (__builtin_object_size (r, 2)
!= (x < 6
? 2 * sizeof (w[0]) - __builtin_offsetof (struct A, a) - 1
: sizeof (a) - __builtin_offsetof (struct A, a) - 6))
abort ();
#else
if (__builtin_object_size (r, 2)
!= sizeof (a) - __builtin_offsetof (struct A, a) - 6)
abort ();
#endif
if (x < 20)
r = malloc (30);
else
r = calloc (2, 16);
#ifdef __builtin_object_size
if (__builtin_object_size (r, 2) != (x < 20 ? 30 : 2 * 16))
abort ();
#else
if (__builtin_object_size (r, 2) != 30)
abort ();
#endif
if (x < 20)
r = malloc (30);
else
@ -145,14 +166,16 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (var + 10, 2) != x)
abort ();
if (__builtin_object_size (&var[5], 2) != x + 5)
abort ();
#else
if (__builtin_object_size (var, 2) != 0)
abort ();
if (__builtin_object_size (var + 10, 2) != 0)
abort ();
#endif
if (__builtin_object_size (&var[5], 2) != 0)
abort ();
#endif
if (__builtin_object_size (zerol, 2) != 0)
abort ();
if (__builtin_object_size (&zerol, 2) != 0)

View File

@ -155,27 +155,28 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (var + 10, 3) != x)
abort ();
if (__builtin_object_size (&var[5], 3) != x + 5)
abort ();
if (__builtin_object_size (vara, 3) != (x + 10) * sizeof (struct A))
abort ();
if (__builtin_object_size (vara + 10, 3) != x * sizeof (struct A))
abort ();
if (__builtin_object_size (&vara[5], 3) != (x + 5) * sizeof (struct A))
abort ();
#else
if (__builtin_object_size (var, 3) != 0)
abort ();
if (__builtin_object_size (var + 10, 3) != 0)
abort ();
#endif
if (__builtin_object_size (&var[5], 3) != 0)
abort ();
#ifdef __builtin_object_size
if (__builtin_object_size (vara, 3) != (x + 10) * sizeof (struct A))
abort ();
if (__builtin_object_size (vara + 10, 3) != x * sizeof (struct A))
abort ();
#else
if (__builtin_object_size (vara, 3) != 0)
abort ();
if (__builtin_object_size (vara + 10, 3) != 0)
abort ();
#endif
if (__builtin_object_size (&vara[5], 3) != 0)
abort ();
#endif
if (__builtin_object_size (&vara[0].a, 3) != sizeof (vara[0].a))
abort ();
if (__builtin_object_size (&vara[10].a[0], 3) != sizeof (vara[0].a))

View File

@ -107,6 +107,14 @@ size_unknown_p (tree val, int object_size_type)
? integer_zerop (val) : integer_all_onesp (val));
}
/* Return true if VAL represents a valid size for OBJECT_SIZE_TYPE. */
static inline bool
size_valid_p (tree val, int object_size_type)
{
return ((object_size_type & OST_DYNAMIC) || TREE_CODE (val) == INTEGER_CST);
}
/* Return true if VAL is usable as an object size in the object_sizes
vectors. */
@ -341,7 +349,6 @@ init_offset_limit (void)
static tree
size_for_offset (tree sz, tree offset, tree wholesize = NULL_TREE)
{
gcc_checking_assert (TREE_CODE (offset) == INTEGER_CST);
gcc_checking_assert (types_compatible_p (TREE_TYPE (sz), sizetype));
/* For negative offsets, if we have a distinct WHOLESIZE, use it to get a net
@ -540,18 +547,11 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
sz = wholesize = size_unknown (object_size_type);
}
if (!size_unknown_p (sz, object_size_type))
{
tree offset = TREE_OPERAND (pt_var, 1);
if (TREE_CODE (offset) != INTEGER_CST
|| TREE_CODE (sz) != INTEGER_CST)
sz = wholesize = size_unknown (object_size_type);
else
sz = size_for_offset (sz, offset, wholesize);
}
sz = size_for_offset (sz, TREE_OPERAND (pt_var, 1), wholesize);
if (!size_unknown_p (sz, object_size_type)
&& TREE_CODE (sz) == INTEGER_CST
&& compare_tree_int (sz, offset_limit) < 0)
&& (TREE_CODE (sz) != INTEGER_CST
|| compare_tree_int (sz, offset_limit) < 0))
{
pt_var_size = sz;
pt_var_wholesize = wholesize;
@ -571,8 +571,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
if (pt_var_size)
{
/* Validate the size determined above. */
if (compare_tree_int (pt_var_size, offset_limit) >= 0)
/* Validate the size determined above if it is a constant. */
if (TREE_CODE (pt_var_size) == INTEGER_CST
&& compare_tree_int (pt_var_size, offset_limit) >= 0)
return false;
}
@ -596,7 +597,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
var = TREE_OPERAND (var, 0);
if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
|| ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var)))
|| (pt_var_size
|| (pt_var_size && TREE_CODE (pt_var_size) == INTEGER_CST
&& tree_int_cst_lt (pt_var_size,
TYPE_SIZE_UNIT (TREE_TYPE (var)))))
var = pt_var;
@ -610,17 +611,11 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
switch (TREE_CODE (v))
{
case ARRAY_REF:
if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))
&& TREE_CODE (TREE_OPERAND (v, 1)) == INTEGER_CST)
if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0))))
{
tree domain
= TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)));
if (domain
&& TYPE_MAX_VALUE (domain)
&& TREE_CODE (TYPE_MAX_VALUE (domain))
== INTEGER_CST
&& tree_int_cst_lt (TREE_OPERAND (v, 1),
TYPE_MAX_VALUE (domain)))
if (domain && TYPE_MAX_VALUE (domain))
{
v = NULL_TREE;
break;
@ -687,20 +682,20 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
var = pt_var;
if (var != pt_var)
var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
{
var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
if (!TREE_CONSTANT (var_size))
var_size = get_or_create_ssa_default_def (cfun, var_size);
if (!var_size)
return false;
}
else if (!pt_var_size)
return false;
else
var_size = pt_var_size;
bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
if (bytes != error_mark_node)
{
if (TREE_CODE (bytes) == INTEGER_CST
&& tree_int_cst_lt (var_size, bytes))
bytes = size_zero_node;
else
bytes = size_binop (MINUS_EXPR, var_size, bytes);
}
bytes = size_for_offset (var_size, bytes);
if (var != pt_var
&& pt_var_size
&& TREE_CODE (pt_var) == MEM_REF
@ -709,11 +704,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
if (bytes2 != error_mark_node)
{
if (TREE_CODE (bytes2) == INTEGER_CST
&& tree_int_cst_lt (pt_var_size, bytes2))
bytes2 = size_zero_node;
else
bytes2 = size_binop (MINUS_EXPR, pt_var_size, bytes2);
bytes2 = size_for_offset (pt_var_size, bytes2);
bytes = size_binop (MIN_EXPR, bytes, bytes2);
}
}
@ -729,14 +720,18 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
wholebytes = pt_var_wholesize;
}
if (TREE_CODE (bytes) != INTEGER_CST
|| TREE_CODE (wholebytes) != INTEGER_CST)
return false;
if (!size_unknown_p (bytes, object_size_type)
&& size_valid_p (bytes, object_size_type)
&& !size_unknown_p (bytes, object_size_type)
&& size_valid_p (wholebytes, object_size_type))
{
*psize = bytes;
if (pwholesize)
*pwholesize = wholebytes;
return true;
}
*psize = bytes;
if (pwholesize)
*pwholesize = wholebytes;
return true;
return false;
}
@ -1058,11 +1053,11 @@ compute_builtin_object_size (tree ptr, int object_size_type,
tree offset = gimple_assign_rhs2 (def);
ptr = gimple_assign_rhs1 (def);
if (tree_fits_shwi_p (offset)
if (((object_size_type & OST_DYNAMIC)
|| tree_fits_shwi_p (offset))
&& compute_builtin_object_size (ptr, object_size_type,
psize))
{
/* Return zero when the offset is out of bounds. */
*psize = size_for_offset (*psize, offset);
return true;
}
@ -1247,7 +1242,7 @@ call_object_size (struct object_size_info *osi, tree ptr, gcall *call)
gcc_assert (osi->pass == 0);
tree bytes = alloc_object_size (call, object_size_type);
if (!(object_size_type & OST_DYNAMIC) && TREE_CODE (bytes) != INTEGER_CST)
if (!size_valid_p (bytes, object_size_type))
bytes = size_unknown (object_size_type);
object_sizes_set (osi, varno, bytes, bytes);
@ -1328,9 +1323,8 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt)
return false;
/* Handle PTR + OFFSET here. */
if (TREE_CODE (op1) == INTEGER_CST
&& (TREE_CODE (op0) == SSA_NAME
|| TREE_CODE (op0) == ADDR_EXPR))
if (size_valid_p (op1, object_size_type)
&& (TREE_CODE (op0) == SSA_NAME || TREE_CODE (op0) == ADDR_EXPR))
{
if (TREE_CODE (op0) == SSA_NAME)
{
@ -1358,6 +1352,10 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt)
else
bytes = wholesize = size_unknown (object_size_type);
if (!size_valid_p (bytes, object_size_type)
|| !size_valid_p (wholesize, object_size_type))
bytes = wholesize = size_unknown (object_size_type);
if (object_sizes_set (osi, varno, bytes, wholesize))
osi->changed = true;
return reexamine;