aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r--gcc/cp/tree.c137
1 files changed, 134 insertions, 3 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 526077a..ae3dc4c 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -407,6 +407,49 @@ rvalue (tree expr)
}
+/* Hash an ARRAY_TYPE. K is really of type `tree'. */
+
+static hashval_t
+cplus_array_hash (const void* k)
+{
+ hashval_t hash;
+ tree t = (tree) k;
+
+ hash = (htab_hash_pointer (TREE_TYPE (t))
+ ^ htab_hash_pointer (TYPE_DOMAIN (t)));
+
+ return hash;
+}
+
+typedef struct cplus_array_info {
+ tree type;
+ tree domain;
+} cplus_array_info;
+
+/* Compare two ARRAY_TYPEs. K1 is really of type `tree', K2 is really
+ of type `cplus_array_info*'. */
+
+static int
+cplus_array_compare (const void * k1, const void * k2)
+{
+ tree t1 = (tree) k1;
+ const cplus_array_info *t2 = (const cplus_array_info*) k2;
+
+ if (!comptypes (TREE_TYPE (t1), t2->type, COMPARE_STRUCTURAL))
+ return 0;
+
+ if (!TYPE_DOMAIN (t1))
+ return !t2->domain;
+
+ if (!t2->domain)
+ return 0;
+
+ return comptypes (TYPE_DOMAIN (t1), t2->domain, COMPARE_STRUCTURAL);
+}
+
+static GTY ((param_is (union tree_node))) htab_t cplus_array_htab;
+
+
static tree
build_cplus_array_type_1 (tree elt_type, tree index_type)
{
@@ -419,9 +462,47 @@ build_cplus_array_type_1 (tree elt_type, tree index_type)
|| (index_type
&& value_dependent_expression_p (TYPE_MAX_VALUE (index_type))))
{
- t = make_node (ARRAY_TYPE);
- TREE_TYPE (t) = elt_type;
- TYPE_DOMAIN (t) = index_type;
+ void **e;
+ cplus_array_info cai;
+ hashval_t hash;
+
+ if (cplus_array_htab == NULL)
+ cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
+ &cplus_array_compare, NULL);
+
+ hash = (htab_hash_pointer (elt_type)
+ ^ htab_hash_pointer (index_type));
+ cai.type = elt_type;
+ cai.domain = index_type;
+
+ e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash, INSERT);
+ if (*e)
+ /* We have found the type: we're done. */
+ return (tree) *e;
+ else
+ {
+ /* Build a new array type. */
+ t = make_node (ARRAY_TYPE);
+ TREE_TYPE (t) = elt_type;
+ TYPE_DOMAIN (t) = index_type;
+
+ /* Complete building the array type. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
+ || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type)))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (TYPE_CANONICAL (elt_type) != elt_type
+ || (index_type
+ && TYPE_CANONICAL (index_type) != index_type))
+ TYPE_CANONICAL (t)
+ = TYPE_CANONICAL
+ (build_cplus_array_type_1 (TYPE_CANONICAL (elt_type),
+ index_type?
+ TYPE_CANONICAL (index_type)
+ : index_type));
+
+ /* Store it in the hash table. */
+ *e = t;
+ }
}
else
t = build_array_type (elt_type, index_type);
@@ -508,10 +589,59 @@ cp_build_qualified_type_real (tree type,
if (!t)
{
+ tree domain = TYPE_DOMAIN (type);
+
/* Make a new array type, just like the old one, but with the
appropriately qualified element type. */
t = build_variant_type_copy (type);
TREE_TYPE (t) = element_type;
+
+ /* This is a new type. */
+ TYPE_CANONICAL (t) = t;
+
+ if (dependent_type_p (element_type)
+ || (domain
+ && value_dependent_expression_p (TYPE_MAX_VALUE (domain))))
+ {
+ /* The new dependent array type we just created might be
+ equivalent to an existing dependent array type, so we
+ need to keep track of this new array type with a
+ lookup into CPLUS_ARRAY_HTAB. Note that we cannot
+ directly call build_cplus_array_type (that would
+ recurse) or build_cplus_array_type_1 (that would lose
+ attributes). */
+ void **e;
+ cplus_array_info cai;
+ hashval_t hash;
+
+ if (cplus_array_htab == NULL)
+ cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
+ &cplus_array_compare,
+ NULL);
+
+ hash = (htab_hash_pointer (element_type)
+ ^ htab_hash_pointer (domain));
+ cai.type = element_type;
+ cai.domain = domain;
+
+ e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash,
+ INSERT);
+ if (! *e)
+ /* Save this new type. */
+ *e = t;
+ }
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t))
+ || (TYPE_DOMAIN (t)
+ && TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (t))))
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else
+ TYPE_CANONICAL (t)
+ = TYPE_CANONICAL
+ (build_array_type (TYPE_CANONICAL (TREE_TYPE (t)),
+ TYPE_DOMAIN (t)?
+ TYPE_CANONICAL (TYPE_DOMAIN(t))
+ : TYPE_DOMAIN (t)));
}
/* Even if we already had this variant, we update
@@ -1003,6 +1133,7 @@ bind_template_template_parm (tree t, tree newargs)
TYPE_NAME (t2) = decl;
TYPE_STUB_DECL (t2) = decl;
TYPE_SIZE (t2) = 0;
+ SET_TYPE_STRUCTURAL_EQUALITY (t2);
return t2;
}