aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/pt.cc101
-rw-r--r--gcc/cp/tree.cc6
-rw-r--r--gcc/cp/typeck.cc2
4 files changed, 63 insertions, 47 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b2df6fc..ba986e8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6647,6 +6647,7 @@ extern bool make_safe_copy_elision (tree, tree);
extern bool cp_handle_deprecated_or_unavailable (tree, tsubst_flags_t = tf_warning_or_error);
extern void cp_warn_deprecated_use_scopes (tree);
extern tree get_function_version_dispatcher (tree);
+extern bool any_template_arguments_need_structural_equality_p (tree);
/* in class.cc */
extern tree build_vfield_ref (tree, tree);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 5037627..b45a299 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -203,7 +203,6 @@ static tree copy_default_args_to_explicit_spec_1 (tree, tree);
static void copy_default_args_to_explicit_spec (tree);
static bool invalid_nontype_parm_type_p (tree, tsubst_flags_t);
static bool dependent_template_arg_p (tree);
-static bool any_template_arguments_need_structural_equality_p (tree);
static bool dependent_type_p_r (tree);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t);
@@ -4526,6 +4525,27 @@ build_template_parm_index (int index,
return t;
}
+struct ctp_hasher : ggc_ptr_hash<tree_node>
+{
+ static hashval_t hash (tree t)
+ {
+ tree_code code = TREE_CODE (t);
+ hashval_t val = iterative_hash_object (code, 0);
+ val = iterative_hash_object (TEMPLATE_TYPE_LEVEL (t), val);
+ val = iterative_hash_object (TEMPLATE_TYPE_IDX (t), val);
+ if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
+ val = iterative_hash_template_arg (TYPE_TI_ARGS (t), val);
+ return val;
+ }
+
+ static bool equal (tree t, tree u)
+ {
+ return comptypes (t, u, COMPARE_STRUCTURAL);
+ }
+};
+
+static GTY (()) hash_table<ctp_hasher> *ctp_table;
+
/* Find the canonical type parameter for the given template type
parameter. Returns the canonical type parameter, which may be TYPE
if no such parameter existed. */
@@ -4533,21 +4553,13 @@ build_template_parm_index (int index,
tree
canonical_type_parameter (tree type)
{
- int idx = TEMPLATE_TYPE_IDX (type);
+ if (ctp_table == NULL)
+ ctp_table = hash_table<ctp_hasher>::create_ggc (61);
- gcc_assert (TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM);
-
- if (vec_safe_length (canonical_template_parms) <= (unsigned) idx)
- vec_safe_grow_cleared (canonical_template_parms, idx + 1, true);
-
- for (tree list = (*canonical_template_parms)[idx];
- list; list = TREE_CHAIN (list))
- if (comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
- return TREE_VALUE (list);
-
- (*canonical_template_parms)[idx]
- = tree_cons (NULL_TREE, type, (*canonical_template_parms)[idx]);
- return type;
+ tree& slot = *ctp_table->find_slot (type, INSERT);
+ if (slot == NULL_TREE)
+ slot = type;
+ return slot;
}
/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
@@ -4720,10 +4732,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
current_template_depth,
decl, TREE_TYPE (parm));
TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
- if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else
- TYPE_CANONICAL (t) = canonical_type_parameter (t);
+ TYPE_CANONICAL (t) = canonical_type_parameter (t);
}
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
@@ -10131,9 +10140,6 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
appropriately. */
TYPE_CANONICAL (t) = template_type;
else if (any_template_arguments_need_structural_equality_p (arglist))
- /* Some of the template arguments require structural
- equality testing, so this template class requires
- structural equality testing. */
SET_TYPE_STRUCTURAL_EQUALITY (t);
}
else
@@ -15908,20 +15914,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
only instantiated during satisfaction. */
PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r) = ci;
- if (TREE_CODE (r) == TEMPLATE_TEMPLATE_PARM)
- /* We have reduced the level of the template
- template parameter, but not the levels of its
- template parameters, so canonical_type_parameter
- will not be able to find the canonical template
- template parameter for this level. Thus, we
- require structural equality checking to compare
- TEMPLATE_TEMPLATE_PARMs. */
- SET_TYPE_STRUCTURAL_EQUALITY (r);
- else if (TYPE_STRUCTURAL_EQUALITY_P (t))
- SET_TYPE_STRUCTURAL_EQUALITY (r);
- else
- TYPE_CANONICAL (r) = canonical_type_parameter (r);
-
if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
tree tinfo = TYPE_TEMPLATE_INFO (t);
@@ -15939,6 +15931,11 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (r)
= build_template_info (tmpl, argvec);
}
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (t))
+ SET_TYPE_STRUCTURAL_EQUALITY (r);
+ else
+ TYPE_CANONICAL (r) = canonical_type_parameter (r);
}
break;
@@ -28227,8 +28224,8 @@ find_parm_usage_r (tree *tp, int *walk_subtrees, void*)
return NULL_TREE;
}
-/* Returns true if ARGS (a collection of template arguments) contains
- any types that require structural equality testing. */
+/* Returns true if a type specialization formed using the template
+ arguments ARGS needs to use structural equality. */
bool
any_template_arguments_need_structural_equality_p (tree args)
@@ -28266,10 +28263,11 @@ any_template_arguments_need_structural_equality_p (tree args)
return true;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
continue;
- else if (TYPE_P (arg) && TYPE_STRUCTURAL_EQUALITY_P (arg))
- return true;
- else if (!TYPE_P (arg) && TREE_TYPE (arg)
- && TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (arg)))
+ else if (arg == any_targ_node)
+ /* An any_targ_node argument (added by add_defaults_to_ttp)
+ makes the corresponding specialization not canonicalizable,
+ since template_args_equal always return true for it. We
+ may see this when called from bind_template_template_parm. */
return true;
/* Checking current_function_decl because this structural
comparison is only necessary for redeclaration. */
@@ -28277,6 +28275,16 @@ any_template_arguments_need_structural_equality_p (tree args)
&& dependent_template_arg_p (arg)
&& (cp_walk_tree_without_duplicates
(&arg, find_parm_usage_r, NULL)))
+ /* The identity of a class template specialization that uses
+ a function parameter depends on the identity of the function.
+ And if this specialization appeared in the trailing return
+ type thereof, we don't know the identity of the function
+ (e.g. if it's a redeclaration or a new function) until we
+ form its signature and go through duplicate_decls. Thus
+ it's unsafe to decide on a canonical type now (which depends
+ on the DECL_CONTEXT of the function parameter, which can get
+ mutated after the fact by duplicate_decls), so just require
+ structural equality in this case (PR52830). */
return true;
}
}
@@ -29144,10 +29152,6 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
TEMPLATE_PARM_PARAMETER_PACK (newidx)
= TEMPLATE_PARM_PARAMETER_PACK (oldidx);
TYPE_STUB_DECL (newtype) = TYPE_NAME (newtype) = newdecl;
- if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (olddecl)))
- SET_TYPE_STRUCTURAL_EQUALITY (newtype);
- else
- TYPE_CANONICAL (newtype) = canonical_type_parameter (newtype);
if (TREE_CODE (olddecl) == TEMPLATE_DECL)
{
@@ -29189,6 +29193,11 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
// All done.
DECL_TEMPLATE_PARMS (newdecl) = ttparms;
}
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (olddecl)))
+ SET_TYPE_STRUCTURAL_EQUALITY (newtype);
+ else
+ TYPE_CANONICAL (newtype) = canonical_type_parameter (newtype);
}
else
{
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index bc38c8f..0916279 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -2901,7 +2901,11 @@ 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);
+
+ if (any_template_arguments_need_structural_equality_p (newargs))
+ SET_TYPE_STRUCTURAL_EQUALITY (t2);
+ else
+ TYPE_CANONICAL (t2) = canonical_type_parameter (t2);
return t2;
}
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6ecdd97..385cdf4 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -1511,8 +1511,10 @@ structural_comptypes (tree t1, tree t2, int strict)
substitute into the specialization arguments at instantiation
time. And aliases can't be equivalent without being ==, so
we don't need to look any deeper. */
+ ++processing_template_decl;
tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent);
tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent);
+ --processing_template_decl;
if ((dep1 || dep2) && dep1 != dep2)
return false;
}