diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 47126a1e649..c31e618ea6a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2009-06-08 Jakub Jelinek + + * 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. + 2009-06-08 Ghassan Shobaki Dwarakanath Rajagopal @@ -20,7 +28,6 @@ 2009-06-08 Michael Matz PR debug/40012 - * cfgexpand.c (set_rtl): Store place also in DECL_RTL, if all partitions use the same. (expand_one_var): Deal with DECL_RTL sometimes begin set also diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9c7651db722..2a32d8fa4b2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2009-06-08 Jakub Jelinek + * 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. + PR c++/40370 PR c++/40372 * g++.dg/template/error41.C: New test. diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-2.c index 4071c2516ee..34f16759d68 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-2.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-2.c @@ -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 (); diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-4.c index 453c2d01921..1eb30d1ba53 100644 --- a/gcc/testsuite/gcc.dg/builtin-object-size-4.c +++ b/gcc/testsuite/gcc.dg/builtin-object-size-4.c @@ -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 (); diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-6.c b/gcc/testsuite/gcc.dg/builtin-object-size-6.c new file mode 100644 index 00000000000..9a285dfb883 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-object-size-6.c @@ -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); +} diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 18e62e860fd..dbd8af482da 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -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, const_tree var) 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 object_size_type) 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)))) { - tree bytes; + unsigned HOST_WIDE_INT sz; - if (pt_var != TREE_OPERAND (ptr, 0)) + if (!osi) + sz = compute_builtin_object_size (TREE_OPERAND (pt_var, 0), + object_size_type); + else { - tree var; - - if (object_size_type & 1) - { - 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)))) - var = pt_var; - } + 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 - var = pt_var; + sz = unknown[object_size_type]; + } - bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); - if (bytes != error_mark_node) + 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 var; + + if (object_size_type & 1) + { + 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) + || (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) { - if (TREE_CODE (bytes) == INTEGER_CST - && tree_int_cst_lt (TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes)) - bytes = size_zero_node; - else - bytes = size_binop (MINUS_EXPR, - TYPE_SIZE_UNIT (TREE_TYPE (var)), bytes); + 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 - bytes = TYPE_SIZE_UNIT (TREE_TYPE (pt_var)); + var = pt_var; - if (host_integerp (bytes, 1)) - return tree_low_cst (bytes, 1); + 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 (bytes2) == INTEGER_CST + && tree_int_cst_lt (pt_var_size, bytes2)) + bytes2 = size_zero_node; + else + bytes2 = size_binop (MINUS_EXPR, var_size, bytes2); + bytes = size_binop (MIN_EXPR, bytes, bytes2); + } + } } + 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, int object_size_type) 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_info *osi, tree ptr, tree value) || !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_size_info *osi, tree var, gimple stmt) 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)