TREE_SET_CODE (*node, ENUMERAL_TYPE);
ENUM_UNDERLYING_TYPE (*node) = orig;
+ TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig);
tree false_value;
if (args)
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);
}
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)
{
{
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)
{
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);
}
}
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);
}
result = get_aka_type (orig_type);
}
+ else if (TREE_CODE (type) == ENUMERAL_TYPE)
+ return type;
else
{
tree canonical = TYPE_CANONICAL (type);
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))
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;
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)
--- /dev/null
+/* { 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();
+}
+
--- /dev/null
+/* { 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();
+}
+
--- /dev/null
+/* { 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();
+}
+
+
--- /dev/null
+/* { 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();
+}
+