diff options
-rw-r--r-- | gcc/c/c-decl.cc | 2 | ||||
-rw-r--r-- | gcc/c/c-objc-common.cc | 5 | ||||
-rw-r--r-- | gcc/c/c-typeck.cc | 37 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/gnu23-tag-alias-8.c | 24 |
4 files changed, 59 insertions, 9 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 6e6606c..9f7d55c 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9749,7 +9749,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, C_TYPE_BEING_DEFINED (t) = 0; /* Set type canonical based on equivalence class. */ - if (flag_isoc23) + if (flag_isoc23 && !C_TYPE_VARIABLE_SIZE (t)) { if (c_struct_htab == NULL) c_struct_htab = hash_table<c_struct_hasher>::create_ggc (61); diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index 283f6a8..738e899 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -420,11 +420,6 @@ c_var_mod_p (tree x, tree fn ATTRIBUTE_UNUSED) alias_set_type c_get_alias_set (tree 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)) - return 0; - return c_common_get_alias_set (t); } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 09b2c265..4893480 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -1167,6 +1167,28 @@ common_type (tree t1, tree t2) return c_common_type (t1, t2); } + + +/* Helper function for comptypes. For two compatible types, return 1 + if they pass consistency checks. In particular we test that + TYPE_CANONICAL is set correctly, i.e. the two types can alias. */ + +static bool +comptypes_verify (tree type1, tree type2) +{ + if (TYPE_CANONICAL (type1) != TYPE_CANONICAL (type2) + && !TYPE_STRUCTURAL_EQUALITY_P (type1) + && !TYPE_STRUCTURAL_EQUALITY_P (type2)) + { + /* FIXME: check other types. */ + if (RECORD_OR_UNION_TYPE_P (type1) + || TREE_CODE (type1) == ENUMERAL_TYPE + || TREE_CODE (type2) == ENUMERAL_TYPE) + return false; + } + return true; +} + struct comptypes_data { bool enum_and_int_p; bool different_types_p; @@ -1188,6 +1210,8 @@ comptypes (tree type1, tree type2) struct comptypes_data data = { }; bool ret = comptypes_internal (type1, type2, &data); + gcc_checking_assert (!ret || comptypes_verify (type1, type2)); + return ret ? (data.warning_needed ? 2 : 1) : 0; } @@ -1201,6 +1225,8 @@ comptypes_same_p (tree type1, tree type2) struct comptypes_data data = { }; bool ret = comptypes_internal (type1, type2, &data); + gcc_checking_assert (!ret || comptypes_verify (type1, type2)); + if (data.different_types_p) return false; @@ -1218,6 +1244,8 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p) bool ret = comptypes_internal (type1, type2, &data); *enum_and_int_p = data.enum_and_int_p; + gcc_checking_assert (!ret || comptypes_verify (type1, type2)); + return ret ? (data.warning_needed ? 2 : 1) : 0; } @@ -1232,6 +1260,8 @@ comptypes_check_different_types (tree type1, tree type2, bool ret = comptypes_internal (type1, type2, &data); *different_types_p = data.different_types_p; + gcc_checking_assert (!ret || comptypes_verify (type1, type2)); + return ret ? (data.warning_needed ? 2 : 1) : 0; } @@ -1274,6 +1304,10 @@ comptypes_equiv_p (tree type1, tree type2) data.equiv = true; bool ret = comptypes_internal (type1, type2, &data); + /* check that different equivance classes are assigned only + to types that are not compatible. */ + gcc_checking_assert (ret || !comptypes (type1, type2)); + return ret; } @@ -1629,9 +1663,6 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2))) return false; - if (data->equiv && (C_TYPE_VARIABLE_SIZE (t1) || C_TYPE_VARIABLE_SIZE (t2))) - return false; - for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2; s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2)) diff --git a/gcc/testsuite/gcc.dg/gnu23-tag-alias-8.c b/gcc/testsuite/gcc.dg/gnu23-tag-alias-8.c new file mode 100644 index 0000000..11f2787 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gnu23-tag-alias-8.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu23 -O2" } */ + +typedef struct E { int a[2]; int b; } *A; + +void* foo(void* a, void *b, void *c, void *d) +{ + *(A**)a = c; + + int N = 2; + typedef struct E { int a[N]; int b; } *B; + *(B**)b = d; + + return *(A**)a; +} + +int main() +{ + A *a, b, c; + if (&c != (A*)foo(&a, &a, &b, &c)) + __builtin_abort(); +} + + |