Sorry, gcc-patches fell out of CC. On Tue, May 31, 2016 at 03:14:43PM +0200, Marek Polacek wrote: > On Thu, May 26, 2016 at 05:16:39PM +0000, Joseph Myers wrote: > > On Thu, 26 May 2016, Marek Polacek wrote: > > > > > The C++ FE has been changed, as a part of c++/50800, in such a way that > > > it no > > > longer considers types differentiating only in TYPE_REF_CAN_ALIAS_ALL > > > incompatible. But the C FE still rejects the following testcase, so this > > > patch > > > makes the C FE follow suit. After all, the may_alias attribute is not > > > considered as "affects_type_identity". This TYPE_REF_CAN_ALIAS_ALL check > > > was > > > introduced back in 2004 (r90078), but since then we've gotten rid of > > > them, only > > > comptypes_internal retained it. I suspect the TYPE_MODE check might go > > > too, > > > but I don't feel like changing that right now. > > > > > > This arised when discussing struct sockaddr vs. may_alias issue in glibc. > > > > > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > > > I'd expect you to need to do something about composite types, to ensure > > that the composite type has TYPE_REF_CAN_ALIAS_ALL set if either of the > > two types does - along with tests in such a case, where the two types are > > in either order, that the composite type produced really is treated as > > may_alias. (The sort of cases I'm thinking of are > > > > typedef int T __attribute__((may_alias)); > > extern T *p; > > extern int *p; > > > > with the declarations in either order, and then making sure that > > type-based aliasing handles references through this pointer properly.) > > I investigated this and it turned out the problem is not in composite_types, > but still in comptypes. For the example above, 'T' and 'int' have different > TYPE_MAIN_VARIANT so they were deemed incompatible. This eventually led me > back to <https://gcc.gnu.org/ml/gcc/2008-01/msg00436.html> and to > <https://gcc.gnu.org/ml/gcc-patches/2008-01/msg01161.html>. The conclusion > there was that we should rely on canonical types to compare INTEGER_TYPE, > FIXED_POINT_TYPE, and REAL_TYPE nodes -- canonical types of 'T' and 'int' are > the same. Since the C++ FE does exactly this, I just used the same code and > commentary. Now, this regressed gcc.dg/pr39464.c, but cc1plus doesn't warn > on that code either, so that might not be a big deal. With this patch cc1 > behaves more like cc1plus so I put the new tests into c-c++-common/. I also > verified that the composite types do have the may_alias property (using > typeof). > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2016-05-31 Marek Polacek <pola...@redhat.com> > > * c-typeck.c (comptypes_internal): Handle comparisons of > INTEGER_TYPE, FIXED_POINT_TYPE, and REAL_TYPE nodes. Don't check > TYPE_REF_CAN_ALIAS_ALL. > > * c-c++-common/attr-may-alias-1.c: New test. > * c-c++-common/attr-may-alias-2.c: New test. > * gcc.dg/pr39464.c: Turn dg-warning into dg-bogus. > > diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c > index 1520c20..a7f28cc 100644 > --- gcc/c/c-typeck.c > +++ gcc/c/c-typeck.c > @@ -1105,10 +1105,28 @@ comptypes_internal (const_tree type1, const_tree > type2, bool *enum_and_int_p, > > switch (TREE_CODE (t1)) > { > + case INTEGER_TYPE: > + case FIXED_POINT_TYPE: > + case REAL_TYPE: > + /* With these nodes, we can't determine type equivalence by > + looking at what is stored in the nodes themselves, because > + two nodes might have different TYPE_MAIN_VARIANTs but still > + represent the same type. For example, wchar_t and int could > + have the same properties (TYPE_PRECISION, TYPE_MIN_VALUE, > + TYPE_MAX_VALUE, etc.), but have different TYPE_MAIN_VARIANTs > + and are distinct types. On the other hand, int and the > + following typedef > + > + typedef int INT __attribute((may_alias)); > + > + have identical properties, different TYPE_MAIN_VARIANTs, but > + represent the same type. The canonical type system keeps > + track of equivalence in this case, so we fall back on it. */ > + return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2); > + > case POINTER_TYPE: > - /* Do not remove mode or aliasing information. */ > - if (TYPE_MODE (t1) != TYPE_MODE (t2) > - || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) > + /* Do not remove mode information. */ > + if (TYPE_MODE (t1) != TYPE_MODE (t2)) > break; > val = (TREE_TYPE (t1) == TREE_TYPE (t2) > ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), > diff --git gcc/testsuite/c-c++-common/attr-may-alias-1.c > gcc/testsuite/c-c++-common/attr-may-alias-1.c > index e69de29..978b9a5 100644 > --- gcc/testsuite/c-c++-common/attr-may-alias-1.c > +++ gcc/testsuite/c-c++-common/attr-may-alias-1.c > @@ -0,0 +1,26 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wall" } */ > + > +typedef int T __attribute__((may_alias)); > + > +extern T *p; > +extern int *p; > + > +extern int *p2; > +extern T *p2; > + > +void fn1 (T); > +void fn1 (int); > + > +void fn2 (int); > +void fn2 (T); > + > +/* Ensure that the composite types have may_alias. */ > +void > +f (long *i) > +{ > + *i = *(__typeof (*p) *) &p; > + asm ("" : : "r" (*p)); > + *i = *(__typeof (*p2) *) &p2; > + asm ("" : : "r" (*p2)); > +} > diff --git gcc/testsuite/c-c++-common/attr-may-alias-2.c > gcc/testsuite/c-c++-common/attr-may-alias-2.c > index e69de29..44ea926 100644 > --- gcc/testsuite/c-c++-common/attr-may-alias-2.c > +++ gcc/testsuite/c-c++-common/attr-may-alias-2.c > @@ -0,0 +1,17 @@ > +/* We used to reject this because types differentiating only in > + TYPE_REF_CAN_ALIAS_ALL were deemed incompatible. */ > +/* { dg-do compile } */ > + > +struct sockaddr; > +struct sockaddr *f (void); > + > +struct __attribute__((may_alias)) sockaddr { int j; }; > +struct sockaddr * > +f (void) > +{ > + return > +#ifndef __cplusplus > + (void *) > +#endif > + 0; > +} > diff --git gcc/testsuite/gcc.dg/pr39464.c gcc/testsuite/gcc.dg/pr39464.c > index cd74540..021c54e 100644 > --- gcc/testsuite/gcc.dg/pr39464.c > +++ gcc/testsuite/gcc.dg/pr39464.c > @@ -8,10 +8,10 @@ typedef unsigned int U __attribute__((may_alias)); > void > foo (void *p) > { > - T *a = (int *) p; /* { dg-warning "initialization from > incompatible pointer type" } */ > - int *b = (T *) p; /* { dg-warning "initialization from > incompatible pointer type" } */ > - U *c = (unsigned int *) p; /* { dg-warning "initialization from > incompatible pointer type" } */ > - unsigned int *d = (U *) p; /* { dg-warning "initialization from > incompatible pointer type" } */ > + T *a = (int *) p; /* { dg-bogus "initialization from incompatible > pointer type" } */ > + int *b = (T *) p; /* { dg-bogus "initialization from incompatible > pointer type" } */ > + U *c = (unsigned int *) p; /* { dg-bogus "initialization from incompatible > pointer type" } */ > + unsigned int *d = (U *) p; /* { dg-bogus "initialization from incompatible > pointer type" } */ > (void) a; > (void) b; > (void) c;
Marek