aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-05-03 10:44:50 +0200
committerRichard Biener <rguenther@suse.de>2024-05-07 13:05:12 +0200
commitb09c2e9560648b0cf993c2ca9ad972c34e6bddfa (patch)
tree99f500d84380cc62ef0546c161e442a44b2c28fc
parent24853cd854eb9b8a5c7b9706ad0908221bf964ce (diff)
downloadgcc-b09c2e9560648b0cf993c2ca9ad972c34e6bddfa.zip
gcc-b09c2e9560648b0cf993c2ca9ad972c34e6bddfa.tar.gz
gcc-b09c2e9560648b0cf993c2ca9ad972c34e6bddfa.tar.bz2
middle-end/114931 - type_hash_canon and structual equality types
TYPE_STRUCTURAL_EQUALITY_P is part of our type system so we have to make sure to include that into the type unification done via type_hash_canon. This requires the flag to be set before querying the hash which is the biggest part of the patch. PR middle-end/114931 gcc/ * tree.cc (type_hash_canon_hash): Hash TYPE_STRUCTURAL_EQUALITY_P. (type_cache_hasher::equal): Compare TYPE_STRUCTURAL_EQUALITY_P. (build_array_type_1): Set TYPE_STRUCTURAL_EQUALITY_P before probing with type_hash_canon. (build_function_type): Likewise. (build_method_type_directly): Likewise. (build_offset_type): Likewise. (build_complex_type): Likewise. * attribs.cc (build_type_attribute_qual_variant): Likewise. gcc/c-family/ * c-common.cc (complete_array_type): Set TYPE_STRUCTURAL_EQUALITY_P before probing with type_hash_canon. gcc/testsuite/ * gcc.dg/pr114931.c: New testcase.
-rw-r--r--gcc/attribs.cc20
-rw-r--r--gcc/c-family/c-common.cc11
-rw-r--r--gcc/testsuite/gcc.dg/pr114931.c10
-rw-r--r--gcc/tree.cc65
4 files changed, 74 insertions, 32 deletions
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index 12ffc5f..3ab0b0f 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -1336,6 +1336,16 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
tree dtype = ntype = build_distinct_type_copy (ttype);
TYPE_ATTRIBUTES (ntype) = attribute;
+ /* If the target-dependent attributes make NTYPE different from
+ its canonical type, we will need to use structural equality
+ checks for this type.
+
+ We shouldn't get here for stripping attributes from a type;
+ the no-attribute type might not need structural comparison. But
+ we can if was discarded from type_hash_table. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
+ || !comp_type_attributes (ntype, ttype))
+ SET_TYPE_STRUCTURAL_EQUALITY (ntype);
hashval_t hash = type_hash_canon_hash (ntype);
ntype = type_hash_canon (hash, ntype);
@@ -1343,16 +1353,6 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
if (ntype != dtype)
/* This variant was already in the hash table, don't mess with
TYPE_CANONICAL. */;
- else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
- || !comp_type_attributes (ntype, ttype))
- /* If the target-dependent attributes make NTYPE different from
- its canonical type, we will need to use structural equality
- checks for this type.
-
- We shouldn't get here for stripping attributes from a type;
- the no-attribute type might not need structural comparison. But
- we can if was discarded from type_hash_table. */
- SET_TYPE_STRUCTURAL_EQUALITY (ntype);
else if (TYPE_CANONICAL (ntype) == ntype)
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 01e3d24..032dcb4 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -7115,6 +7115,13 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
TYPE_TYPELESS_STORAGE (main_type) = TYPE_TYPELESS_STORAGE (type);
layout_type (main_type);
+ /* Set TYPE_STRUCTURAL_EQUALITY_P early. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
+ || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
+ SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+ else
+ TYPE_CANONICAL (main_type) = main_type;
+
/* Make sure we have the canonical MAIN_TYPE. */
hashval_t hashcode = type_hash_canon_hash (main_type);
main_type = type_hash_canon (hashcode, main_type);
@@ -7122,7 +7129,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
/* Fix the canonical type. */
if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
|| TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
- SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+ gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (main_type));
else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
|| (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
!= TYPE_DOMAIN (main_type)))
@@ -7130,8 +7137,6 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
= build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
TYPE_CANONICAL (TYPE_DOMAIN (main_type)),
TYPE_TYPELESS_STORAGE (main_type));
- else
- TYPE_CANONICAL (main_type) = main_type;
if (quals == 0)
type = main_type;
diff --git a/gcc/testsuite/gcc.dg/pr114931.c b/gcc/testsuite/gcc.dg/pr114931.c
new file mode 100644
index 0000000..d690ed7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114931.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+struct Tcl_Obj;
+void(Tcl_FreeInternalRepProc)(struct Tcl_Obj *);
+typedef struct Tcl_Obj {
+} Tcl_Obj;
+struct {
+ void (*tclFreeObj)(Tcl_Obj *);
+} Tcl_InitStubs;
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 7806625..6564b00 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -6012,6 +6012,8 @@ type_hash_canon_hash (tree type)
hstate.add_int (TREE_CODE (type));
+ hstate.add_flag (TYPE_STRUCTURAL_EQUALITY_P (type));
+
if (TREE_TYPE (type))
hstate.add_object (TYPE_HASH (TREE_TYPE (type)));
@@ -6109,6 +6111,10 @@ type_cache_hasher::equal (type_hash *a, type_hash *b)
|| TYPE_MODE (a->type) != TYPE_MODE (b->type)))
return false;
+ if (TYPE_STRUCTURAL_EQUALITY_P (a->type)
+ != TYPE_STRUCTURAL_EQUALITY_P (b->type))
+ return false;
+
switch (TREE_CODE (a->type))
{
case VOID_TYPE:
@@ -7347,6 +7353,14 @@ build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
TYPE_DOMAIN (t) = index_type;
TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type);
TYPE_TYPELESS_STORAGE (t) = typeless_storage;
+
+ /* Set TYPE_STRUCTURAL_EQUALITY_P. */
+ if (set_canonical
+ && (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
+ || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))
+ || in_lto_p))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+
layout_type (t);
if (shared)
@@ -7363,7 +7377,7 @@ build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
|| (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))
|| in_lto_p)
- SET_TYPE_STRUCTURAL_EQUALITY (t);
+ gcc_unreachable ();
else if (TYPE_CANONICAL (elt_type) != elt_type
|| (index_type && TYPE_CANONICAL (index_type) != index_type))
TYPE_CANONICAL (t)
@@ -7510,21 +7524,25 @@ build_function_type (tree value_type, tree arg_types,
TYPE_NO_NAMED_ARGS_STDARG_P (t) = 1;
}
- /* If we already have such a type, use the old one. */
- hashval_t hash = type_hash_canon_hash (t);
- tree probe_type = t;
- t = type_hash_canon (hash, t);
- if (t != probe_type)
- return t;
-
/* Set up the canonical type. */
any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type);
any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
canon_argtypes = maybe_canonicalize_argtypes (arg_types,
&any_structural_p,
&any_noncanonical_p);
+ /* Set TYPE_STRUCTURAL_EQUALITY_P early. */
if (any_structural_p)
SET_TYPE_STRUCTURAL_EQUALITY (t);
+
+ /* If we already have such a type, use the old one. */
+ hashval_t hash = type_hash_canon_hash (t);
+ tree probe_type = t;
+ t = type_hash_canon (hash, t);
+ if (t != probe_type)
+ return t;
+
+ if (any_structural_p)
+ gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
else if (any_noncanonical_p)
TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
canon_argtypes);
@@ -7667,13 +7685,6 @@ build_method_type_directly (tree basetype,
argtypes = tree_cons (NULL_TREE, ptype, argtypes);
TYPE_ARG_TYPES (t) = argtypes;
- /* If we already have such a type, use the old one. */
- hashval_t hash = type_hash_canon_hash (t);
- tree probe_type = t;
- t = type_hash_canon (hash, t);
- if (t != probe_type)
- return t;
-
/* Set up the canonical type. */
any_structural_p
= (TYPE_STRUCTURAL_EQUALITY_P (basetype)
@@ -7684,8 +7695,20 @@ build_method_type_directly (tree basetype,
canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes),
&any_structural_p,
&any_noncanonical_p);
+
+ /* Set TYPE_STRUCTURAL_EQUALITY_P early. */
if (any_structural_p)
SET_TYPE_STRUCTURAL_EQUALITY (t);
+
+ /* If we already have such a type, use the old one. */
+ hashval_t hash = type_hash_canon_hash (t);
+ tree probe_type = t;
+ t = type_hash_canon (hash, t);
+ if (t != probe_type)
+ return t;
+
+ if (any_structural_p)
+ gcc_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
else if (any_noncanonical_p)
TYPE_CANONICAL (t)
= build_method_type_directly (TYPE_CANONICAL (basetype),
@@ -7726,6 +7749,9 @@ build_offset_type (tree basetype, tree type)
TYPE_OFFSET_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
TREE_TYPE (t) = type;
+ if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
+ || TYPE_STRUCTURAL_EQUALITY_P (type))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
/* If we already have such a type, use the old one. */
hashval_t hash = type_hash_canon_hash (t);
@@ -7741,7 +7767,7 @@ build_offset_type (tree basetype, tree type)
{
if (TYPE_STRUCTURAL_EQUALITY_P (basetype)
|| TYPE_STRUCTURAL_EQUALITY_P (type))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
+ gcc_unreachable ();
else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype
|| TYPE_CANONICAL (type) != type)
TYPE_CANONICAL (t)
@@ -7770,6 +7796,8 @@ build_complex_type (tree component_type, bool named)
tree probe = make_node (COMPLEX_TYPE);
TREE_TYPE (probe) = TYPE_MAIN_VARIANT (component_type);
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (probe)))
+ SET_TYPE_STRUCTURAL_EQUALITY (probe);
/* If we already have such a type, use the old one. */
hashval_t hash = type_hash_canon_hash (probe);
@@ -7781,11 +7809,10 @@ build_complex_type (tree component_type, bool named)
out the type. We need to check the canonicalization and
maybe set the name. */
gcc_checking_assert (COMPLETE_TYPE_P (t)
- && !TYPE_NAME (t)
- && TYPE_CANONICAL (t) == t);
+ && !TYPE_NAME (t));
if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t)))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
+ ;
else if (TYPE_CANONICAL (TREE_TYPE (t)) != TREE_TYPE (t))
TYPE_CANONICAL (t)
= build_complex_type (TYPE_CANONICAL (TREE_TYPE (t)), named);