diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 605469dd7dd..e3833ed5f20 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -1074,6 +1074,7 @@ handle_hardbool_attribute (tree *node, tree name, tree args, TREE_SET_CODE (*node, ENUMERAL_TYPE); ENUM_UNDERLYING_TYPE (*node) = orig; + TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig); tree false_value; if (args) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index b691b91b3db..6e6606c9570 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -5051,7 +5051,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) if (t == NULL_TREE) { t = make_node (code); - if (flag_isoc23 && code != ENUMERAL_TYPE) + if (flag_isoc23 || code == ENUMERAL_TYPE) SET_TYPE_STRUCTURAL_EQUALITY (t); pushtag (input_location, name, t); } @@ -8828,7 +8828,7 @@ parser_xref_tag (location_t loc, enum tree_code code, tree name, the forward-reference will be altered into a real type. */ ref = make_node (code); - if (flag_isoc23 && code != ENUMERAL_TYPE) + if (flag_isoc23 || code == ENUMERAL_TYPE) SET_TYPE_STRUCTURAL_EQUALITY (ref); if (code == ENUMERAL_TYPE) { @@ -9919,6 +9919,7 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name, { enumtype = make_node (ENUMERAL_TYPE); TYPE_SIZE (enumtype) = NULL_TREE; + SET_TYPE_STRUCTURAL_EQUALITY (enumtype); pushtag (loc, name, enumtype); if (fixed_underlying_type != NULL_TREE) { @@ -9935,6 +9936,8 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name, TYPE_SIZE (enumtype) = NULL_TREE; TYPE_PRECISION (enumtype) = TYPE_PRECISION (fixed_underlying_type); ENUM_UNDERLYING_TYPE (enumtype) = fixed_underlying_type; + TYPE_CANONICAL (enumtype) = TYPE_CANONICAL (fixed_underlying_type); + c_update_type_canonical (enumtype); layout_type (enumtype); } } @@ -10094,6 +10097,10 @@ finish_enum (tree enumtype, tree values, tree attributes) ENUM_UNDERLYING_TYPE (enumtype) = c_common_type_for_size (TYPE_PRECISION (tem), TYPE_UNSIGNED (tem)); + TYPE_CANONICAL (enumtype) = + TYPE_CANONICAL (ENUM_UNDERLYING_TYPE (enumtype)); + c_update_type_canonical (enumtype); + layout_type (enumtype); } diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index 42a62c84fe7..283f6a8ae26 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -130,6 +130,8 @@ get_aka_type (tree type) result = get_aka_type (orig_type); } + else if (TREE_CODE (type) == ENUMERAL_TYPE) + return type; else { tree canonical = TYPE_CANONICAL (type); @@ -418,11 +420,6 @@ c_var_mod_p (tree x, tree fn ATTRIBUTE_UNUSED) alias_set_type c_get_alias_set (tree t) { - /* Allow aliasing between enumeral types and the underlying - integer type. This is required since those are compatible types. */ - if (TREE_CODE (t) == ENUMERAL_TYPE) - return get_alias_set (ENUM_UNDERLYING_TYPE (t)); - /* Structs with variable size can alias different incompatible structs. Let them alias anything. */ if (RECORD_OR_UNION_TYPE_P (t) && C_TYPE_VARIABLE_SIZE (t)) diff --git a/gcc/godump.cc b/gcc/godump.cc index 66e73ade7df..6784bd70e37 100644 --- a/gcc/godump.cc +++ b/gcc/godump.cc @@ -1118,10 +1118,8 @@ go_output_typedef (class godump_container *container, tree decl) separately. */ if (TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE && TYPE_SIZE (TREE_TYPE (decl)) != 0 - && !container->decls_seen.contains (TREE_TYPE (decl)) - && (TYPE_CANONICAL (TREE_TYPE (decl)) == NULL_TREE - || !container->decls_seen.contains - (TYPE_CANONICAL (TREE_TYPE (decl))))) + && !container->decls_seen.contains + (TYPE_MAIN_VARIANT (TREE_TYPE (decl)))) { tree element; @@ -1163,9 +1161,7 @@ go_output_typedef (class godump_container *container, tree decl) mhval->value = xstrdup (buf); *slot = mhval; } - container->decls_seen.add (TREE_TYPE (decl)); - if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE) - container->decls_seen.add (TYPE_CANONICAL (TREE_TYPE (decl))); + container->decls_seen.add (TYPE_MAIN_VARIANT (TREE_TYPE (decl))); } if (DECL_NAME (decl) != NULL_TREE) diff --git a/gcc/testsuite/gcc.dg/enum-alias-1.c b/gcc/testsuite/gcc.dg/enum-alias-1.c new file mode 100644 index 00000000000..8fa30eb7897 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-1.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +enum E { E1 = -1, E2 = 0, E3 = 1 }; + +typedef int A; +typedef enum E B; + +_Static_assert(_Generic((A){ 0 }, B: 1), ""); + +void* foo(void* a, void *b, A *c, B *d) +{ + *(A**)a = c; + *(B**)b = d; + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + diff --git a/gcc/testsuite/gcc.dg/enum-alias-2.c b/gcc/testsuite/gcc.dg/enum-alias-2.c new file mode 100644 index 00000000000..7ca3f3b2db8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-2.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +typedef int A; + +void* foo(void* a, void *b, void *c, void *d) +{ + *(A**)a = c; + + { + typedef enum E B; + enum E { E1 = -1, E2 = 0, E3 = 1 }; + *(B**)b = d; + } + + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + diff --git a/gcc/testsuite/gcc.dg/enum-alias-3.c b/gcc/testsuite/gcc.dg/enum-alias-3.c new file mode 100644 index 00000000000..36a4f02a455 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-3.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -flto" } */ + +typedef int *A; + +void* foo(void* a, void *b, void *c, void *d) +{ + *(A**)a = c; + + typedef enum E *B; + enum E { E1 = -1, E2 = 0, E3 = 1 }; + { + *(B**)b = d; + } + + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + + diff --git a/gcc/testsuite/gcc.dg/enum-alias-4.c b/gcc/testsuite/gcc.dg/enum-alias-4.c new file mode 100644 index 00000000000..b78d0451e3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-alias-4.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +typedef int A; +typedef int __attribute__ (( hardbool(0, 1) )) B; + +_Static_assert(_Generic((A*){ 0 }, B*: 1), ""); + +void* foo(void* a, void *b, A *c, B *d) +{ + *(A**)a = c; + *(B**)b = d; + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} +