diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 1262c82cedb..f0b03d2c8d7 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2016-06-06 Marek Polacek + + * 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. + 2016-06-03 Chung-Lin Tang * c-typeck.c (c_finish_omp_clauses): Mark OpenACC reduction diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 0ff28f2ec28..cee566f8322 100644 --- a/gcc/c/c-typeck.c +++ b/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 a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0940e916b16..1a7e9eef59b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-06-06 Marek Polacek + + * 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. + 2016-06-06 Bernd Edlinger PR c/24414 diff --git a/gcc/testsuite/c-c++-common/attr-may-alias-1.c b/gcc/testsuite/c-c++-common/attr-may-alias-1.c new file mode 100644 index 00000000000..978b9a58faf --- /dev/null +++ b/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 a/gcc/testsuite/c-c++-common/attr-may-alias-2.c b/gcc/testsuite/c-c++-common/attr-may-alias-2.c new file mode 100644 index 00000000000..44ea9265729 --- /dev/null +++ b/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 a/gcc/testsuite/gcc.dg/pr39464.c b/gcc/testsuite/gcc.dg/pr39464.c index cd745406da8..021c54e60b1 100644 --- a/gcc/testsuite/gcc.dg/pr39464.c +++ b/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;