On Tue, 10 Dec 2024, Martin Uecker wrote:

> 
> The second part now only contains the changes for array size. 
> 
> I added back a special case for this instead of having the
> 'ignore_size' flag (which I would nevertheless assume might be
> needed in the future when matching pointer types).

I see.  I think the current way is easier to follow.

> In this version, I added an exception to the special case to ignore
> the case were both are zero-sized arrays, because this seems to be
> the only case were the new code would otherwise be stricter than the
> old code.
> 
> I also replaced/fixed one test where I accidentally included a similar 
> test for another closely related bug involving VLA types.
> 
> Bootstrapped and regression tested on x86_64.

OK.

Thanks,
Richard.

> 
> For checking or computing TYPE_CANONICAL, ignore the array size when it is
> the last element of a structure or union.  To not get errors because of
> an inconsistent number of members, zero-sized arrays which are the last
> element are not ignored anymore when checking the fields of a struct.
> 
>       PR c/113688
>       PR c/114014
>       PR c/114713
>       PR c/117724
> 
> gcc/ChangeLog:
>       * tree.cc (gimple_canonical_types_compatible_p): Add exception.
> 
> gcc/lto/ChangeLog:
>       * lto-common.cc (hash_canonical_type): Add exception.
> 
> gcc/testsuite/ChangeLog:
>       * gcc.dg/pr113688.c: New test.
>       * gcc.dg/pr114014.c: New test.
>       * gcc.dg/pr114713.c: New test.
>       * gcc.dg/pr117724.c: New test.
> ---
>  gcc/lto/lto-common.cc           |  6 +++++-
>  gcc/testsuite/gcc.dg/pr113688.c |  8 +++++++
>  gcc/testsuite/gcc.dg/pr114014.c | 14 ++++++++++++
>  gcc/testsuite/gcc.dg/pr114713.c | 35 ++++++++++++++++++++++++++++++
>  gcc/testsuite/gcc.dg/pr117724.c | 16 ++++++++++++++
>  gcc/tree.cc                     | 38 ++++++++++++++++++++++++++-------
>  6 files changed, 108 insertions(+), 9 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/pr113688.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr114014.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr114713.c
>  create mode 100644 gcc/testsuite/gcc.dg/pr117724.c
> 
> diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc
> index 94050209912..f65a9d1c7b6 100644
> --- a/gcc/lto/lto-common.cc
> +++ b/gcc/lto/lto-common.cc
> @@ -333,7 +333,11 @@ hash_canonical_type (tree type)
>           && (! DECL_SIZE (f)
>               || ! integer_zerop (DECL_SIZE (f))))
>         {
> -         iterative_hash_canonical_type (TREE_TYPE (f), hstate);
> +         tree t = TREE_TYPE (f);
> +         if (!TREE_CHAIN (f)
> +             && TREE_CODE (t) == ARRAY_TYPE)
> +           t = TREE_TYPE  (t);
> +         iterative_hash_canonical_type (t, hstate);
>           nf++;
>         }
>  
> diff --git a/gcc/testsuite/gcc.dg/pr113688.c b/gcc/testsuite/gcc.dg/pr113688.c
> new file mode 100644
> index 00000000000..8dee8c86f1b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr113688.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-g" } */
> +
> +struct S{int x,y[1];}*a;
> +int main(void){
> +     struct S{int x,y[];};
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr114014.c b/gcc/testsuite/gcc.dg/pr114014.c
> new file mode 100644
> index 00000000000..1531ffab1b7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr114014.c
> @@ -0,0 +1,14 @@
> +/* PR c/114014
> + * { dg-do compile }
> + * { dg-options "-std=gnu23 -g" } */
> +
> +struct r {
> +  int a;
> +  char b[];
> +};
> +struct r {
> +  int a;
> +  char b[0];
> +};
> +
> +
> diff --git a/gcc/testsuite/gcc.dg/pr114713.c b/gcc/testsuite/gcc.dg/pr114713.c
> new file mode 100644
> index 00000000000..1f0ad39c433
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr114713.c
> @@ -0,0 +1,35 @@
> +/* { dg-do run } */
> +/* { dg-require-effective-target lto } */
> +/* { dg-options "-flto -O2" } */
> +
> +struct foo { int x; char a[]; };
> +
> +void test_bar(void* b);
> +
> +__attribute__((noinline))
> +int test_foo(struct foo* a, void* b)
> +{
> +        a->x = 1;
> +        test_bar(b);
> +        return a->x;
> +}
> +
> +int main()
> +{
> +        struct foo y;
> +
> +        if (2 != test_foo(&y, &y))
> +                __builtin_abort();
> +
> +        return 0;
> +}
> +
> +// TU2
> +struct foo { int x; char a[0]; };
> +
> +void test_bar(void* b)
> +{
> +        struct foo *p = b;
> +        p->x = 2;
> +}
> +
> diff --git a/gcc/testsuite/gcc.dg/pr117724.c b/gcc/testsuite/gcc.dg/pr117724.c
> new file mode 100644
> index 00000000000..d631daeb644
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr117724.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-g" } */
> +
> +struct {
> +  unsigned long len;
> +  unsigned long size;
> +  char data[];
> +};                   /* { dg-warning "unnamed struct" } */
> +struct {
> +  struct {
> +    unsigned long len;
> +    unsigned long size;
> +    char data[6];
> +  };
> +};                   /* { dg-warning "unnamed struct" } */
> +
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index 1391af6bd4c..9803d16805c 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -13838,7 +13838,6 @@ type_with_interoperable_signedness (const_tree type)
>     that have TYPE_CANONICAL defined and assume them equivalent.  This is 
> useful
>     only for LTO because only in these cases TYPE_CANONICAL equivalence
>     correspond to one defined by gimple_canonical_types_compatible_p.  */
> -
>  bool
>  gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
>                                    bool trust_type_canonical)
> @@ -13969,7 +13968,7 @@ gimple_canonical_types_compatible_p (const_tree t1, 
> const_tree t2,
>      {
>      case ARRAY_TYPE:
>        /* Array types are the same if the element types are the same and
> -      the number of elements are the same.  */
> +      minimum and maximum index are the same.  */
>        if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE 
> (t2),
>                                               trust_type_canonical)
>         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
> @@ -14063,23 +14062,46 @@ gimple_canonical_types_compatible_p (const_tree t1, 
> const_tree t2,
>            f1 || f2;
>            f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
>         {
> -         /* Skip non-fields and zero-sized fields.  */
> +         /* Skip non-fields and zero-sized fields, except zero-sized
> +            arrays at the end.  */
>           while (f1 && (TREE_CODE (f1) != FIELD_DECL
>                         || (DECL_SIZE (f1)
> -                           && integer_zerop (DECL_SIZE (f1)))))
> +                           && integer_zerop (DECL_SIZE (f1))
> +                           && (TREE_CHAIN (f1)
> +                               || TREE_CODE (TREE_TYPE (f1))
> +                                  != ARRAY_TYPE))))
>             f1 = TREE_CHAIN (f1);
>           while (f2 && (TREE_CODE (f2) != FIELD_DECL
>                         || (DECL_SIZE (f2)
> -                           && integer_zerop (DECL_SIZE (f2)))))
> +                           && integer_zerop (DECL_SIZE (f2))
> +                           && (TREE_CHAIN (f2)
> +                               || TREE_CODE (TREE_TYPE (f2))
> +                                  != ARRAY_TYPE))))
>             f2 = TREE_CHAIN (f2);
>           if (!f1 || !f2)
>             break;
> -         /* The fields must have the same name, offset and type.  */
> +
> +         tree t1 = TREE_TYPE (f1);
> +         tree t2 = TREE_TYPE (f2);
> +
> +         /* If the last element are arrays, we only compare the element
> +            types.  */
> +         if (TREE_CHAIN (f1) == NULL_TREE && TREE_CODE (t1) == ARRAY_TYPE
> +             && TREE_CHAIN (f2) == NULL_TREE && TREE_CODE (t2) == ARRAY_TYPE)
> +           {
> +             /* If both arrays have zero size, this is a match.  */
> +             if (DECL_SIZE (f1) && integer_zerop (DECL_SIZE (f1))
> +                 && DECL_SIZE (f2) && integer_zerop (DECL_SIZE (f2)))
> +               return true;
> +
> +             t1 = TREE_TYPE (t1);
> +             t2 = TREE_TYPE (t2);
> +           }
> +
>           if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
>               || !gimple_compare_field_offset (f1, f2)
>               || !gimple_canonical_types_compatible_p
> -                   (TREE_TYPE (f1), TREE_TYPE (f2),
> -                    trust_type_canonical))
> +                   (t1, t2, trust_type_canonical))
>             return false;
>         }
>  
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to