public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Qing Zhao <qing.zhao@oracle.com>
To: Richard Biener <rguenther@suse.de>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	"siddhesh@gotplt.org" <siddhesh@gotplt.org>,
	"keescook@chromium.org" <keescook@chromium.org>
Subject: Re: [PATCH 1/2] Handle component_ref to a structre/union field including flexible array member [PR101832]
Date: Thu, 2 Feb 2023 14:38:05 +0000	[thread overview]
Message-ID: <3B30CFBF-5004-41A4-940D-1F23C010403B@oracle.com> (raw)
In-Reply-To: <nycvar.YFH.7.77.849.2302021354160.6551@jbgna.fhfr.qr>



> On Feb 2, 2023, at 8:54 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> On Thu, 2 Feb 2023, Qing Zhao wrote:
> 
>> 
>> 
>>> On Feb 2, 2023, at 3:07 AM, Richard Biener <rguenther@suse.de> wrote:
>>> 
>>> On Wed, 1 Feb 2023, Qing Zhao wrote:
>>> 
>>>> 
>>>> 
>>>>> On Feb 1, 2023, at 6:41 AM, Richard Biener <rguenther@suse.de> wrote:
>>>>> 
>>>>> On Tue, 31 Jan 2023, Qing Zhao wrote:
>>>>> 
>>>>>> GCC extension accepts the case when a struct with a flexible array member
>>>>>> is embedded into another struct (possibly recursively).
>>>>>> __builtin_object_size should treat such struct as flexible size per
>>>>>> -fstrict-flex-arrays.
>>>>>> 
>>>>>> 	PR tree-optimization/101832
>>>>>> 
>>>>>> gcc/ChangeLog:
>>>>>> 
>>>>>> 	PR tree-optimization/101832
>>>>>> 	* tree-object-size.cc (flexible_size_type_p): New function.
>>>>>> 	(addr_object_size): Handle structure/union type when it has
>>>>>> 	flexible size.
>>>>>> 
>>>>>> gcc/testsuite/ChangeLog:
>>>>>> 
>>>>>> 	PR tree-optimization/101832
>>>>>> 	* gcc.dg/builtin-object-size-pr101832-2.c: New test.
>>>>>> 	* gcc.dg/builtin-object-size-pr101832-3.c: New test.
>>>>>> 	* gcc.dg/builtin-object-size-pr101832-4.c: New test.
>>>>>> 	* gcc.dg/builtin-object-size-pr101832.c: New test.
>>>>>> ---
>>>>>> .../gcc.dg/builtin-object-size-pr101832-2.c   | 135 ++++++++++++++++++
>>>>>> .../gcc.dg/builtin-object-size-pr101832-3.c   | 135 ++++++++++++++++++
>>>>>> .../gcc.dg/builtin-object-size-pr101832-4.c   | 135 ++++++++++++++++++
>>>>>> .../gcc.dg/builtin-object-size-pr101832.c     | 119 +++++++++++++++
>>>>>> gcc/tree-object-size.cc                       | 115 +++++++++++----
>>>>>> 5 files changed, 611 insertions(+), 28 deletions(-)
>>>>>> create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c
>>>>>> create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c
>>>>>> create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c
>>>>>> create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
>>>>>> 
>>>>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c
>>>>>> new file mode 100644
>>>>>> index 00000000000..f38babc5415
>>>>>> --- /dev/null
>>>>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-2.c
>>>>>> @@ -0,0 +1,135 @@
>>>>>> +/* PR 101832: 
>>>>>> +   GCC extension accepts the case when a struct with a flexible array member
>>>>>> +   is embedded into another struct (possibly recursively).
>>>>>> +   __builtin_object_size will treat such struct as flexible size per
>>>>>> +   -fstrict-flex-arrays.  */ 
>>>>>> +/* { dg-do run } */
>>>>>> +/* { dg-options "-O2 -fstrict-flex-arrays=1" } */
>>>>>> +
>>>>>> +#include <stdio.h>
>>>>>> +
>>>>>> +unsigned n_fails = 0;
>>>>>> +
>>>>>> +#define expect(p, _v) do { \
>>>>>> +  size_t v = _v; \
>>>>>> +  if (p == v) \
>>>>>> +    printf("ok:  %s == %zd\n", #p, p); \
>>>>>> +  else {\
>>>>>> +    printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
>>>>>> +    n_fails++; \
>>>>>> +  } \
>>>>>> +} while (0);
>>>>>> +
>>>>>> +struct A {
>>>>>> +  int n;
>>>>>> +  char data[];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B {
>>>>>> +  int m;
>>>>>> +  struct A a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C {
>>>>>> +  int q;
>>>>>> +  struct B b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A0 {
>>>>>> +  int n;
>>>>>> +  char data[0];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B0 {
>>>>>> +  int m;
>>>>>> +  struct A0 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C0 {
>>>>>> +  int q;
>>>>>> +  struct B0 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A1 {
>>>>>> +  int n;
>>>>>> +  char data[1];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B1 {
>>>>>> +  int m;
>>>>>> +  struct A1 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C1 {
>>>>>> +  int q;
>>>>>> +  struct B1 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct An {
>>>>>> +  int n;
>>>>>> +  char data[8];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct Bn {
>>>>>> +  int m;
>>>>>> +  struct An a;
>>>>>> +};
>>>>>> +
>>>>>> +struct Cn {
>>>>>> +  int q;
>>>>>> +  struct Bn b;
>>>>>> +};
>>>>>> +
>>>>>> +volatile void *magic1, *magic2;
>>>>>> +
>>>>>> +int main(int argc, char *argv[])
>>>>>> +{
>>>>>> +    struct B *outer;
>>>>>> +    struct C *outest;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer = (void *)magic1;
>>>>>> +    outest = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B0 *outer0;
>>>>>> +    struct C0 *outest0;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer0 = (void *)magic1;
>>>>>> +    outest0 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer0->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest0->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest0->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B1 *outer1;
>>>>>> +    struct C1 *outest1;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer1 = (void *)magic1;
>>>>>> +    outest1 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer1->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest1->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest1->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct Bn *outern;
>>>>>> +    struct Cn *outestn;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outern = (void *)magic1;
>>>>>> +    outestn = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a));
>>>>>> +    expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b));
>>>>>> +    expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a));
>>>>>> +
>>>>>> +    if (n_fails > 0)
>>>>>> +      __builtin_abort ();
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c
>>>>>> new file mode 100644
>>>>>> index 00000000000..aaae99b8d67
>>>>>> --- /dev/null
>>>>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-3.c
>>>>>> @@ -0,0 +1,135 @@
>>>>>> +/* PR 101832: 
>>>>>> +   GCC extension accepts the case when a struct with a flexible array member
>>>>>> +   is embedded into another struct (possibly recursively).
>>>>>> +   __builtin_object_size will treat such struct as flexible size per
>>>>>> +   -fstrict-flex-arrays.  */
>>>>>> +/* { dg-do run } */
>>>>>> +/* { dg-options "-O2 -fstrict-flex-arrays=2" } */
>>>>>> +
>>>>>> +#include <stdio.h>
>>>>>> +
>>>>>> +unsigned n_fails = 0;
>>>>>> +
>>>>>> +#define expect(p, _v) do { \
>>>>>> +  size_t v = _v; \
>>>>>> +  if (p == v) \
>>>>>> +    printf("ok:  %s == %zd\n", #p, p); \
>>>>>> +  else {\
>>>>>> +    printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
>>>>>> +    n_fails++; \
>>>>>> +  } \
>>>>>> +} while (0);
>>>>>> +
>>>>>> +struct A {
>>>>>> +  int n;
>>>>>> +  char data[];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B {
>>>>>> +  int m;
>>>>>> +  struct A a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C {
>>>>>> +  int q;
>>>>>> +  struct B b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A0 {
>>>>>> +  int n;
>>>>>> +  char data[0];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B0 {
>>>>>> +  int m;
>>>>>> +  struct A0 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C0 {
>>>>>> +  int q;
>>>>>> +  struct B0 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A1 {
>>>>>> +  int n;
>>>>>> +  char data[1];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B1 {
>>>>>> +  int m;
>>>>>> +  struct A1 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C1 {
>>>>>> +  int q;
>>>>>> +  struct B1 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct An {
>>>>>> +  int n;
>>>>>> +  char data[8];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct Bn {
>>>>>> +  int m;
>>>>>> +  struct An a;
>>>>>> +};
>>>>>> +
>>>>>> +struct Cn {
>>>>>> +  int q;
>>>>>> +  struct Bn b;
>>>>>> +};
>>>>>> +
>>>>>> +volatile void *magic1, *magic2;
>>>>>> +
>>>>>> +int main(int argc, char *argv[])
>>>>>> +{
>>>>>> +    struct B *outer;
>>>>>> +    struct C *outest;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer = (void *)magic1;
>>>>>> +    outest = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B0 *outer0;
>>>>>> +    struct C0 *outest0;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer0 = (void *)magic1;
>>>>>> +    outest0 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer0->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest0->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest0->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B1 *outer1;
>>>>>> +    struct C1 *outest1;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer1 = (void *)magic1;
>>>>>> +    outest1 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer1->a, 1), sizeof(outer1->a));
>>>>>> +    expect(__builtin_object_size(&outest1->b, 1), sizeof(outest1->b));
>>>>>> +    expect(__builtin_object_size(&outest1->b.a, 1), sizeof(outest1->b.a));
>>>>>> +
>>>>>> +    struct Bn *outern;
>>>>>> +    struct Cn *outestn;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outern = (void *)magic1;
>>>>>> +    outestn = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a));
>>>>>> +    expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b));
>>>>>> +    expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a));
>>>>>> +
>>>>>> +    if (n_fails > 0)
>>>>>> +      __builtin_abort ();
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c
>>>>>> new file mode 100644
>>>>>> index 00000000000..424264e2acd
>>>>>> --- /dev/null
>>>>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832-4.c
>>>>>> @@ -0,0 +1,135 @@
>>>>>> +/* PR 101832: 
>>>>>> +   GCC extension accepts the case when a struct with a flexible array member
>>>>>> +   is embedded into another struct (possibly recursively).
>>>>>> +   __builtin_object_size will treat such struct as flexible size per
>>>>>> +   -fstrict-flex-arrays.  */
>>>>>> +/* { dg-do run } */
>>>>>> +/* { dg-options "-O2 -fstrict-flex-arrays=3" } */
>>>>>> +
>>>>>> +#include <stdio.h>
>>>>>> +
>>>>>> +unsigned n_fails = 0;
>>>>>> +
>>>>>> +#define expect(p, _v) do { \
>>>>>> +  size_t v = _v; \
>>>>>> +  if (p == v) \
>>>>>> +    printf("ok:  %s == %zd\n", #p, p); \
>>>>>> +  else {\
>>>>>> +    printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
>>>>>> +    n_fails++; \
>>>>>> +  } \
>>>>>> +} while (0);
>>>>>> +
>>>>>> +struct A {
>>>>>> +  int n;
>>>>>> +  char data[];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B {
>>>>>> +  int m;
>>>>>> +  struct A a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C {
>>>>>> +  int q;
>>>>>> +  struct B b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A0 {
>>>>>> +  int n;
>>>>>> +  char data[0];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B0 {
>>>>>> +  int m;
>>>>>> +  struct A0 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C0 {
>>>>>> +  int q;
>>>>>> +  struct B0 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A1 {
>>>>>> +  int n;
>>>>>> +  char data[1];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B1 {
>>>>>> +  int m;
>>>>>> +  struct A1 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C1 {
>>>>>> +  int q;
>>>>>> +  struct B1 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct An {
>>>>>> +  int n;
>>>>>> +  char data[8];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct Bn {
>>>>>> +  int m;
>>>>>> +  struct An a;
>>>>>> +};
>>>>>> +
>>>>>> +struct Cn {
>>>>>> +  int q;
>>>>>> +  struct Bn b;
>>>>>> +};
>>>>>> +
>>>>>> +volatile void *magic1, *magic2;
>>>>>> +
>>>>>> +int main(int argc, char *argv[])
>>>>>> +{
>>>>>> +    struct B *outer;
>>>>>> +    struct C *outest;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer = (void *)magic1;
>>>>>> +    outest = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B0 *outer0;
>>>>>> +    struct C0 *outest0;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer0 = (void *)magic1;
>>>>>> +    outest0 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer0->a, 1), sizeof(outer0->a));
>>>>>> +    expect(__builtin_object_size(&outest0->b, 1), sizeof(outest0->b));
>>>>>> +    expect(__builtin_object_size(&outest0->b.a, 1), sizeof(outest0->b.a));
>>>>>> +
>>>>>> +    struct B1 *outer1;
>>>>>> +    struct C1 *outest1;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outer1 = (void *)magic1;
>>>>>> +    outest1 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer1->a, 1), sizeof(outer1->a));
>>>>>> +    expect(__builtin_object_size(&outest1->b, 1), sizeof(outest1->b));
>>>>>> +    expect(__builtin_object_size(&outest1->b.a, 1), sizeof(outest1->b.a));
>>>>>> +
>>>>>> +    struct Bn *outern;
>>>>>> +    struct Cn *outestn;
>>>>>> +
>>>>>> +    /* Make sure optimization can't find some other object size. */
>>>>>> +    outern = (void *)magic1;
>>>>>> +    outestn = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outern->a, 1), sizeof(outern->a));
>>>>>> +    expect(__builtin_object_size(&outestn->b, 1), sizeof(outestn->b));
>>>>>> +    expect(__builtin_object_size(&outestn->b.a, 1), sizeof(outestn->b.a));
>>>>>> +
>>>>>> +    if (n_fails > 0)
>>>>>> +      __builtin_abort ();
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
>>>>>> new file mode 100644
>>>>>> index 00000000000..8ed6980edf0
>>>>>> --- /dev/null
>>>>>> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
>>>>>> @@ -0,0 +1,119 @@
>>>>>> +/* PR 101832: 
>>>>>> +   GCC extension accepts the case when a struct with a flexible array member
>>>>>> +   is embedded into another struct (possibly recursively).
>>>>>> +   __builtin_object_size will treat such struct as flexible size per
>>>>>> +   -fstrict-flex-arrays.  */
>>>>>> +/* { dg-do run } */
>>>>>> +/* { dg-options "-O2" } */
>>>>>> +
>>>>>> +#include <stdio.h>
>>>>>> +
>>>>>> +unsigned n_fails = 0;
>>>>>> +
>>>>>> +#define expect(p, _v) do { \
>>>>>> +  size_t v = _v; \
>>>>>> +  if (p == v) \
>>>>>> +    printf("ok:  %s == %zd\n", #p, p); \
>>>>>> +  else {\
>>>>>> +    printf("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
>>>>>> +    n_fails++; \
>>>>>> +  } \
>>>>>> +} while (0);
>>>>>> +
>>>>>> +struct A {
>>>>>> +  int n;
>>>>>> +  char data[];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B {
>>>>>> +  int m;
>>>>>> +  struct A a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C {
>>>>>> +  int q;
>>>>>> +  struct B b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A0 {
>>>>>> +  int n;
>>>>>> +  char data[0];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B0 {
>>>>>> +  int m;
>>>>>> +  struct A0 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C0 {
>>>>>> +  int q;
>>>>>> +  struct B0 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct A1 {
>>>>>> +  int n;
>>>>>> +  char data[1];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct B1 {
>>>>>> +  int m;
>>>>>> +  struct A1 a;
>>>>>> +};
>>>>>> +
>>>>>> +struct C1 {
>>>>>> +  int q;
>>>>>> +  struct B1 b;
>>>>>> +};
>>>>>> +
>>>>>> +struct An {
>>>>>> +  int n;
>>>>>> +  char data[8];/* Content following header */
>>>>>> +};
>>>>>> +
>>>>>> +struct Bn {
>>>>>> +  int m;
>>>>>> +  struct An a;
>>>>>> +};
>>>>>> +
>>>>>> +struct Cn {
>>>>>> +  int q;
>>>>>> +  struct Bn b;
>>>>>> +};
>>>>>> +
>>>>>> +volatile void *magic1, *magic2;
>>>>>> +
>>>>>> +int main(int argc, char *argv[])
>>>>>> +{
>>>>>> +    struct B *outer = (void *)magic1;
>>>>>> +    struct C *outest = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B0 *outer0 = (void *)magic1;
>>>>>> +    struct C0 *outest0 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer0->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest0->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest0->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct B1 *outer1 = (void *)magic1;
>>>>>> +    struct C1 *outest1 = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outer1->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest1->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outest1->b.a, 1), -1);
>>>>>> +
>>>>>> +    struct Bn *outern = (void *)magic1;
>>>>>> +    struct Cn *outestn = (void *)magic2;
>>>>>> +
>>>>>> +    expect(__builtin_object_size(&outern->a, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outestn->b, 1), -1);
>>>>>> +    expect(__builtin_object_size(&outestn->b.a, 1), -1);
>>>>>> +
>>>>>> +    if (n_fails > 0)
>>>>>> +      __builtin_abort ();
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
>>>>>> index 9a936a91983..56b78ca2a8c 100644
>>>>>> --- a/gcc/tree-object-size.cc
>>>>>> +++ b/gcc/tree-object-size.cc
>>>>>> @@ -500,6 +500,42 @@ decl_init_size (tree decl, bool min)
>>>>>> return size;
>>>>>> }
>>>>>> 
>>>>>> +/* Determine whether TYPE is a structure with a flexible array member
>>>>>> +   per -fstrict-flex-array or a union containing such a structure
>>>>>> +   (possibly recursively).  */
>>>>>> +static bool
>>>>>> +flexible_size_type_p (const_tree type)
>>>>>> +{
>>>>>> +  tree x = NULL_TREE;
>>>>>> +  tree last = NULL_TREE;
>>>>>> +  switch (TREE_CODE (type))
>>>>>> +    {
>>>>>> +    case RECORD_TYPE:
>>>>>> +      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
>>>>>> +	if (TREE_CODE (x) == FIELD_DECL)
>>>>>> +	  last = x;
>>>>>> +      if (last == NULL_TREE)
>>>>>> +	return false;
>>>>>> +      if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE
>>>>>> +	  && !DECL_NOT_FLEXARRAY (last))
>>>>>> +	return true;
>>>>>> +      else if (TREE_CODE (TREE_TYPE (last)) == RECORD_TYPE
>>>>>> +	       || TREE_CODE (TREE_TYPE (last)) == UNION_TYPE)
>>>>>> +	return flexible_size_type_p (TREE_TYPE (last));
>>>>> 
>>>>> For types with many members this can become quite slow (IIRC we had
>>>>> bugs about similar walks of all fields in types), and this function
>>>>> looks like it's invoked multiple times on the same type per TU.
>>>>> 
>>>>> In principle the property is fixed at the time we lay out a record
>>>>> type, so we might want to compute it at that time and record the
>>>>> result.
>>>> 
>>>> You mean in FE? 
>>> 
>>> Yes, either in the frontend or in the middle-ends layout_type.
>>> 
>>>> Yes, that?s better and cleaner.
>>>> 
>>>> I will add one more field in the TYPE structure to record this information and check this field during middle end.
>>>> 
>>>> I had the same thought in the beginning, but not sure whether adding a 
>>>> new field in IR is necessary or not, other places in middle end might 
>>>> not use this new field.
>>> 
>>> It might be interesting to search for other code walking all fields of
>>> a type to determine this or similar info.
>> 
>> There is one which is defined in tree.cc but only is referenced in c/c-decl.cc:
>> 
>> /* Determine whether TYPE is a structure with a flexible array member,
>>   or a union containing such a structure (possibly recursively).  */
>> flexible_array_type_p
>> 
>> However, this routine is a little different than the one I tried to add:
>> 
>> In the current routine ?flexible_array_type_p?,  only one level nesting in the structure is accepted, multiple nesting in structure is not permitted.
>> 
>> So, my question is:  shall we accept multiple nesting in structure? i.e.
> 
> If we don't reject the testcase with an error, then yes.

Gcc currently accepts the multiple nesting in structure without error.  So, we will continue to accept such extension as long as the flex array is at the end of the structure.
At the same time, for the case the flex array is in the middle of the structure, issue additional warnings now to discourage such usage, and deprecate this case in a future release. 

Does this sound reasonable? 

Qing
> 
>> struct A {
>>  int n;
>>  char data[];/* Content following header */
>> };
>> 
>> struct B {
>>  int m;
>>  struct A a;
>> };
>> 
>> struct C {
>>  int q;
>>  struct B b;
>> };
>> 
>> Qing
>>> 
>>>> thanks.
>>>> 
>>>> Qing
>>>> 
>>>>> 
>>>>>> +      return false;
>>>>>> +    case UNION_TYPE:
>>>>>> +      for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
>>>>>> +	{
>>>>>> +	  if (TREE_CODE (x) == FIELD_DECL
>>>>>> +	      && flexible_array_type_p (TREE_TYPE (x)))
>>>>>> +	    return true;
>>>>>> +	}
>>>>>> +      return false;
>>>>>> +    default:
>>>>>> +      return false;
>>>>>> +  }
>>>>>> +}
>>>>>> +
>>>>>> /* 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).  */
>>>>>> @@ -633,45 +669,68 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
>>>>>> 		    v = NULL_TREE;
>>>>>> 		    break;
>>>>>> 		  case COMPONENT_REF:
>>>>>> -		    if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
>>>>>> +		    /* When the ref is not to an array, a record or a union, it
>>>>>> +		       will not have flexible size, compute the object size
>>>>>> +		       directly.  */
>>>>>> +		    if ((TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
>>>>>> +			&& (TREE_CODE (TREE_TYPE (v)) != RECORD_TYPE)
>>>>>> +			&& (TREE_CODE (TREE_TYPE (v)) != UNION_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)
>>>>>> +		    /* if the record or union does not have flexible size
>>>>>> +		       compute the object size directly.  */
>>>>>> +		    if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE
>>>>>> +			|| TREE_CODE (TREE_TYPE (v)) == UNION_TYPE)
>>>>>> 		      {
>>>>>> -			/* compute object size only if v is not a
>>>>>> -			   flexible array member.  */
>>>>>> -			if (!is_flexible_array_mem_ref)
>>>>>> +			if (!flexible_size_type_p (TREE_TYPE (v)))
>>>>>> 			  {
>>>>>> 			    v = NULL_TREE;
>>>>>> 			    break;
>>>>>> 			  }
>>>>>> -			v = TREE_OPERAND (v, 0);
>>>>>> +			else
>>>>>> +			  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;
>>>>>> +		      {
>>>>>> +			/* Now the ref is to an array type.  */
>>>>>> +			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;
>>>>>> 
>>>>> 
>>>>> -- 
>>>>> Richard Biener <rguenther@suse.de>
>>>>> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
>>>>> Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
>>>>> HRB 36809 (AG Nuernberg)
>>>> 
>>>> 
>>> 
>>> -- 
>>> Richard Biener <rguenther@suse.de>
>>> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
>>> Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
>>> HRB 36809 (AG Nuernberg)
>> 
>> 
> 
> -- 
> Richard Biener <rguenther@suse.de>
> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
> Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
> HRB 36809 (AG Nuernberg)


  reply	other threads:[~2023-02-02 14:38 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-31 14:11 [PATCH 0/2]PR101832: Handle component_ref to a structure/union field including flexible array member for builtin_object_size Qing Zhao
2023-01-31 14:11 ` [PATCH 1/2] Handle component_ref to a structre/union field including flexible array member [PR101832] Qing Zhao
2023-02-01 11:41   ` Richard Biener
2023-02-01 14:19     ` Qing Zhao
2023-02-02  8:07       ` Richard Biener
2023-02-02 13:52         ` Qing Zhao
2023-02-02 13:54           ` Richard Biener
2023-02-02 14:38             ` Qing Zhao [this message]
2023-02-03  7:49               ` Richard Biener
2023-02-03 13:17                 ` Qing Zhao
2023-02-06  9:31                   ` Richard Biener
2023-02-06 14:38                     ` Qing Zhao
2023-02-06 23:14                       ` Joseph Myers
2023-02-07 14:54                         ` Qing Zhao
2023-02-07 19:17                           ` Joseph Myers
2023-02-07 19:57                             ` Qing Zhao
2023-02-07 23:37                               ` Joseph Myers
2023-02-08 15:06                                 ` Qing Zhao
2023-02-08 19:09                                   ` Joseph Myers
2023-02-08 19:20                                     ` Siddhesh Poyarekar
2023-02-08 20:51                                       ` Joseph Myers
2023-02-08 22:53                                       ` Qing Zhao
2023-02-08 23:18                                     ` Qing Zhao
2023-02-09 14:40                                       ` Qing Zhao
2023-02-09 16:46                                         ` Kees Cook
2023-02-10 15:25                                           ` Qing Zhao
2023-02-09 10:35                                   ` Richard Biener
2023-02-09 13:44                                     ` Qing Zhao
2023-02-07 15:28                         ` Siddhesh Poyarekar
2023-02-07 15:38                           ` Qing Zhao
2023-02-01 16:48   ` Siddhesh Poyarekar
2023-02-01 18:20     ` Qing Zhao
2023-01-31 14:11 ` [PATCH 2/2] Documentation Update Qing Zhao
2023-02-01 16:55   ` Siddhesh Poyarekar
2023-02-01 18:24     ` Qing Zhao
2023-02-01 18:57       ` Siddhesh Poyarekar
2023-02-01 19:19         ` Qing Zhao
2023-02-02  8:33         ` Richard Biener
2023-02-02 14:31           ` Qing Zhao
2023-02-02 17:05             ` Kees Cook
2023-02-03 15:56               ` Jeff Law
2023-02-03  4:25           ` Siddhesh Poyarekar
2023-02-03 14:52             ` Qing Zhao
2023-02-03 20:55             ` Joseph Myers
2023-02-03 22:38               ` Qing Zhao
2023-05-25  1:22 [V8][PATCH 0/2]Accept and Handle the case when a structure including a FAM nested in another structure Qing Zhao
2023-05-25  1:22 ` [PATCH 1/2] Handle component_ref to a structre/union field including flexible array member [PR101832] Qing Zhao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3B30CFBF-5004-41A4-940D-1F23C010403B@oracle.com \
    --to=qing.zhao@oracle.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=keescook@chromium.org \
    --cc=rguenther@suse.de \
    --cc=siddhesh@gotplt.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).