aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c/c-decl.cc2
-rw-r--r--gcc/c/c-objc-common.cc5
-rw-r--r--gcc/c/c-typeck.cc37
-rw-r--r--gcc/testsuite/gcc.dg/gnu23-tag-alias-8.c24
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();
+}
+
+