gcc/gcc44-builtin-object-size.p...

765 lines
23 KiB
Diff

2009-06-08 Jakub Jelinek <jakub@redhat.com>
* tree-object-size.c (addr_object_size): Add OSI argument.
Handle also INDIRECT_REF with SSA_NAME inside of it as base address.
(compute_builtin_object_size, expr_object_size): Adjust callers.
(plus_stmt_object_size): Call addr_object_size instead of
compute_builtin_object_size.
* gcc.dg/builtin-object-size-2.c (test1): Adjust expected results.
* gcc.dg/builtin-object-size-4.c (test1): Adjust expected results.
* gcc.dg/builtin-object-size-6.c: New test.
--- gcc/testsuite/gcc.dg/builtin-object-size-4.c (revision 148278)
+++ gcc/testsuite/gcc.dg/builtin-object-size-4.c (revision 148279)
@@ -130,15 +130,15 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (&vara[5], 3) != 0)
abort ();
- if (__builtin_object_size (&vara[0].a, 3) != 0)
+ if (__builtin_object_size (&vara[0].a, 3) != sizeof (vara[0].a))
abort ();
- if (__builtin_object_size (&vara[10].a[0], 3) != 0)
+ if (__builtin_object_size (&vara[10].a[0], 3) != sizeof (vara[0].a))
abort ();
- if (__builtin_object_size (&vara[5].a[4], 3) != 0)
+ if (__builtin_object_size (&vara[5].a[4], 3) != sizeof (vara[0].a) - 4)
abort ();
- if (__builtin_object_size (&vara[5].b, 3) != 0)
+ if (__builtin_object_size (&vara[5].b, 3) != sizeof (vara[0].b))
abort ();
- if (__builtin_object_size (&vara[7].c[7], 3) != 0)
+ if (__builtin_object_size (&vara[7].c[7], 3) != sizeof (vara[0].c) - 7)
abort ();
if (__builtin_object_size (zerol, 3) != 0)
abort ();
--- gcc/testsuite/gcc.dg/builtin-object-size-2.c (revision 148278)
+++ gcc/testsuite/gcc.dg/builtin-object-size-2.c (revision 148279)
@@ -130,15 +130,15 @@ test1 (void *q, int x)
abort ();
if (__builtin_object_size (&vara[5], 1) != (size_t) -1)
abort ();
- if (__builtin_object_size (&vara[0].a, 1) != (size_t) -1)
+ if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a))
abort ();
- if (__builtin_object_size (&vara[10].a[0], 1) != (size_t) -1)
+ if (__builtin_object_size (&vara[10].a[0], 1) != sizeof (vara[0].a))
abort ();
- if (__builtin_object_size (&vara[5].a[4], 1) != (size_t) -1)
+ if (__builtin_object_size (&vara[5].a[4], 1) != sizeof (vara[0].a) - 4)
abort ();
- if (__builtin_object_size (&vara[5].b, 1) != (size_t) -1)
+ if (__builtin_object_size (&vara[5].b, 1) != sizeof (vara[0].b))
abort ();
- if (__builtin_object_size (&vara[7].c[7], 1) != (size_t) -1)
+ if (__builtin_object_size (&vara[7].c[7], 1) != sizeof (vara[0].c) - 7)
abort ();
if (__builtin_object_size (zerol, 1) != 0)
abort ();
--- gcc/testsuite/gcc.dg/builtin-object-size-6.c (revision 0)
+++ gcc/testsuite/gcc.dg/builtin-object-size-6.c (revision 148279)
@@ -0,0 +1,435 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern void free (void *);
+
+struct A
+{
+ char a[10];
+ int b;
+ char c[10];
+};
+
+void
+__attribute__ ((noinline))
+test1 (struct A *p)
+{
+ char *c;
+ if (__builtin_object_size (&p->a, 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&p->b, 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&p->c, 0) != (size_t) -1)
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 0) != (size_t) -1)
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 0) != (size_t) -1)
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 0) != (size_t) -1)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 0) != (size_t) -1)
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&p->a, 1) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[0], 1) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[3], 1) != sizeof (p->a) - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 1) != sizeof (p->b))
+ abort ();
+ if (__builtin_object_size (&p->c, 1) != (size_t) -1)
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 1) != sizeof (p->a))
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 1) != sizeof (p->a))
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 1) != sizeof (p->a) - 3)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 1) != sizeof (p->b))
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 1) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&p->a, 2) != 0)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 2) != 0)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 2) != 0)
+ abort ();
+ if (__builtin_object_size (&p->b, 2) != 0)
+ abort ();
+ if (__builtin_object_size (&p->c, 2) != 0)
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 2) != 0)
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 2) != 0)
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 2) != 0)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 2) != 0)
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 2) != 0)
+ abort ();
+ if (__builtin_object_size (&p->a, 3) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[0], 3) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[3], 3) != sizeof (p->a) - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 3) != sizeof (p->b))
+ abort ();
+ if (__builtin_object_size (&p->c, 3) != 0)
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 3) != sizeof (p->a))
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 3) != sizeof (p->a))
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 3) != sizeof (p->a) - 3)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 3) != sizeof (p->b))
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 3) != 0)
+ abort ();
+}
+
+void
+__attribute__ ((noinline))
+test2 (void)
+{
+ char *c;
+ size_t s = 2 * sizeof (struct A);
+ struct A *p = malloc (2 * sizeof (struct A));
+ if (__builtin_object_size (&p->a, 0) != s)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 0) != s)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 0) != s - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 0) != s - __builtin_offsetof (struct A, b))
+ abort ();
+ if (__builtin_object_size (&p->c, 0) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 0) != s)
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 0) != s)
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 0) != s - 3)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 0) != s - __builtin_offsetof (struct A, b))
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 0) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ if (__builtin_object_size (&p->a, 1) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[0], 1) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[3], 1) != sizeof (p->a) - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 1) != sizeof (p->b))
+ abort ();
+ if (__builtin_object_size (&p->c, 1) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 1) != sizeof (p->a))
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 1) != sizeof (p->a))
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 1) != sizeof (p->a) - 3)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 1) != sizeof (p->b))
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 1) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ if (__builtin_object_size (&p->a, 2) != s)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 2) != s)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 2) != s - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 2) != s - __builtin_offsetof (struct A, b))
+ abort ();
+ if (__builtin_object_size (&p->c, 2) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 2) != s)
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 2) != s)
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 2) != s - 3)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 2) != s - __builtin_offsetof (struct A, b))
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 2) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ if (__builtin_object_size (&p->a, 3) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[0], 3) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[3], 3) != sizeof (p->a) - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 3) != sizeof (p->b))
+ abort ();
+ if (__builtin_object_size (&p->c, 3) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ c = p->a;
+ if (__builtin_object_size (c, 3) != sizeof (p->a))
+ abort ();
+ c = &p->a[0];
+ if (__builtin_object_size (c, 3) != sizeof (p->a))
+ abort ();
+ c = &p->a[3];
+ if (__builtin_object_size (c, 3) != sizeof (p->a) - 3)
+ abort ();
+ c = (char *) &p->b;
+ if (__builtin_object_size (c, 3) != sizeof (p->b))
+ abort ();
+ c = (char *) &p->c;
+ if (__builtin_object_size (c, 3) != s - __builtin_offsetof (struct A, c))
+ abort ();
+ free (p);
+}
+
+void
+__attribute__ ((noinline))
+test3 (void)
+{
+ char *c;
+ size_t s;
+ struct A *p = malloc (4);
+ if (__builtin_object_size (&p->a, 0) != 4)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 0) != 4)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 0) != 1)
+ abort ();
+ if (__builtin_object_size (&p->b, 0) != 0)
+ abort ();
+ if (__builtin_object_size (&p->c, 0) != 0)
+ abort ();
+ if (__builtin_object_size (&p->a, 1) != 4)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 1) != 4)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 1) != 1)
+ abort ();
+ if (__builtin_object_size (&p->b, 1) != 0)
+ abort ();
+ if (__builtin_object_size (&p->c, 1) != 0)
+ abort ();
+ free (p);
+ s = __builtin_offsetof (struct A, c) + 4;
+ p = malloc (s);
+ if (__builtin_object_size (&p->a, 0) != s)
+ abort ();
+ if (__builtin_object_size (&p->a[0], 0) != s)
+ abort ();
+ if (__builtin_object_size (&p->a[3], 0) != s - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 0) != s - __builtin_offsetof (struct A, b))
+ abort ();
+ if (__builtin_object_size (&p->c, 0) != 4)
+ abort ();
+ if (__builtin_object_size (&p->a, 1) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[0], 1) != sizeof (p->a))
+ abort ();
+ if (__builtin_object_size (&p->a[3], 1) != sizeof (p->a) - 3)
+ abort ();
+ if (__builtin_object_size (&p->b, 1) != sizeof (p->b))
+ abort ();
+ if (__builtin_object_size (&p->c, 1) != 4)
+ abort ();
+ free (p);
+}
+
+struct B
+{
+ struct A a[4];
+};
+
+void
+__attribute__ ((noinline))
+test4 (struct B *q, int i)
+{
+ if (__builtin_object_size (&q->a[2].a[2], 1) != sizeof (q->a[0].a) - 2)
+ abort ();
+ if (__builtin_object_size (&q->a[2].c[2], 1) != sizeof (q->a[0].c) - 2)
+ abort ();
+ if (__builtin_object_size (&q->a[3].a[2], 1) != sizeof (q->a[0].a) - 2)
+ abort ();
+ if (__builtin_object_size (&q->a[3].c[2], 1) != sizeof (q->a[0].c) - 2)
+ abort ();
+ if (__builtin_object_size (&q->a[i].a[2], 1) != sizeof (q->a[0].a) - 2)
+ abort ();
+ if (__builtin_object_size (&q->a[i].c[2], 1) != sizeof (q->a[0].c) - 2)
+ abort ();
+}
+
+struct C
+{
+ char a[10];
+ char b;
+};
+
+void
+__attribute__ ((noinline))
+test5 (struct C *c)
+{
+ if (__builtin_object_size (&c->b, 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&c->b, 1) != 1)
+ abort ();
+ if (__builtin_object_size (&c->b, 2) != 0)
+ abort ();
+ if (__builtin_object_size (&c->b, 3) != 1)
+ abort ();
+}
+
+struct D
+{
+ int i;
+ struct D1
+ {
+ char b;
+ char a[10];
+ } j;
+};
+
+void
+__attribute__ ((noinline))
+test6 (struct D *d)
+{
+ if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3)
+ abort ();
+ if (__builtin_object_size (&d->j.a[3], 2) != 0)
+ abort ();
+ if (__builtin_object_size (&d->j.a[3], 3) != sizeof (d->j.a) - 3)
+ abort ();
+}
+
+struct E
+{
+ int i;
+ struct E1
+ {
+ char b;
+ char a[10];
+ } j[1];
+};
+
+void
+__attribute__ ((noinline))
+test7 (struct E *e)
+{
+ if (__builtin_object_size (&e->j[0].a[3], 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&e->j[0].a[3], 1) != sizeof (e->j[0].a) - 3)
+ abort ();
+ if (__builtin_object_size (&e->j[0].a[3], 2) != 0)
+ abort ();
+ if (__builtin_object_size (&e->j[0].a[3], 3) != sizeof (e->j[0].a) - 3)
+ abort ();
+ if (__builtin_object_size ((char *) &e->j[0], 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size ((char *) &e->j[0], 1) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size ((char *) &e->j[0], 2) != 0)
+ abort ();
+ if (__builtin_object_size ((char *) &e->j[0], 3) != 0)
+ abort ();
+}
+
+union F
+{
+ char a[1];
+ struct F1
+ {
+ char b;
+ char c[10];
+ } d;
+};
+
+void
+__attribute__ ((noinline))
+test8 (union F *f)
+{
+ if (__builtin_object_size (&f->d.c[3], 0) != (size_t) -1)
+ abort ();
+ if (__builtin_object_size (&f->d.c[3], 1) != sizeof (f->d.c) - 3)
+ abort ();
+ if (__builtin_object_size (&f->d.c[3], 2) != 0)
+ abort ();
+ if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3)
+ abort ();
+}
+
+int
+main (void)
+{
+ struct A a, *p = &a;
+ int i = 1;
+ __asm ("" : "+r" (p));
+ test1 (p);
+ test2 ();
+ test3 ();
+ struct B b, *q = &b;
+ __asm ("" : "+r" (q), "+r" (i));
+ test4 (q, i);
+ struct C c, *cp = &c;
+ __asm ("" : "+r" (cp));
+ test5 (cp);
+ struct D d, *dp = &d;
+ __asm ("" : "+r" (dp));
+ test6 (dp);
+ struct E e, *ep = &e;
+ __asm ("" : "+r" (ep));
+ test7 (ep);
+ union F f, *fp = &f;
+ __asm ("" : "+r" (fp));
+ test8 (fp);
+ exit (0);
+}
--- gcc/tree-object-size.c (revision 148278)
+++ gcc/tree-object-size.c (revision 148279)
@@ -43,7 +43,8 @@ struct object_size_info
static unsigned HOST_WIDE_INT unknown[4] = { -1, -1, 0, 0 };
static tree compute_object_offset (const_tree, const_tree);
-static unsigned HOST_WIDE_INT addr_object_size (const_tree, int);
+static unsigned HOST_WIDE_INT addr_object_size (struct object_size_info *,
+ const_tree, int);
static unsigned HOST_WIDE_INT alloc_object_size (const_gimple, int);
static tree pass_through_call (const_gimple);
static void collect_object_sizes_for (struct object_size_info *, tree);
@@ -152,9 +153,10 @@ compute_object_offset (const_tree expr,
If unknown, return unknown[object_size_type]. */
static unsigned HOST_WIDE_INT
-addr_object_size (const_tree ptr, int object_size_type)
+addr_object_size (struct object_size_info *osi, const_tree ptr,
+ int object_size_type)
{
- tree pt_var;
+ tree pt_var, pt_var_size = NULL_TREE, var_size, bytes;
gcc_assert (TREE_CODE (ptr) == ADDR_EXPR);
@@ -163,58 +165,170 @@ addr_object_size (const_tree ptr, int ob
pt_var = get_base_address (pt_var);
if (pt_var
- && (SSA_VAR_P (pt_var) || 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)
- tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1) < offset_limit)
+ && TREE_CODE (pt_var) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (pt_var, 0)) == SSA_NAME
+ && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (pt_var, 0))))
+ {
+ unsigned HOST_WIDE_INT sz;
+
+ if (!osi)
+ sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0),
+ object_size_type);
+ else
+ {
+ tree var = TREE_OPERAND (pt_var, 0);
+ if (osi->pass == 0)
+ collect_object_sizes_for (osi, var);
+ if (bitmap_bit_p (computed[object_size_type],
+ SSA_NAME_VERSION (var)))
+ sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)];
+ else
+ sz = unknown[object_size_type];
+ }
+
+ if (sz != unknown[object_size_type] && sz < offset_limit)
+ pt_var_size = size_int (sz);
+ }
+ else if (pt_var
+ && (SSA_VAR_P (pt_var) || 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)
+ tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)), 1)
+ < offset_limit)
+ pt_var_size = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
+ else
+ return unknown[object_size_type];
+
+ if (pt_var != TREE_OPERAND (ptr, 0))
{
- tree bytes;
+ tree var;
- if (pt_var != TREE_OPERAND (ptr, 0))
+ if (object_size_type & 1)
{
- tree var;
+ var = TREE_OPERAND (ptr, 0);
- if (object_size_type & 1)
+ while (var != pt_var
+ && TREE_CODE (var) != BIT_FIELD_REF
+ && TREE_CODE (var) != COMPONENT_REF
+ && TREE_CODE (var) != ARRAY_REF
+ && TREE_CODE (var) != ARRAY_RANGE_REF
+ && TREE_CODE (var) != REALPART_EXPR
+ && TREE_CODE (var) != IMAGPART_EXPR)
+ var = TREE_OPERAND (var, 0);
+ if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
+ var = TREE_OPERAND (var, 0);
+ if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
+ || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
+ || (pt_var_size
+ && tree_int_cst_lt (pt_var_size,
+ TYPE_SIZE_UNIT (TREE_TYPE (var)))))
+ var = pt_var;
+ else if (var != pt_var && TREE_CODE (pt_var) == INDIRECT_REF)
{
- var = TREE_OPERAND (ptr, 0);
-
- while (var != pt_var
- && TREE_CODE (var) != BIT_FIELD_REF
- && TREE_CODE (var) != COMPONENT_REF
- && TREE_CODE (var) != ARRAY_REF
- && TREE_CODE (var) != ARRAY_RANGE_REF
- && TREE_CODE (var) != REALPART_EXPR
- && TREE_CODE (var) != IMAGPART_EXPR)
- var = TREE_OPERAND (var, 0);
- if (var != pt_var && TREE_CODE (var) == ARRAY_REF)
- var = TREE_OPERAND (var, 0);
- if (! TYPE_SIZE_UNIT (TREE_TYPE (var))
- || ! host_integerp (TYPE_SIZE_UNIT (TREE_TYPE (var)), 1)
- || tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (pt_var)),
- TYPE_SIZE_UNIT (TREE_TYPE (var))))
+ tree v = var;
+ /* For &X->fld, compute object size only if fld isn't the last
+ field, as struct { int i; char c[1]; } is often used instead
+ of flexible array member. */
+ while (v && v != pt_var)
+ 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)
+ {
+ 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)))
+ {
+ v = NULL_TREE;
+ break;
+ }
+ }
+ v = TREE_OPERAND (v, 0);
+ break;
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ v = NULL_TREE;
+ break;
+ case COMPONENT_REF:
+ if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE
+ && TREE_CHAIN (TREE_OPERAND (v, 1)))
+ || TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+ v = NULL_TREE;
+ else
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+ v = TREE_OPERAND (v, 0);
+ while (v && v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+ if (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE
+ && TREE_CODE (TREE_TYPE (v)) != QUAL_UNION_TYPE)
+ break;
+ else
+ v = TREE_OPERAND (v, 0);
+ if (v && v != pt_var)
+ v = NULL_TREE;
+ else
+ v = pt_var;
+ }
+ break;
+ default:
+ v = pt_var;
+ break;
+ }
+ if (v == pt_var)
var = pt_var;
}
- else
- var = pt_var;
+ }
+ else
+ var = pt_var;
- bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var);
- if (bytes != error_mark_node)
+ if (var != pt_var)
+ var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
+ else if (!pt_var_size)
+ return unknown[object_size_type];
+ 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);
+ }
+ if (var != pt_var
+ && pt_var_size
+ && TREE_CODE (pt_var) == INDIRECT_REF
+ && bytes != error_mark_node)
+ {
+ tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), pt_var);
+ if (bytes2 != error_mark_node)
{
- if (TREE_CODE (bytes) == INTEGER_CST
- && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes))
- bytes = size_zero_node;
+ if (TREE_CODE (bytes2) == INTEGER_CST
+ && tree_int_cst_lt (pt_var_size, bytes2))
+ bytes2 = size_zero_node;
else
- bytes = size_binop (MINUS_EXPR,
- TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes);
+ bytes2 = size_binop (MINUS_EXPR, var_size, bytes2);
+ bytes = size_binop (MIN_EXPR, bytes, bytes2);
}
}
- else
- bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var));
-
- if (host_integerp (bytes, 1))
- return tree_low_cst (bytes, 1);
}
+ else if (!pt_var_size)
+ return unknown[object_size_type];
+ else
+ bytes = pt_var_size;
+
+ if (host_integerp (bytes, 1))
+ return tree_low_cst (bytes, 1);
return unknown[object_size_type];
}
@@ -332,11 +446,11 @@ compute_builtin_object_size (tree ptr, i
init_offset_limit ();
if (TREE_CODE (ptr) == ADDR_EXPR)
- return addr_object_size (ptr, object_size_type);
+ return addr_object_size (NULL, ptr, object_size_type);
if (TREE_CODE (ptr) == SSA_NAME
- && POINTER_TYPE_P (TREE_TYPE (ptr))
- && object_sizes[object_size_type] != NULL)
+ && POINTER_TYPE_P (TREE_TYPE (ptr))
+ && object_sizes[object_size_type] != NULL)
{
if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)))
{
@@ -477,7 +591,7 @@ expr_object_size (struct object_size_inf
|| !POINTER_TYPE_P (TREE_TYPE (value)));
if (TREE_CODE (value) == ADDR_EXPR)
- bytes = addr_object_size (value, object_size_type);
+ bytes = addr_object_size (osi, value, object_size_type);
else
bytes = unknown[object_size_type];
@@ -633,7 +747,7 @@ plus_stmt_object_size (struct object_siz
unsigned HOST_WIDE_INT off = tree_low_cst (op1, 1);
/* op0 will be ADDR_EXPR here. */
- bytes = compute_builtin_object_size (op0, object_size_type);
+ bytes = addr_object_size (osi, op0, object_size_type);
if (bytes == unknown[object_size_type])
;
else if (off > offset_limit)