pt.c (process_partial_specialization): Build a TEMPLATE_DECL for a partial specialization.

* pt.c (process_partial_specialization): Build a TEMPLATE_DECL for
	a partial specialization.
	(tsubst_decl): Don't clobber CLASSTYPE_TI_TEMPLATE of a partial
	specialization.
	(most_specialized_class): Adjust.

From-SVN: r200263
This commit is contained in:
Jason Merrill 2013-06-20 14:33:02 -04:00 committed by Jason Merrill
parent 4ab013d93a
commit 4ca5c232d0
3 changed files with 35 additions and 24 deletions

View file

@ -1,5 +1,11 @@
2013-06-20 Jason Merrill <jason@redhat.com>
* pt.c (process_partial_specialization): Build a TEMPLATE_DECL for
a partial specialization.
(tsubst_decl): Don't clobber CLASSTYPE_TI_TEMPLATE of a partial
specialization.
(most_specialized_class): Adjust.
* cp-tree.h (DECL_TEMPLATE_PARMS, DECL_TEMPLATE_RESULT)
(DECL_TEMPLATE_INSTANTIATIONS, DECL_TEMPLATE_SPECIALIZATIONS): Use
TEMPLATE_DECL_CHECK.

View file

@ -3727,11 +3727,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
specializations of this template. (Full specializations are not
recorded on this list.) The TREE_PURPOSE holds the arguments used
in the partial specialization (e.g., for `template <class T> struct
S<T*, int>' this will be `T*'.) The arguments will also include
any outer template arguments. The TREE_VALUE holds the innermost
template parameters for the specialization (e.g., `T' in the
example above.) The TREE_TYPE is the _TYPE node for the partial
specialization.
S<T*, int>' this will be `T*, int'.) The arguments will also include
any outer template arguments. The TREE_VALUE holds the TEMPLATE_DECL
for the partial specialization. The TREE_TYPE is the _TYPE node for
the partial specialization.
This list is not used for other templates. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) \
@ -3801,9 +3800,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define SET_DECL_SELF_REFERENCE_P(NODE) \
(DECL_LANG_FLAG_4 (NODE) = 1)
/* A `primary' template is one that has its own template header. A
member function of a class template is a template, but not primary.
A member template is primary. Friend templates are primary, too. */
/* A `primary' template is one that has its own template header and is not
a partial specialization. A member function of a class template is a
template, but not primary. A member template is primary. Friend
templates are primary, too. */
/* Returns the primary template corresponding to these parameters. */
#define DECL_PRIMARY_TEMPLATE(NODE) \

View file

@ -4246,8 +4246,16 @@ process_partial_specialization (tree decl)
/* We should only get here once. */
gcc_assert (!COMPLETE_TYPE_P (type));
tree tmpl = build_template_decl (decl, current_template_parms,
DECL_MEMBER_TEMPLATE_P (maintmpl));
TREE_TYPE (tmpl) = type;
DECL_TEMPLATE_RESULT (tmpl) = decl;
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs);
DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl;
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
= tree_cons (specargs, inner_parms,
= tree_cons (specargs, tmpl,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
@ -10058,7 +10066,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
RETURN (error_mark_node);
TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r;
/* For a partial specialization, we need to keep pointing to
the primary template. */
if (!DECL_TEMPLATE_SPECIALIZATION (t))
CLASSTYPE_TI_TEMPLATE (new_type) = r;
DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);
@ -18080,7 +18091,8 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
{
tree partial_spec_args;
tree spec_args;
tree parms = TREE_VALUE (t);
tree spec_tmpl = TREE_VALUE (t);
tree orig_parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
@ -18088,24 +18100,14 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
if (outer_args)
{
int i;
/* Discard the outer levels of args, and then substitute in the
template args from the enclosing class. */
partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
partial_spec_args = tsubst_template_args
(partial_spec_args, outer_args, tf_none, NULL_TREE);
/* PARMS already refers to just the innermost parms, but the
template parms in partial_spec_args had their levels lowered
by tsubst, so we need to do the same for the parm list. We
can't just tsubst the TREE_VEC itself, as tsubst wants to
treat a TREE_VEC as an argument vector. */
parms = copy_node (parms);
for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
TREE_VEC_ELT (parms, i) =
tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE);
/* And the same for the partial specialization TEMPLATE_DECL. */
spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE);
}
partial_spec_args =
@ -18120,7 +18122,10 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
if (partial_spec_args == error_mark_node)
return error_mark_node;
if (spec_tmpl == error_mark_node)
return error_mark_node;
tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
spec_args = get_class_bindings (tmpl, parms,
partial_spec_args,
args);
@ -18128,7 +18133,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
{
if (outer_args)
spec_args = add_to_template_args (outer_args, spec_args);
list = tree_cons (spec_args, TREE_VALUE (t), list);
list = tree_cons (spec_args, orig_parms, list);
TREE_TYPE (list) = TREE_TYPE (t);
}
}