@@ -6673,7 +6673,7 @@ build_self_reference (void)
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
- cp_set_underlying_type (value);
+ set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);
@@ -3954,6 +3954,8 @@ enum tsubst_flags {
when issuing other errors. */
/* Do not instantiate classes (used by count_non_default_template_args). */
tf_no_class_instantiations = 1 << 8,
+ tf_no_tpl_reduce = 1 << 9, /* Do not reduce the level of
+ template parameters. */
/* Convenient substitution flags combinations. */
tf_warning_or_error = tf_warning | tf_error
};
@@ -4321,10 +4323,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
(TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
(TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
- TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
- (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
+
+/* The length of the template parms list this template parm belongs
+ to. This is a an integer wrapped into a tree node. */
+#define TEMPLATE_NUM_SIBLING_PARMS(NODE) \
+ (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, \
+ TEMPLATE_TEMPLATE_PARM, \
+ BOUND_TEMPLATE_TEMPLATE_PARM))->type.maxval
/* These constants can used as bit flags in the process of tree formatting.
@@ -5005,7 +5010,7 @@ extern void append_type_to_template_for_access_check (tree, tree, tree,
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
extern tree process_template_parm (tree, location_t, tree,
- bool, bool);
+ bool, bool, unsigned);
extern tree end_template_parm_list (tree);
extern void end_template_decl (void);
extern tree maybe_update_decl_type (tree, tree);
@@ -5341,7 +5346,6 @@ extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree);
-extern void cp_set_underlying_type (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_tree);
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
if (declspecs->specs[(int)ds_typedef]
&& TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
- cp_set_underlying_type (value);
+ set_underlying_type (value);
return value;
}
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
inlining. */
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
- cp_set_underlying_type (x);
+ set_underlying_type (x);
if (type != error_mark_node
&& TYPE_NAME (type)
@@ -10997,6 +10997,15 @@ cp_parser_template_parameter_list (cp_parser* parser)
tree parameter_list = NULL_TREE;
begin_template_parm_list ();
+
+ /* The loop below parses the template parms. Note that dependent
+ types created during this parsing require structural comparison
+ rather than canonical type comparison. This is because we first
+ need to know the total number of template parms to be able to
+ compute canonical types of each dependent type. So after the
+ loop, when we know the total number of template parms,
+ end_template_parm_list computes the proper canonical types and
+ fixes up the dependent types accordingly. */
while (true)
{
tree parameter;
@@ -11015,11 +11024,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
parm_loc,
parameter,
is_non_type,
- is_parameter_pack);
+ is_parameter_pack,
+ 0);
else
{
tree err_parm = build_tree_list (parameter, parameter);
- TREE_VALUE (err_parm) = error_mark_node;
parameter_list = chainon (parameter_list, err_parm);
}
@@ -93,10 +93,14 @@ static GTY ((param_is (spec_entry)))
static GTY ((param_is (spec_entry)))
htab_t type_specializations;
-/* Contains canonical template parameter types. The vector is indexed 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. */
+/* Contains canonical template parameter types. The vector is indexed
+ by the TEMPLATE_TYPE_IDX of the template parameter. Each element is
+ a TREE_LIST, whose TREE_PURPOSE is a INT_CST tree representing a
+ total size of the template parameter list a given template
+ parameter would belong too, and whose TREE_VALUEs contain the
+ canonical template parameters of various types and levels,
+ belonging to a set of template parameters which size is
+ TREE_PURPOSE. */
static GTY(()) VEC(tree,gc) *canonical_template_parms;
#define UNIFY_ALLOW_NONE 0
@@ -190,6 +194,9 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static tree listify (tree);
static tree listify_autos (tree, tree);
+static tree current_template_args (void);
+static void fixup_template_parms_canonical_types (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -3369,12 +3376,25 @@ build_template_parm_index (int index,
/* 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. */
+ if no such parameter existed. TOTAL_NUM_PARMS is the number of
+ template parameters carried by the considered template.
+
+ If TYPE is the template parameter at position P in a
+ template, this function won't return the same canonical type as for
+ a another TYPE that would be a template parameter at position Q,
+ with Q != P.
+
+ If TOTAL_NUM_PARMS is 0, the function returns NULL_TREE. */
+
static tree
-canonical_type_parameter (tree type)
+canonical_type_parameter (tree type, unsigned total_num_parms)
{
tree list;
int idx = TEMPLATE_TYPE_IDX (type);
+
+ if (total_num_parms == 0)
+ return NULL_TREE;
+
if (!canonical_template_parms)
canonical_template_parms = VEC_alloc (tree, gc, idx+1);
@@ -3382,15 +3402,20 @@ canonical_type_parameter (tree type)
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);
+ while (list)
+ {
+ if (TREE_INT_CST_LOW (TREE_PURPOSE (list)) == total_num_parms
+ && comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
+ break;
+ list = TREE_CHAIN (list);
+ }
if (list)
return TREE_VALUE (list);
else
{
VEC_replace(tree, canonical_template_parms, idx,
- tree_cons (NULL_TREE, type,
+ tree_cons (size_int (total_num_parms), type,
VEC_index (tree, canonical_template_parms, idx)));
return type;
}
@@ -3438,15 +3463,21 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
return TEMPLATE_PARM_DESCENDANTS (index);
}
-/* Process information from new template parameter PARM and append it to the
- LIST being built. This new parameter is a non-type parameter iff
- IS_NON_TYPE is true. This new parameter is a parameter
- pack iff IS_PARAMETER_PACK is true. The location of PARM is in
- PARM_LOC. */
+/* Process information from new template parameter PARM and append it
+ to the LIST being built. This new parameter is a non-type
+ parameter iff IS_NON_TYPE is true. This new parameter is a
+ parameter pack iff IS_PARAMETER_PACK is true. The location of PARM
+ is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+ parameter list PARM belongs to. This is used used to create a
+ proper canonical type for the type of PARM that is to be created,
+ iff PARM is a type. If the size is not known, this parameter can
+ be set to 0. Setting it to zero would create a template type
+ parameter with no canonical type. */
tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type,
- bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+ bool is_non_type, bool is_parameter_pack,
+ unsigned num_template_parms)
{
tree decl = 0;
tree defval;
@@ -3556,8 +3587,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
processing_template_decl,
decl, TREE_TYPE (parm));
TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
- TYPE_CANONICAL (t) = canonical_type_parameter (t);
- }
+ TYPE_CANONICAL (t) =
+ canonical_type_parameter (t, num_template_parms);
+ }
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
pushdecl (decl);
@@ -3573,9 +3605,9 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
tree
end_template_parm_list (tree parms)
{
- int nparms;
+ int nparms, length = list_length (parms);
tree parm, next;
- tree saved_parmlist = make_tree_vec (list_length (parms));
+ tree saved_parmlist = make_tree_vec (length);
current_template_parms
= tree_cons (size_int (processing_template_decl),
@@ -3586,16 +3618,141 @@ end_template_parm_list (tree parms)
next = TREE_CHAIN (parm);
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
TREE_CHAIN (parm) = NULL_TREE;
- if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
- TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
- current_template_parms;
+ if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
+ || TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
+ TEMPLATE_NUM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
+ size_int (length);
}
+ fixup_template_parms_canonical_types ();
+
--processing_template_parmlist;
return saved_parmlist;
}
+/* Walk current the template parms and properly compute the canonical
+ types of the dependent types created during
+ cp_parser_template_parameter_list. */
+
+static void
+fixup_template_parms_canonical_types (void)
+{
+ tree parm;
+ tree full_template_args;
+ tree parameter_vec;
+ int i, num_parms;
+
+ parameter_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ if (parameter_vec == NULL_TREE)
+ return;
+
+ num_parms = TREE_VEC_LENGTH (parameter_vec);
+
+ /* In this first loop, let's update the canonical type of each
+ type template parameter. */
+ for (i = 0; i < num_parms; ++i)
+ {
+ tree main_type, variant;
+
+ parm = TREE_VALUE (TREE_VEC_ELT (parameter_vec, i));
+ if (TREE_CODE (parm) == TYPE_DECL
+ || TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ tree arglist = current_template_args ();
+ tree tparms;
+ int j;
+
+ /* So PARM is a template tempate parameter, e.g, like TT
+ in:
+
+ template<class T, template<T> class TT> class S;
+
+ In this case we want to substitute T into the
+ template parameters of TT.
+
+ Sot let's walk the template parms of PARM here, and
+ tsubst ARGLIST into into each of the template
+ parms. */
+ tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
+ for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
+ {
+ tree substed_parm;
+ ++cp_unevaluated_operand;
+ /* Note the use of tf_no_tpl_reduce as the last
+ argument to tsubst_template_parm here. Suppose
+ the current template parameter of PARM is itself
+ a template. In that case, we do not want
+ tsubst_template_parm to reduce the level of the
+ parameters of that later template , as tsubst or
+ tsubst_template_parms would normally do [because
+ we are not tsubsting here for the purpose of
+ instantiating a type, rather, we just want to
+ substitute template parameters "in
+ place"]. Therefore, we use tf_no_tpl_reduce to
+ really avoid that template parm level
+ reduction. */
+ substed_parm = tsubst_template_parm (TREE_VEC_ELT (tparms, j),
+ arglist,
+ tf_no_tpl_reduce);
+ --cp_unevaluated_operand;
+ TREE_VEC_ELT (tparms, j) = substed_parm;
+ }
+ }
+
+ /* Compute the canonical type of type template
+ parameters and their variants. */
+ main_type = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
+ TYPE_CANONICAL (main_type) =
+ canonical_type_parameter (main_type, num_parms);
+ for (variant = TYPE_NEXT_VARIANT (main_type);
+ variant;
+ variant = TYPE_NEXT_VARIANT (variant))
+ TYPE_CANONICAL (variant) =
+ canonical_type_parameter (variant, num_parms);
+ }
+ }
+
+ /* And now let's substitute the template type parameters into
+ dependent non-type template arguments and default template
+ arguments. */
+ full_template_args = current_template_args ();
+ for (i = 0; i < num_parms; ++i)
+ {
+ tree cur = TREE_VEC_ELT (parameter_vec, i);
+
+ if ((TREE_CODE (parm) == TYPE_DECL
+ || TREE_CODE (parm) == TEMPLATE_DECL)
+ && TREE_PURPOSE (cur))
+ {
+ tree default_arg = TREE_PURPOSE (cur);
+
+ if (TYPE_P (default_arg)
+ && !dependent_type_p (default_arg))
+ continue;
+
+ ++cp_unevaluated_operand;
+ TREE_PURPOSE (cur) =
+ tsubst_expr (default_arg, full_template_args,
+ tf_none, default_arg, false);
+ --cp_unevaluated_operand;
+ }
+
+ if (TREE_CODE (TREE_VALUE (cur)) == PARM_DECL)
+ {
+ tree non_type_parm = TREE_VALUE (cur);
+ ++cp_unevaluated_operand;
+ TREE_VALUE (cur) =
+ tsubst_decl (non_type_parm,
+ full_template_args,
+ tf_none);
+ --cp_unevaluated_operand;
+ }
+ }
+}
+
/* end_template_decl is called after a template declaration is seen. */
void
@@ -3706,7 +3863,23 @@ current_template_args (void)
else
args = a;
}
-
+
+ if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+ /* This can happen for template parms of a template template
+ parameter, e.g:
+
+ template<template<class T, class U> class TT> struct S;
+
+ Consider the level of the parms of TT; T and U both have
+ level 2; TT has no template parm of level 1. So in this case
+ the first element of full_template_args is NULL_TREE. If we
+ leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+ of 2. This will make tsubst wrongly consider that T and U
+ have level 1. Instead, let's create a dummy vector as the
+ first element of full_template_args so that TMPL_ARG_DEPTH
+ returns the correct depth for args.
+ */
+ TREE_VEC_ELT (args, 0) = make_tree_vec (1);
return args;
}
@@ -6681,16 +6854,22 @@ lookup_template_class (tree d1,
if (context == current_function_decl)
pushtag (DECL_NAME (gen_tmpl), t, /*tag_scope=*/ts_current);
- if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), arglist))
+ 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. Note that we check this
+ condition first because for dependent types that are
+ created /during/ the parsing of template parameter lists,
+ we must not require canonical type equality because
+ canonical types of dependent types are actually going
+ to be properly computed right at /the end/ of the
+ template parms parsing. */
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else 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
@@ -8722,6 +8901,7 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
{
tree r = NULL_TREE;
tree* new_parms;
+ bool reduce_level_p = !(complain & tf_no_tpl_reduce);
/* When substituting into a template, we must set
PROCESSING_TEMPLATE_DECL as the template parameters may be
@@ -8730,19 +8910,18 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
++processing_template_decl;
for (new_parms = &r;
- TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
+ ((reduce_level_p && TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args))
+ ||(!reduce_level_p && parms));
new_parms = &(TREE_CHAIN (*new_parms)),
parms = TREE_CHAIN (parms))
{
tree new_vec =
make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
- int i;
+ int i, new_level;
for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
{
tree tuple;
- tree default_value;
- tree parm_decl;
if (parms == error_mark_node)
continue;
@@ -8752,23 +8931,16 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
if (tuple == error_mark_node)
continue;
- default_value = TREE_PURPOSE (tuple);
- parm_decl = TREE_VALUE (tuple);
-
- parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
- if (TREE_CODE (parm_decl) == PARM_DECL
- && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
- parm_decl = error_mark_node;
- default_value = tsubst_template_arg (default_value, args,
- complain, NULL_TREE);
-
- tuple = build_tree_list (default_value, parm_decl);
- TREE_VEC_ELT (new_vec, i) = tuple;
+ TREE_VEC_ELT (new_vec, i) =
+ tsubst_template_parm (tuple, args, complain);
}
+ new_level = reduce_level_p
+ ? TMPL_PARMS_DEPTH (parms) - TMPL_ARGS_DEPTH (args)
+ : TMPL_PARMS_DEPTH (parms);
+
*new_parms =
- tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
- - TMPL_ARGS_DEPTH (args)),
+ tree_cons (size_int (new_level),
new_vec, NULL_TREE);
}
@@ -8777,6 +8949,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
return r;
}
+/* Return the result of substituting ARGS into one template parameter
+ given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+ parameter and which TREE_PURPOSE is the default argument of the
+ template parameter. */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+ tree default_value, parm_decl;
+
+ if (args == NULL_TREE
+ || t == NULL_TREE
+ || t == error_mark_node)
+ return t;
+
+ gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+ default_value = TREE_PURPOSE (t);
+ parm_decl = TREE_VALUE (t);
+
+ parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+ if (TREE_CODE (parm_decl) == PARM_DECL
+ && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+ parm_decl = error_mark_node;
+ default_value = tsubst_template_arg (default_value, args,
+ complain, NULL_TREE);
+
+ return build_tree_list (default_value, parm_decl);
+}
+
/* Substitute the ARGS into the indicated aggregate (or enumeration)
type T. If T is not an aggregate or enumeration type, it is
handled as if by tsubst. IN_DECL is as for tsubst. If
@@ -10271,9 +10473,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
{
r = copy_type (t);
- TEMPLATE_TYPE_PARM_INDEX (r)
- = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
- r, levels, args, complain);
+ if (!(complain & tf_no_tpl_reduce))
+ TEMPLATE_TYPE_PARM_INDEX (r)
+ = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+ r, levels, args, complain);
TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
TYPE_MAIN_VARIANT (r) = r;
TYPE_POINTER_TO (r) = NULL_TREE;
@@ -10291,7 +10494,14 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else if (TYPE_STRUCTURAL_EQUALITY_P (t))
SET_TYPE_STRUCTURAL_EQUALITY (r);
else
- TYPE_CANONICAL (r) = canonical_type_parameter (r);
+ {
+ unsigned num_parms =
+ (TEMPLATE_NUM_SIBLING_PARMS (t))
+ ? TREE_INT_CST_LOW (TEMPLATE_NUM_SIBLING_PARMS (t))
+ : 0;
+ TYPE_CANONICAL (r) =
+ canonical_type_parameter (r, num_parms);
+ }
if (code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
@@ -10307,7 +10517,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
case TEMPLATE_PARM_INDEX:
- r = reduce_template_parm_level (t, type, levels, args, complain);
+ if (complain & tf_no_tpl_reduce)
+ r = t;
+ else
+ r = reduce_template_parm_level (t, type, levels, args, complain);
break;
default:
@@ -14701,6 +14914,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+ tree full_argvec = add_to_template_args (targs, argvec);
tree parm_parms
= DECL_INNERMOST_TEMPLATE_PARMS
(TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14735,7 +14949,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
the global operator+ will be used; if they are not, the
Lvalue_proxy will be converted to float. */
if (coerce_template_parms (parm_parms,
- argvec,
+ full_argvec,
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
@@ -17781,7 +17995,8 @@ type_dependent_expression_p (tree expression)
if (!processing_template_decl)
return false;
- if (expression == error_mark_node)
+ if (expression == error_mark_node
+ || expression == NULL_TREE)
return false;
/* An unresolved name is always dependent. */
@@ -18401,7 +18616,7 @@ make_auto (void)
TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
(0, processing_template_decl + 1, processing_template_decl + 1,
TYPE_NAME (au), NULL_TREE);
- TYPE_CANONICAL (au) = canonical_type_parameter (au);
+ TYPE_CANONICAL (au) = canonical_type_parameter (au, 0);
DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
@@ -1063,22 +1063,6 @@ strip_typedefs (tree t)
return cp_build_qualified_type (result, cp_type_quals (t));
}
-/* Setup a TYPE_DECL node as a typedef representation.
- See comments of set_underlying_type in c-common.c. */
-
-void
-cp_set_underlying_type (tree t)
-{
- set_underlying_type (t);
- /* If T is a template type parm, make it require structural equality.
- This is useful when comparing two template type parms,
- because it forces the comparison of the template parameters of their
- decls. */
- if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
- SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
and we do a shallow copy. If BINFO is non-NULL, we do a deep copy.
@@ -1143,114 +1143,20 @@ comp_template_parms_position (tree t1, tree t2)
|| TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
- if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
- || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
- || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
- != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
- return false;
-
- return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
- Return the template parameter of the dependent type T.
- If T is a typedef, return the template parameters of
- the _decl_ of the typedef. T must be a dependent type. */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
- tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
- /* First, try the obvious case of getting the
- template info from T itself. */
- if ((tinfo = get_template_info (t)))
- ;
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
- else if (typedef_variant_p (t)
- && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
- tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
- /* If T is a TYPENAME_TYPE which context is a template type
- parameter, get the template parameters from that context. */
- else if (TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
- else if (TYPE_CONTEXT (t)
- && !NAMESPACE_SCOPE_P (t))
- tinfo = get_template_info (TYPE_CONTEXT (t));
-
- if (tinfo)
- tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
- return tparms;
-}
-
-/* Subroutine of structural_comptypes.
- Compare the dependent types T1 and T2.
- Return TRUE if we are sure they can't be equal, FALSE otherwise.
- The whole point of this function is to support cases where either T1 or
- T2 is a typedef. In those cases, we need to compare the template parameters
- of the _decl_ of the typedef. If those don't match then we know T1
- and T2 cannot be equal. */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
- tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
- bool t1_typedef_variant_p, t2_typedef_variant_p;
-
- if (!uses_template_parms (t1) || !uses_template_parms (t2))
- return false;
-
- if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
- {
- /* If T1 and T2 don't have the same relative position in their
- template parameters set, they can't be equal. */
- if (!comp_template_parms_position (t1, t2))
- return true;
- }
-
- t1_typedef_variant_p = typedef_variant_p (t1);
- t2_typedef_variant_p = typedef_variant_p (t2);
-
- /* Either T1 or T2 must be a typedef. */
- if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+ /* If T1 and T2 belong to template parm lists of different size,
+ let's assume they are different. */
+ if (TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t1))
+ != TEMPLATE_NUM_SIBLING_PARMS (TYPE_MAIN_VARIANT (t2)))
return false;
- if (!t1_typedef_variant_p || !t2_typedef_variant_p)
- /* Either T1 or T2 is not a typedef so we cannot compare the
- template parms of the typedefs of T1 and T2.
- At this point, if the main variant type of T1 and T2 are equal
- it means the two types can't be incompatible, from the perspective
- of this function. */
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return false;
-
- /* So if we reach this point, it means either T1 or T2 is a typedef variant.
- Let's compare their template parameters. */
-
- tparms1 = get_template_parms_of_dependent_type (t1);
- tparms2 = get_template_parms_of_dependent_type (t2);
-
- /* If T2 is a template type parm and if we could not get the template
- parms it belongs to, that means we have not finished parsing the
- full set of template parameters of the template declaration it
- belongs to yet. If we could get the template parms T1 belongs to,
- that mostly means T1 and T2 belongs to templates that are
- different and incompatible. */
- if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
- && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
- && tparms1 != tparms2)
- return true;
-
- if (tparms1 == NULL_TREE
- || tparms2 == NULL_TREE
- || tparms1 == tparms2)
+ /* Then compare their relative position. */
+ if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
+ || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
+ || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
+ != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
return false;
- /* And now compare the mighty template parms! */
- return !comp_template_parms (tparms1, tparms2);
+ return true;
}
/* Subroutine in comptypes. */
@@ -1295,12 +1201,6 @@ structural_comptypes (tree t1, tree t2, int strict)
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false;
- /* If T1 and T2 are dependent typedefs then check upfront that
- the template parameters of their typedef DECLs match before
- going down checking their subtypes. */
- if (incompatible_dependent_types_p (t1, t2))
- return false;
-
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
@@ -1345,6 +1245,7 @@ structural_comptypes (tree t1, tree t2, int strict)
(DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t2))))
return false;
+
if (TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM)
break;
/* Don't check inheritance. */
@@ -1401,8 +1302,10 @@ structural_comptypes (tree t1, tree t2, int strict)
break;
case TEMPLATE_TYPE_PARM:
- /* If incompatible_dependent_types_p called earlier didn't decide
- T1 and T2 were different, they might be equal. */
+ /* If T1 and T2 don't have the same relative position in their
+ template parameters set, they can't be equal. */
+ if (!comp_template_parms_position (t1, t2))
+ return false;
break;
case TYPENAME_TYPE:
new file mode 100644
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+#include <list>
+
+template<class T>
+class Test
+{
+protected:
+ typedef std::list<T> ListAlias;
+ ListAlias list;
+public:
+ typedef typename ListAlias::const_iterator const_iterator;
+ inline const_iterator begin() const;
+
+};
+
+template<class T>
+inline typename std::list<T>::const_iterator Test<T>::begin() const
+{
+ return list.begin();
+}
+