Hi, Siddhesh, Thanks a lot for this patch, after -fstrict-flex-array functionality has been added into GCC, I think that making the tree-object-size to have consistent behavior with flex arrays is a valuable and natural work that need to be added.
I also like the comments you added into tree-object-size.cc, making the code much easier to be understood. Minor comments below: > On Dec 21, 2022, at 5:25 PM, Siddhesh Poyarekar <siddh...@gotplt.org> wrote: > > The tree object size pass tries to fail when it detects a flex array in > the struct, but it ends up doing the right thing only when the flex > array is in the outermost struct. For nested cases (such as arrays > nested in a union or an inner struct), it ends up taking whatever value > the flex array is declared with, using zero for the standard flex array, > i.e. []. > > Rework subobject size computation to make it more consistent across the > board, honoring -fstrict-flex-arrays. With this change, any array at > the end of the struct will end up causing __bos to use the allocated > value of the outer object, bailing out in the maximum case when it can't > find it. In the minimum case, it will return the subscript value or the > allocated value of the outer object, whichever is larger. I see from the changes in the testing case, there are the following major changes for the existing behavior (can be show with the testing case) ****For non-nested structures: struct A { char a[10]; int b; char c[10]; }; 1. The Minimum size of the reference to the subobject that is a trailing array of a structure is changed from “0” to “sizeof the subobject" > - if (__builtin_object_size (&p->c, 3) != 0) + if (__builtin_object_size (&p->c, 3) != 10) ****For nested structures: struct D { int i; struct D1 { char b; char a[10]; } j; }; 2. The Maximum size of the reference to the subobject that is a trailing array of the inner structure is changed from “sizeof the subobject” to “-1" > - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) > + if (__builtin_object_size (&d->j.a[3], 1) != (size_t) -1) . 3. The Minimum size of the reference to the subobject that is a trailing array of the inner structure is changed from “0” to “sizeof the subobject" - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) > + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) I think that all the above changes are good. My only concern is, for the change of the Minimum size of the reference to the subobject that is a trailing array (the above case 1 and 3), will there be any negtive impact on the existing application that use it? > > gcc/ChangeLog: > > PR tree-optimization/107952 > * tree-object-size.cc (size_from_objects): New function. > (addr_object_size): Call it. Fully rely on > array_ref_flexible_size_p call to determine flex array. > > gcc/testsuite/ChangeLog: > > PR tree-optimization/107952 > * g++.dg/ext/builtin-object-size1.C (test1, test6, test7, > test8): Adjust expected result for object size type 3 and 1. > * g++.dg/ext/builtin-object-size2.C (test1, test6, test7, > test8): Likewise. > * gcc.dg/builtin-object-size-13.c (main): Likewise. > * gcc.dg/builtin-object-size-6.c (test1, test6, test7, test8): > Likewise. > * gcc.dg/builtin-object-size-8.c (main): Likewise. > * gcc.dg/builtin-object-size-flex-common.h: Common code for new > tests. > * gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c: New > test. > * gcc.dg/builtin-object-size-flex-nested-struct-zero.c: New > test. > * gcc.dg/builtin-object-size-flex-nested-struct.c: New test. > * gcc.dg/builtin-object-size-flex-nested-union-nonzero.c: New > test. > * gcc.dg/builtin-object-size-flex-nested-union-zero.c: New test. > * gcc.dg/builtin-object-size-flex-nested-union.c: New test. > * gcc.dg/builtin-object-size-flex-nonzero.c: New test. > * gcc.dg/builtin-object-size-flex-zero.c: New test. > * gcc.dg/builtin-object-size-flex.c: New test. > > Signed-off-by: Siddhesh Poyarekar <siddh...@gotplt.org> > --- > .../g++.dg/ext/builtin-object-size1.C | 10 +- > .../g++.dg/ext/builtin-object-size2.C | 10 +- > gcc/testsuite/gcc.dg/builtin-object-size-13.c | 4 +- > gcc/testsuite/gcc.dg/builtin-object-size-6.c | 10 +- > gcc/testsuite/gcc.dg/builtin-object-size-8.c | 4 +- > .../gcc.dg/builtin-object-size-flex-common.h | 90 +++++++++++ > ...n-object-size-flex-nested-struct-nonzero.c | 6 + > ...ltin-object-size-flex-nested-struct-zero.c | 6 + > .../builtin-object-size-flex-nested-struct.c | 22 +++ > ...in-object-size-flex-nested-union-nonzero.c | 6 + > ...iltin-object-size-flex-nested-union-zero.c | 6 + > .../builtin-object-size-flex-nested-union.c | 28 ++++ > .../gcc.dg/builtin-object-size-flex-nonzero.c | 6 + > .../gcc.dg/builtin-object-size-flex-zero.c | 6 + > .../gcc.dg/builtin-object-size-flex.c | 18 +++ > gcc/tree-object-size.cc | 150 ++++++------------ > 16 files changed, 265 insertions(+), 117 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h > create mode 100644 > gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c > create mode 100644 > gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c > create mode 100644 > gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c > create mode 100644 > gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c > create mode 100644 > gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c > create mode 100644 > gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c > create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-flex.c > > diff --git a/gcc/testsuite/g++.dg/ext/builtin-object-size1.C > b/gcc/testsuite/g++.dg/ext/builtin-object-size1.C > index 165b415683b..5b863637123 100644 > --- a/gcc/testsuite/g++.dg/ext/builtin-object-size1.C > +++ b/gcc/testsuite/g++.dg/ext/builtin-object-size1.C > @@ -103,7 +103,7 @@ test1 (A *p) > FAIL (); > if (__builtin_object_size (&p->b, 3) != sizeof (p->b)) > FAIL (); > - if (__builtin_object_size (&p->c, 3) != 0) > + if (__builtin_object_size (&p->c, 3) != 10) > FAIL (); > c = p->a; > if (__builtin_object_size (c, 3) != sizeof (p->a)) > @@ -118,7 +118,7 @@ test1 (A *p) > if (__builtin_object_size (c, 3) != sizeof (p->b)) > FAIL (); > c = (char *) &p->c; > - if (__builtin_object_size (c, 3) != 0) > + if (__builtin_object_size (c, 3) != 10) > FAIL (); > } > > @@ -344,7 +344,7 @@ test6 (struct D *d) > { > if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1) > FAIL (); > - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) > + if (__builtin_object_size (&d->j.a[3], 1) != (size_t) -1) > FAIL (); > if (__builtin_object_size (&d->j.a[3], 2) != 0) > FAIL (); > @@ -380,7 +380,7 @@ test7 (struct E *e) > FAIL (); > if (__builtin_object_size ((char *) &e->j[0], 2) != 0) > FAIL (); > - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) > + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) > FAIL (); > } > > @@ -404,7 +404,7 @@ test8 (union F *f) > FAIL (); > if (__builtin_object_size (&f->d.c[3], 2) != 0) > FAIL (); > - if (__builtin_object_size (&f->d.c[3], 3) != 0) > + if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3) > FAIL (); > } > > diff --git a/gcc/testsuite/g++.dg/ext/builtin-object-size2.C > b/gcc/testsuite/g++.dg/ext/builtin-object-size2.C > index c5dbd96193c..665dad886d4 100644 > --- a/gcc/testsuite/g++.dg/ext/builtin-object-size2.C > +++ b/gcc/testsuite/g++.dg/ext/builtin-object-size2.C > @@ -106,7 +106,7 @@ test1 (A *p) > FAIL (); > if (__builtin_object_size (&p->b, 3) != sizeof (p->b)) > FAIL (); > - if (__builtin_object_size (&p->c, 3) != 0) > + if (__builtin_object_size (&p->c, 3) != 10) > FAIL (); > c = p->a; > if (__builtin_object_size (c, 3) != sizeof (p->a)) > @@ -121,7 +121,7 @@ test1 (A *p) > if (__builtin_object_size (c, 3) != sizeof (p->b)) > FAIL (); > c = (char *) &p->c; > - if (__builtin_object_size (c, 3) != 0) > + if (__builtin_object_size (c, 3) != 10) > FAIL (); > } > > @@ -347,7 +347,7 @@ test6 (struct D *d) > { > if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1) > FAIL (); > - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) > + if (__builtin_object_size (&d->j.a[3], 1) != (size_t) -1) > FAIL (); > if (__builtin_object_size (&d->j.a[3], 2) != 0) > FAIL (); > @@ -383,7 +383,7 @@ test7 (struct E *e) > FAIL (); > if (__builtin_object_size ((char *) &e->j[0], 2) != 0) > FAIL (); > - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) > + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) > FAIL (); > } > > @@ -407,7 +407,7 @@ test8 (union F *f) > FAIL (); > if (__builtin_object_size (&f->d.c[3], 2) != 0) > FAIL (); > - if (__builtin_object_size (&f->d.c[3], 3) != 0) > + if (__builtin_object_size (&f->d.c[3], 3) != sizeof (f->d.c) - 3) > FAIL (); > } > > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-13.c > b/gcc/testsuite/gcc.dg/builtin-object-size-13.c > index c7d58c941d4..6429dcaf426 100644 > --- a/gcc/testsuite/gcc.dg/builtin-object-size-13.c > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-13.c > @@ -332,9 +332,9 @@ main (void) > o2 = __builtin_offsetof (struct H, h2.e1.c2); > h1 = malloc (s); > h2 = malloc (o2 + 212); > - TA (h1->h2.e1.c2.a2, s - o2, sizeof (h1->h2.e1.c2.a2)); > + TA (h1->h2.e1.c2.a2, s - o2, s - o2); > s = o2 + 212; > - TA (h2->h2.e1.c2.a2, s - o2, sizeof (h2->h2.e1.c2.a2)); > + TA (h2->h2.e1.c2.a2, s - o2, s - o2); > free (h2); > free (h1); > s = sizeof (struct H); > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-6.c > b/gcc/testsuite/gcc.dg/builtin-object-size-6.c > index 4ce05184143..1ae608d456b 100644 > --- a/gcc/testsuite/gcc.dg/builtin-object-size-6.c > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-6.c > @@ -103,7 +103,7 @@ test1 (struct A *p) > FAIL (); > if (__builtin_object_size (&p->b, 3) != sizeof (p->b)) > FAIL (); > - if (__builtin_object_size (&p->c, 3) != 0) > + if (__builtin_object_size (&p->c, 3) != 10) > FAIL (); > c = p->a; > if (__builtin_object_size (c, 3) != sizeof (p->a)) > @@ -118,7 +118,7 @@ test1 (struct A *p) > if (__builtin_object_size (c, 3) != sizeof (p->b)) > FAIL (); > c = (char *) &p->c; > - if (__builtin_object_size (c, 3) != 0) > + if (__builtin_object_size (c, 3) != 10) > FAIL (); > } > > @@ -344,7 +344,7 @@ test6 (struct D *d) > { > if (__builtin_object_size (&d->j.a[3], 0) != (size_t) -1) > FAIL (); > - if (__builtin_object_size (&d->j.a[3], 1) != sizeof (d->j.a) - 3) > + if (__builtin_object_size (&d->j.a[3], 1) != -1) > FAIL (); > if (__builtin_object_size (&d->j.a[3], 2) != 0) > FAIL (); > @@ -380,7 +380,7 @@ test7 (struct E *e) > FAIL (); > if (__builtin_object_size ((char *) &e->j[0], 2) != 0) > FAIL (); > - if (__builtin_object_size ((char *) &e->j[0], 3) != 0) > + if (__builtin_object_size ((char *) &e->j[0], 3) != sizeof (e->j)) > FAIL (); > } > > @@ -404,7 +404,7 @@ test8 (union F *f) > FAIL (); > if (__builtin_object_size (&f->d.c[3], 2) != 0) > FAIL (); > - if (__builtin_object_size (&f->d.c[3], 3) != 0) > + if (__builtin_object_size (&f->d.c[3], 3) != 7) > FAIL (); > } > > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-8.c > b/gcc/testsuite/gcc.dg/builtin-object-size-8.c > index f67902e29f0..184769f1bd8 100644 > --- a/gcc/testsuite/gcc.dg/builtin-object-size-8.c > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-8.c > @@ -186,13 +186,13 @@ main (void) > TS (h1->h1, s); > TS (h1->h2.e1.c1, s - o); > TS (h1->h2.e1.c2.a1, s - o2); > - TA (h1->h2.e1.c2.a2, s - o2, sizeof (h1->h2.e1.c2.a2)); > + TA (h1->h2.e1.c2.a2, s - o2, s - o2); > TF (h1->h2.e2, s - o); > s = o2 + 212; > TS (h2->h1, s); > TS (h2->h2.e1.c1, s - o); > TS (h2->h2.e1.c2.a1, s - o2); > - TA (h2->h2.e1.c2.a2, s - o2, sizeof (h2->h2.e1.c2.a2)); > + TA (h2->h2.e1.c2.a2, s - o2, s - o2); > TF (h2->h2.e2, s - o); > free (h2); > free (h1); > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h > new file mode 100644 > index 00000000000..b8b68da762d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-common.h > @@ -0,0 +1,90 @@ > +#include "builtin-object-size-common.h" > + > +typedef __SIZE_TYPE__ size_t; > + > +void > +__attribute__ ((noinline)) > +test_flexarray_allocate (const char *name) > +{ > + size_t n = sizeof (flex_t); > + > + if (name != (void *) 0) > + n += __builtin_strlen (name) + 1; > + > + flex_t *p = __builtin_malloc (n); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 0) > + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 1) > + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 2) > + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 3) > + != n - sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + __builtin_free (p); > +} > + > +void > +__attribute__ ((noinline)) > +__attribute__ ((access (read_only, 1, 2))) > +test_flexarray_access (flex_t *p, size_t sz) > +{ > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 0) > + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 1) > + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 2) > + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 3) > + != (sz - 1) * sizeof (*p) + SIZEOF_FLEX_ARRAY) > + FAIL (); > +} > + > +void > +__attribute__ ((noinline)) > +test_flexarray_none (flex_t *p) > +{ > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 0) != -1) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 1) != -1) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 2) != 0) > + FAIL (); > + > + if (__builtin_dynamic_object_size (FLEX_ARRAY (p), 3) != SIZEOF_FLEX_ARRAY) > + FAIL (); > +} > + > +int > +main (int argc, char **argv) > +{ > + const char *str = "qwertyuiopasdfgghjklzxcvbnm"; > + > + test_flexarray_allocate (str); > + > + const size_t sz = 1024; > + flex_t *p = __builtin_malloc (sz * sizeof (*p)); > + > + test_flexarray_access (p, sz); > + > + test_flexarray_none (p); > + __builtin_free (p); > + > + DONE (); > +} > diff --git > a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c > new file mode 100644 > index 00000000000..c50cd89a817 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-nonzero.c > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#define SIZEOF_FLEX_ARRAY 4 > + > +#include "builtin-object-size-flex-nested-struct.c" > diff --git > a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c > new file mode 100644 > index 00000000000..554aece0b46 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct-zero.c > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#define SIZEOF_FLEX_ARRAY 0 > + > +#include "builtin-object-size-flex-nested-struct.c" > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c > new file mode 100644 > index 00000000000..1adeac16ac4 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-struct.c > @@ -0,0 +1,22 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#ifndef SIZEOF_FLEX_ARRAY > +# define SIZEOF_FLEX_ARRAY_DECL > +# define SIZEOF_FLEX_ARRAY 0 > +#else > +# define SIZEOF_FLEX_ARRAY_DECL SIZEOF_FLEX_ARRAY > +#endif > + > +typedef struct { > + unsigned pad; > + struct { > + unsigned pad; > + char data[SIZEOF_FLEX_ARRAY_DECL]; > + } s; > +} flex_t; > + > +#define FLEX_ARRAY(p) p->s.data > +#define SIZE_OF_FLEX sizeof (unsigned) + sizeof (unsigned) > + > +#include "builtin-object-size-flex-common.h" > diff --git > a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c > new file mode 100644 > index 00000000000..58e387c8db6 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-nonzero.c > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#define SIZEOF_FLEX_ARRAY 4 > + > +#include "builtin-object-size-flex-nested-union.c" > diff --git > a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c > new file mode 100644 > index 00000000000..ec6429a5a9b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union-zero.c > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#define SIZEOF_FLEX_ARRAY 0 > + > +#include "builtin-object-size-flex-nested-union.c" > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c > new file mode 100644 > index 00000000000..8326131c890 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nested-union.c > @@ -0,0 +1,28 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#ifndef SIZEOF_FLEX_ARRAY > +# define SIZEOF_FLEX_ARRAY_DECL > +# define SIZEOF_FLEX_ARRAY 0 > +#else > +# define SIZEOF_FLEX_ARRAY_DECL SIZEOF_FLEX_ARRAY > +#endif > + > +typedef struct { > + unsigned pad; > + union { > + struct { > + unsigned pad; > + char data[SIZEOF_FLEX_ARRAY_DECL]; > + } s1; > + struct { > + unsigned pad; > + char data[SIZEOF_FLEX_ARRAY_DECL]; > + } s2; > + } u; > +} flex_t; > + > +#define FLEX_ARRAY(p) p->u.s1.data > +#define SIZE_OF_FLEX sizeof (unsigned) + sizeof (unsigned) > + > +#include "builtin-object-size-flex-common.h" > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c > new file mode 100644 > index 00000000000..693d2e98758 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-nonzero.c > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#define SIZEOF_FLEX_ARRAY 4 > + > +#include "builtin-object-size-flex.c" > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c > new file mode 100644 > index 00000000000..f38d0e01d4b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex-zero.c > @@ -0,0 +1,6 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#define SIZEOF_FLEX_ARRAY 0 > + > +#include "builtin-object-size-flex.c" > diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-flex.c > b/gcc/testsuite/gcc.dg/builtin-object-size-flex.c > new file mode 100644 > index 00000000000..34aba8942d6 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/builtin-object-size-flex.c > @@ -0,0 +1,18 @@ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#ifndef SIZEOF_FLEX_ARRAY > +# define SIZEOF_FLEX_ARRAY_DECL > +# define SIZEOF_FLEX_ARRAY 0 > +#else > +# define SIZEOF_FLEX_ARRAY_DECL SIZEOF_FLEX_ARRAY > +#endif > + > +typedef struct { > + unsigned pad; > + char data[SIZEOF_FLEX_ARRAY_DECL]; > +} flex_t; > + > +#define FLEX_ARRAY(p) p->data > + > +#include "builtin-object-size-flex-common.h" > diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc > index d9f25397c71..98ee3c2b527 100644 > --- a/gcc/tree-object-size.cc > +++ b/gcc/tree-object-size.cc > @@ -499,6 +499,19 @@ decl_init_size (tree decl, bool min) > return size; > } > > +/* Return the size of SUBOBJ that is within VAR where the latter has VAR_SIZE > + size. */ > + > +static tree > +size_from_objects (const_tree subobj, const_tree var, tree var_size, > + int object_size_type) > +{ > + tree bytes = compute_object_offset (subobj, var); > + > + return (bytes != error_mark_node ? size_for_offset (var_size, bytes) > + : size_unknown (object_size_type)); > +} > + > /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. > OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. > If unknown, return size_unknown (object_size_type). */ > @@ -589,105 +602,52 @@ addr_object_size (struct object_size_info *osi, > const_tree ptr, > { > var = TREE_OPERAND (ptr, 0); > > + /* Get the immediate containing subobject. Skip over conversions > + because we don't need them. */ > 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) > + && (!handled_component_p (var) > + || TREE_CODE (var) == VIEW_CONVERT_EXPR)) > var = TREE_OPERAND (var, 0); > if (var != pt_var && TREE_CODE (var) == ARRAY_REF) > var = TREE_OPERAND (var, 0); > + > + /* If the subobject size cannot be easily inferred or is smaller than > + the whole size, just use the whole size. */ Should the above comment be: + /* If the subobject size cannot be easily inferred or is larger than + the whole size, just use the whole size. */ > if (! TYPE_SIZE_UNIT (TREE_TYPE (var)) > || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var))) > || (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; thanks. Qing > - else if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) > - { > - tree v = var; > - /* For &X->fld, compute object size if fld isn't a flexible array > - member. */ > - bool is_flexible_array_mem_ref = false; > - while (v && v != pt_var) > - switch (TREE_CODE (v)) > - { > - case ARRAY_REF: > - 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)) > - { > - 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 (v)) != ARRAY_TYPE) > - { > - v = NULL_TREE; > - break; > - } > - is_flexible_array_mem_ref = array_ref_flexible_size_p (v); > - while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) > - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != UNION_TYPE > - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != QUAL_UNION_TYPE) > - break; > - else > - v = TREE_OPERAND (v, 0); > - if (TREE_CODE (v) == COMPONENT_REF > - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - == RECORD_TYPE) > - { > - /* compute object size only if v is not a > - flexible array member. */ > - if (!is_flexible_array_mem_ref) > - { > - v = NULL_TREE; > - break; > - } > - v = TREE_OPERAND (v, 0); > - } > - while (v != pt_var && TREE_CODE (v) == COMPONENT_REF) > - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != UNION_TYPE > - && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0))) > - != QUAL_UNION_TYPE) > - break; > - else > - v = TREE_OPERAND (v, 0); > - if (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; > > + bool is_flexible_array_mem_ref = false; > + /* Find out if this is a flexible array. This will change > + according to -fstrict-flex-arrays. */ > + if (var != pt_var && TREE_CODE (pt_var) == MEM_REF) > + is_flexible_array_mem_ref = array_ref_flexible_size_p (var); > + > + /* We cannot get a maximum estimate for a flex array without the > + whole object size. */ > + if (is_flexible_array_mem_ref && !pt_var_size > + && !(object_size_type & OST_MINIMUM)) > + return false; > + > if (var != pt_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); > + /* For flexible arrays, we prefer the size based on the whole object > + if it is available. */ > + if (is_flexible_array_mem_ref && pt_var_size) > + var_size = size_from_objects (var, pt_var, pt_var_size, > + object_size_type); > + else > + { > + 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; > } > @@ -695,23 +655,17 @@ addr_object_size (struct object_size_info *osi, > const_tree ptr, > return false; > else > var_size = pt_var_size; > - bytes = compute_object_offset (TREE_OPERAND (ptr, 0), var); > - if (bytes != error_mark_node) > + > + bytes = size_from_objects (TREE_OPERAND (ptr, 0), var, var_size, > + object_size_type); > + > + if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF > + && !is_flexible_array_mem_ref) > { > - bytes = size_for_offset (var_size, bytes); > - if (var != pt_var && pt_var_size && TREE_CODE (pt_var) == MEM_REF) > - { > - tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0), > - pt_var); > - if (bytes2 != error_mark_node) > - { > - bytes2 = size_for_offset (pt_var_size, bytes2); > - bytes = size_binop (MIN_EXPR, bytes, bytes2); > - } > - } > + tree bytes2 = size_from_objects (TREE_OPERAND (ptr, 0), pt_var, > + pt_var_size, object_size_type); > + bytes = size_binop (MIN_EXPR, bytes, bytes2); > } > - else > - bytes = size_unknown (object_size_type); > > wholebytes > = object_size_type & OST_SUBOBJECT ? var_size : pt_var_wholesize; > -- > 2.38.1 >