Commit 4ca5c232 by Jason Merrill Committed by Jason Merrill

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
parent 4ab013d9
2013-06-20 Jason Merrill <jason@redhat.com> 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) * cp-tree.h (DECL_TEMPLATE_PARMS, DECL_TEMPLATE_RESULT)
(DECL_TEMPLATE_INSTANTIATIONS, DECL_TEMPLATE_SPECIALIZATIONS): Use (DECL_TEMPLATE_INSTANTIATIONS, DECL_TEMPLATE_SPECIALIZATIONS): Use
TEMPLATE_DECL_CHECK. TEMPLATE_DECL_CHECK.
......
...@@ -3727,11 +3727,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -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 specializations of this template. (Full specializations are not
recorded on this list.) The TREE_PURPOSE holds the arguments used recorded on this list.) The TREE_PURPOSE holds the arguments used
in the partial specialization (e.g., for `template <class T> struct in the partial specialization (e.g., for `template <class T> struct
S<T*, int>' this will be `T*'.) The arguments will also include S<T*, int>' this will be `T*, int'.) The arguments will also include
any outer template arguments. The TREE_VALUE holds the innermost any outer template arguments. The TREE_VALUE holds the TEMPLATE_DECL
template parameters for the specialization (e.g., `T' in the for the partial specialization. The TREE_TYPE is the _TYPE node for
example above.) The TREE_TYPE is the _TYPE node for the partial the partial specialization.
specialization.
This list is not used for other templates. */ This list is not used for other templates. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) \ #define DECL_TEMPLATE_SPECIALIZATIONS(NODE) \
...@@ -3801,9 +3800,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -3801,9 +3800,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define SET_DECL_SELF_REFERENCE_P(NODE) \ #define SET_DECL_SELF_REFERENCE_P(NODE) \
(DECL_LANG_FLAG_4 (NODE) = 1) (DECL_LANG_FLAG_4 (NODE) = 1)
/* A `primary' template is one that has its own template header. A /* A `primary' template is one that has its own template header and is not
member function of a class template is a template, but not primary. a partial specialization. A member function of a class template is a
A member template is primary. Friend templates are primary, too. */ template, but not primary. A member template is primary. Friend
templates are primary, too. */
/* Returns the primary template corresponding to these parameters. */ /* Returns the primary template corresponding to these parameters. */
#define DECL_PRIMARY_TEMPLATE(NODE) \ #define DECL_PRIMARY_TEMPLATE(NODE) \
......
...@@ -4246,8 +4246,16 @@ process_partial_specialization (tree decl) ...@@ -4246,8 +4246,16 @@ process_partial_specialization (tree decl)
/* We should only get here once. */ /* We should only get here once. */
gcc_assert (!COMPLETE_TYPE_P (type)); 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) DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
= tree_cons (specargs, inner_parms, = tree_cons (specargs, tmpl,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
...@@ -10058,7 +10066,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -10058,7 +10066,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
RETURN (error_mark_node); RETURN (error_mark_node);
TREE_TYPE (r) = new_type; 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_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type); DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
DECL_CONTEXT (r) = TYPE_CONTEXT (new_type); DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);
...@@ -18080,7 +18091,8 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) ...@@ -18080,7 +18091,8 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
{ {
tree partial_spec_args; tree partial_spec_args;
tree 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)); partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
...@@ -18088,24 +18100,14 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) ...@@ -18088,24 +18100,14 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
if (outer_args) if (outer_args)
{ {
int i;
/* Discard the outer levels of args, and then substitute in the /* Discard the outer levels of args, and then substitute in the
template args from the enclosing class. */ template args from the enclosing class. */
partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args); partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
partial_spec_args = tsubst_template_args partial_spec_args = tsubst_template_args
(partial_spec_args, outer_args, tf_none, NULL_TREE); (partial_spec_args, outer_args, tf_none, NULL_TREE);
/* PARMS already refers to just the innermost parms, but the /* And the same for the partial specialization TEMPLATE_DECL. */
template parms in partial_spec_args had their levels lowered spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE);
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);
} }
partial_spec_args = partial_spec_args =
...@@ -18120,7 +18122,10 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) ...@@ -18120,7 +18122,10 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
if (partial_spec_args == error_mark_node) if (partial_spec_args == error_mark_node)
return 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, spec_args = get_class_bindings (tmpl, parms,
partial_spec_args, partial_spec_args,
args); args);
...@@ -18128,7 +18133,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) ...@@ -18128,7 +18133,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
{ {
if (outer_args) if (outer_args)
spec_args = add_to_template_args (outer_args, spec_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); TREE_TYPE (list) = TREE_TYPE (t);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment