From 4ca5c232d025bf96bd70127dcb5940c4b227cbef Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 20 Jun 2013 14:33:02 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/cp-tree.h | 16 ++++++++-------- gcc/cp/pt.c | 37 +++++++++++++++++++++---------------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7c7a17f8a45..a7df33b562c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2013-06-20 Jason Merrill + * 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 41ef24d455b..9fc4aeb1365 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 struct - S' 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' 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) \ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 517f05b3f42..97efdc99b1a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); } } -- 2.30.2