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:
parent
1f07810659
commit
06bc1b0c53
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user