Thanks Joseph, I will sent an updated series tomorrow. 

Richard, maybe you could look at what I wrote below
about my use of TYPE_CANONICAL ?  Does this make sense?


Am Donnerstag, dem 23.11.2023 um 23:47 +0000 schrieb Joseph Myers:
> On Thu, 16 Nov 2023, Martin Uecker wrote:
> 
> > Tell the backend which types are equivalent by setting
> > TYPE_CANONICAL to one struct in the set of equivalent
> > structs. Structs are considered equivalent by ignoring
> > all sizes of arrays nested in types below field level.
> 
> Is TYPE_CANONICAL *only* used for alias analysis?  It's not obvious to me 
> that setting TYPE_CANONICAL to a type that's definitely not equivalent for 
> other purposes is necessarily safe.

My understand is that it is used for aliasing analysis and also
checking of conversions.  TYPE_CANONICAL must be consistent with
the idea the middle-end has about type conversions.  But as long
as we do not give the same TYPE_CANONICAL to types the middle-end
thinks must be incompatible using its own type checking machinery,
it should be safe even for types the C standard thinks must be
incompatible for some reason.

> I also think more rationale is needed for ignoring sizes like this.  Is it 
> intended for e.g. making structs with flexible array members 
> alias-compatible with similar structs with a fixed-size array?

The main reason are pointers to arrays:

struct foo { int (*x)[]; }
struct foo { int (*x)[2]; };
struct foo { int (*x)[1]; };

So at least when putting it in terms of equivalence classes,
one has no choice than making those types equivalent. So
all those would get the same TYPE_CANONICAL. The middle-end 
does not care about the different pointer types (in
useless_type_conversion_p or
gimple_canonical_types_compatible_p).


Martin




> 
> > @@ -1250,6 +1266,9 @@ comptypes_internal (const_tree type1, const_tree 
> > type2,
> >  
> >     if ((d1 == NULL_TREE) != (d2 == NULL_TREE))
> >       data->different_types_p = true;
> > +   /* ignore size mismatches */
> > +   if (data->equiv)
> > +     return 1;
> 
> Should start comment with capital letter, end with '.'.
> 
> > diff --git a/gcc/testsuite/gcc.dg/c23-tag-2.c 
> > b/gcc/testsuite/gcc.dg/c23-tag-2.c
> > index 5dd4a21e9df..e28c2b5eea2 100644
> > --- a/gcc/testsuite/gcc.dg/c23-tag-2.c
> > +++ b/gcc/testsuite/gcc.dg/c23-tag-2.c
> > @@ -1,5 +1,5 @@
> > -/* { dg-do compile { target { ! "*-*-*" } } }
> > - * { dg-options "-std=c23" }
> > +/* { dg-do compile }
> > + * { dg-options "-std=c2x" }
> >   */
> >  
> >  // compatibility of structs in assignment
> > diff --git a/gcc/testsuite/gcc.dg/c23-tag-5.c 
> > b/gcc/testsuite/gcc.dg/c23-tag-5.c
> > index ff40d07aef1..95a04bf9b0e 100644
> > --- a/gcc/testsuite/gcc.dg/c23-tag-5.c
> > +++ b/gcc/testsuite/gcc.dg/c23-tag-5.c
> > @@ -1,5 +1,6 @@
> > -/* { dg-do run { target { ! "*-*-*" } } }
> > - * { dg-options "-std=c23" }
> > +/*
> > + * { dg-do run }
> > + * { dg-options "-std=c2x" }
> 
> These tests should not be changed to use -std=c2x.
> 
> > diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-2.c 
> > b/gcc/testsuite/gcc.dg/c23-tag-alias-2.c
> > new file mode 100644
> > index 00000000000..555c30a8501
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-2.c
> > @@ -0,0 +1,73 @@
> > +/*
> > + * { dg-do run }
> > + * { dg-options "-std=c23 -O2" }
> > + */
> > +
> > +
> > +struct foo { int x; };
> > +
> > +int test_foo1(struct foo* a, void* b)
> > +{
> > +   a->x = 1;
> > +
> > +   struct foo { int x; int y; }* p = b;
> > +   p->x = 2;
> > +
> > +   return a->x;
> > +}
> 
> > +int main()
> > +{
> > +   struct foo y;
> > +
> > +   if (1 != test_foo1(&y, &y))
> > +           __builtin_abort();
> 
> This test appears to be testing various invalid cases - testing that the 
> compiler does not consider aliasing to occur in those cases (even though 
> in fact there is aliasing).
> 
> If that's the intent of this test, it definitely needs commenting.  The 
> test would also need to (be a gnu23-* test and) use appropriate attributes 
> to disable interprocedural analysis, since it would be entirely valid for 
> the compiler in this test to inline test_foo1, see that p->x in fact 
> points to the same location as a->x despite the incompatible types, and 
> have the function return 2.
> 
> The same applies to c23-tag-alias-4.c and c23-tag-alias-5.c.
> 
> > diff --git a/gcc/testsuite/gcc.dg/c23-tag-alias-5.c 
> > b/gcc/testsuite/gcc.dg/c23-tag-alias-5.c
> > new file mode 100644
> > index 00000000000..4e956720143
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c23-tag-alias-5.c
> > @@ -0,0 +1,30 @@
> > +/* { dg-do run }
> > + * { dg-options "-std=c23 -O2" }
> > + */
> > +
> > +// not sure this is wise, but this was already like thi sbefore
> 
> "this before"
> 

Reply via email to