aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-06-20 14:33:02 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-06-20 14:33:02 -0400
commit4ca5c232d025bf96bd70127dcb5940c4b227cbef (patch)
treecb21c34194d2b27c26ff1d691d755b58932cdbea /gcc
parent4ab013d93a27e19926e0dd3669768ddd93e4662b (diff)
downloadgcc-4ca5c232d025bf96bd70127dcb5940c4b227cbef.zip
gcc-4ca5c232d025bf96bd70127dcb5940c4b227cbef.tar.gz
gcc-4ca5c232d025bf96bd70127dcb5940c4b227cbef.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h16
-rw-r--r--gcc/cp/pt.c37
3 files changed, 35 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7c7a17f..a7df33b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 41ef24d..9fc4aeb 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 <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) \
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 517f05b..97efdc9 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);
}
}