aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2007-01-02 14:23:26 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2007-01-02 14:23:26 +0000
commit06d40de8bb03594e0f0eb7d0636f8ca84ce7d86d (patch)
treec7764f44cdfd0ac83984115b7e6b9f215d169dc5 /gcc/cp/tree.c
parenteca0d5e8cef314a820425453b74f7bc4bb26100a (diff)
downloadgcc-06d40de8bb03594e0f0eb7d0636f8ca84ce7d86d.zip
gcc-06d40de8bb03594e0f0eb7d0636f8ca84ce7d86d.tar.gz
gcc-06d40de8bb03594e0f0eb7d0636f8ca84ce7d86d.tar.bz2
c-common.c (c_common_nodes_and_builtins): Since variants of void_type_node get built before it is given a name...
2007-01-02 Douglas Gregor <doug.gregor@gmail.com> * c-common.c(c_common_nodes_and_builtins): Since variants of void_type_node get built before it is given a name, we need to give those variants the name, too. (complete_array_type): We need to work with the canonical main type of the array, from which we will build the qualified version. * params.def (PARAM_VERIFY_CANONICAL_TYPES): New. * print-tree.c (print_node): Display canonical type information for each type. * stor-layout.c (layout_type): When we don't know the alignment of a type for which we're building an array, we end up guessing wrong, so make the type require structural equality. * tree.c (make_node_stat): When we build a new type, it is its own canonical type. (build_type_attribute_qual_variant): When building an attribute variant, its canonical type is the non-attribute variant. However, if the attributes are target-dependent and they differ, we need to use structural equality checks for this type. (build_qualified_type): A qualified type is not equivalent to its unqualified variant; set the canonical type appropriately. (build_distinct_type_copy): When building a distinct type from another type, the new type is its own canonical type. (build_variant_type_copy): When building a new type variant, we assume that it is equivalent to the original type. (build_pointer_type_for_mode): When building a pointer type, also build a canonical type pointer. (build_reference_type_for_mode): When building a reference type, also build a canonical type reference. (build_index_type): When we can't hash an index type (e.g., because its maximum value is negative), the index type requires structural equality tests. (build_array_type): Build the canonical form of an array type. (build_function_type): Function types require structural equality, because they contain default arguments, attributes, etc. (build_method_type_directly): Ditto for method types. (build_offset_type): Build the canonical offset type. (build_complex_type): Build the canonical vector type. (make_vector_type): Build the canonical vector type. * tree.h (TYPE_CANONICAL): New. (TYPE_STRUCTURAL_EQUALITY_P): New. (SET_TYPE_STRUCTURAL_EQUALITY): New. (struct tree_type): Added "canonical" field. * params.h (VERIFY_CANONICAL_TYPES): New. * doc/c-tree.texi (TYPE_CANONICAL): Document. (TYPE_STRUCTURAL_EQUALITY_P): Document. (SET_TYPE_STRUCTURAL_EQUALITY): Document. * doc/invoke.texi (verify-canonical-types): Document --param parameter for verifying canonical types. 2007-01-02 Douglas Gregor <doug.gregor@gmail.com> * typeck.c (structural_comptypes): Renamed from "comptypes". (comptypes): Use canonical type information to perform fast type comparison. When VERIFY_CANONICAL_TYPES, verify that the canonical type comparison returns the same results as we would see from the current, structural check. Support COMPARE_STRUCTURAL when we need structural checks. * decl.c (typename_compare): Fix comment. (build_typename_type): TYPENAME_TYPE nodes require structural equality checks, because they resolve different based on the current class type. (make_unbound_class_template): UNBOUND_CLASS_TEMPLATE nodes require structural equality checks (for now). (build_ptrmemfunc_type): Build the canonical pointer to member function type. (compute_array_index_type): Whenever we build a new index type to represent the size of an array in a template, we need to mark this index type as requiring structural equality. This goes for arrays with value-dependent sizes with the current ABI, or all arrays with ABI-1. * tree.c (cplus_array_hash): New. (struct cplus_array_info): New. (cplus_array_compare): New. (cplus_array_htab): New. (build_cplus_array_type_1): Use a hash table to cache the array types we build. Build the canonical array type for each array type. (cp_build_qualified_type_real): When building a cv-qualified array type, use the hash table of array types and build canonical array types as necessary. (bind_template_template_parm): BOUND_TEMPLATE_TEMPLATE_PARM nodes use structural equality (for now). * cp-tree.h (COMPARE_STRUCTURAL): New. * pt.c (canonical_template_parms): New. (canonical_type_parameter): New. (process_template_parm): Find the canonical type parameter. (lookup_template_class): When we have named the primary template type, set the canonical type for our template class to the primary template type. If any of the template arguments need structural equality checks, the template class needs structural equality checks. (tsubst): When reducing the level of a template template parameter, we require structural equality tests for the resulting parameter because its template parameters have not had their types canonicalized. When reducing a template type parameter, find the canonical reduced type parameter. (any_template_arguments_need_structural_equality_p): New. 2007-01-02 Douglas Gregor <doug.gregor@gmail.com> * objc-act.c (objc_build_volatilized_type): Keep track of canonical types. (objc_get_protocol_qualified_type): Ditto. From-SVN: r120341
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;
}