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)