diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f9a728fa4b5..1e90751287c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -80,6 +80,12 @@ static tree cur_stmt_expr; local variables. */ static htab_t local_specializations; +/* Contains canonical template parameter types. The vector is index by + the TEMPLATE_TYPE_IDX of the template parameter. Each element is a + TREE_LIST, whose TREE_VALUEs contain the canonical template + parameters of various types and levels. */ +static GTY(()) VEC(tree,gc) *canonical_template_parms; + #define UNIFY_ALLOW_NONE 0 #define UNIFY_ALLOW_MORE_CV_QUAL 1 #define UNIFY_ALLOW_LESS_CV_QUAL 2 @@ -157,6 +163,7 @@ static tree copy_default_args_to_explicit_spec_1 (tree, tree); static void copy_default_args_to_explicit_spec (tree); static int invalid_nontype_parm_type_p (tree, tsubst_flags_t); static int eq_local_specializations (const void *, const void *); +static bool any_template_arguments_need_structural_equality_p (tree); static bool dependent_type_p_r (tree); static tree tsubst (tree, tree, tsubst_flags_t, tree); static tree tsubst_expr (tree, tree, tsubst_flags_t, tree, bool); @@ -2335,6 +2342,35 @@ build_template_parm_index (int index, return t; } +/* Find the canonical type parameter for the given template type + parmaeter. Returns the canonical type parameter, which may be TYPE + if no such parameter existed. */ +static tree +canonical_type_parameter (tree type) +{ + tree list; + int idx = TEMPLATE_TYPE_IDX (type); + if (!canonical_template_parms) + canonical_template_parms = VEC_alloc (tree, gc, idx+1); + + while (VEC_length (tree, canonical_template_parms) <= (unsigned)idx) + VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE); + + list = VEC_index (tree, canonical_template_parms, idx); + while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL)) + list = TREE_CHAIN (list); + + if (list) + return TREE_VALUE (list); + else + { + VEC_replace(tree, canonical_template_parms, idx, + tree_cons (NULL_TREE, type, + VEC_index (tree, canonical_template_parms, idx))); + return type; + } +} + /* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a @@ -2473,6 +2509,7 @@ process_template_parm (tree list, tree parm, bool is_non_type) = build_template_parm_index (idx, processing_template_decl, processing_template_decl, decl, TREE_TYPE (parm)); + TYPE_CANONICAL (t) = canonical_type_parameter (t); } DECL_ARTIFICIAL (decl) = 1; SET_DECL_TEMPLATE_PARM_P (decl); @@ -4807,6 +4844,17 @@ lookup_template_class (tree d1, /* A local class. Make sure the decl gets registered properly. */ if (context == current_function_decl) pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current); + + if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist)) + /* This instantiation is another name for the primary + template type. Set the TYPE_CANONICAL field + 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); } /* If we called start_enum or pushtag above, this information @@ -7473,6 +7521,18 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) TYPE_POINTER_TO (r) = NULL_TREE; TYPE_REFERENCE_TO (r) = NULL_TREE; + 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 + TYPE_CANONICAL (r) = canonical_type_parameter (r); + if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) { tree argvec = tsubst (TYPE_TI_ARGS (t), args, @@ -13168,6 +13228,40 @@ dependent_template_arg_p (tree arg) } /* Returns true if ARGS (a collection of template arguments) contains + any types that require structural equality testing. */ + +bool +any_template_arguments_need_structural_equality_p (tree args) +{ + int i; + int j; + + if (!args) + return false; + if (args == error_mark_node) + return true; + + for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i) + { + tree level = TMPL_ARGS_LEVEL (args, i + 1); + for (j = 0; j < TREE_VEC_LENGTH (level); ++j) + { + tree arg = TREE_VEC_ELT (level, j); + if (TREE_CODE (arg) == TEMPLATE_DECL + || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + 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))) + return true; + } + } + + return false; +} + +/* Returns true if ARGS (a collection of template arguments) contains any dependent arguments. */ bool |