From 8d019cef1a2ecde418d34b58aece9b5a0be0586f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 27 Feb 1998 12:15:17 +0000 Subject: Support partial specialization of member class templates. * pt.c (get_class_bindings): Add outer_args parm. (most_specialized_class): Likewise. (instantiate_class_template): Pass it. (more_specialized_class): Likewise. (lookup_template_class): Get context from template if none was specified. (finish_member_template_decl): Don't do anything with a partial specialization. * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of AGGREGATE_TYPE_P. * class.c (finish_struct): Member class templates have already been checked for name clashes. * decl.c (pushdecl_with_scope): Handle pushing at class level. From-SVN: r18285 --- gcc/cp/ChangeLog | 16 ++++++++++++++++ gcc/cp/class.c | 2 ++ gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 19 +++++++++++++++---- gcc/cp/decl2.c | 4 ++-- gcc/cp/pt.c | 51 +++++++++++++++++++++++++++++++++++---------------- 6 files changed, 71 insertions(+), 23 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 319136f..136a71a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +Fri Feb 27 11:17:50 1998 Jason Merrill + + * pt.c (get_class_bindings): Add outer_args parm. + (most_specialized_class): Likewise. + (instantiate_class_template): Pass it. + (more_specialized_class): Likewise. + (lookup_template_class): Get context from template if none + was specified. + (finish_member_template_decl): Don't do anything with a + partial specialization. + * decl2.c (check_member_template): Use IS_AGGR_TYPE instead of + AGGREGATE_TYPE_P. + * class.c (finish_struct): Member class templates have already been + checked for name clashes. + * decl.c (pushdecl_with_scope): Handle pushing at class level. + Fri Feb 27 02:25:16 1998 Jason Merrill * pt.c (tsubst, TEMPLATE_DECL): Support member class templates. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 9868928..6d64e98 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4375,6 +4375,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) /* Check for inconsistent use of this name in the class body. Enums, types and static vars have already been checked. */ if (TREE_CODE (x) != TYPE_DECL && TREE_CODE (x) != USING_DECL + && ! (TREE_CODE (x) == TEMPLATE_DECL + && TREE_CODE (DECL_RESULT (x)) == TYPE_DECL) && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL) { tree name = DECL_NAME (x); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9f96b4a..eedf3e2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2458,7 +2458,7 @@ extern void end_tree PROTO((void)); extern void add_maybe_template PROTO((tree, tree)); extern void pop_tinst_level PROTO((void)); extern tree most_specialized PROTO((tree, tree, tree)); -extern tree most_specialized_class PROTO((tree, tree)); +extern tree most_specialized_class PROTO((tree, tree, tree)); extern int more_specialized_class PROTO((tree, tree)); extern void do_pushlevel PROTO((void)); extern int is_member_template PROTO((tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0002891..b61d44a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3503,13 +3503,24 @@ pushdecl_with_scope (x, level) tree x; struct binding_level *level; { - register struct binding_level *b = current_binding_level; + register struct binding_level *b; tree function_decl = current_function_decl; current_function_decl = NULL_TREE; - current_binding_level = level; - x = pushdecl (x); - current_binding_level = b; + if (level->parm_flag == 2) + { + b = class_binding_level; + class_binding_level = level; + pushdecl_class_level (x); + class_binding_level = b; + } + else + { + b = current_binding_level; + current_binding_level = level; + x = pushdecl (x); + current_binding_level = b; + } current_function_decl = function_decl; return x; } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index cb786f9..fa39b9e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1386,8 +1386,8 @@ check_member_template (tmpl) with member templates. */ DECL_IGNORED_P (tmpl) = 1; } - else if (TREE_CODE (decl) == TYPE_DECL && - AGGREGATE_TYPE_P (TREE_TYPE (decl))) + else if (TREE_CODE (decl) == TYPE_DECL + && IS_AGGR_TYPE (TREE_TYPE (decl))) { if (current_function_decl) /* 14.5.2.2 [temp.mem] diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fe66bf4..d5362aa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -77,7 +77,7 @@ static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree)); static tree tsubst_expr_values PROTO((tree, tree)); static int comp_template_args PROTO((tree, tree)); static int list_eq PROTO((tree, tree)); -static tree get_class_bindings PROTO((tree, tree, tree)); +static tree get_class_bindings PROTO((tree, tree, tree, tree)); static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int)); static tree tsubst_enum PROTO((tree, tree, tree *)); static tree add_to_template_args PROTO((tree, tree)); @@ -109,12 +109,14 @@ finish_member_template_decl (template_parameters, decl) { /* Assume that the class is the only declspec. */ decl = TREE_VALUE (decl); - if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl)) + if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl) + && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl)) { tree tmpl = CLASSTYPE_TI_TEMPLATE (decl); check_member_template (tmpl); return tmpl; } + return NULL_TREE; } else if (DECL_TEMPLATE_INFO (decl) && !DECL_TEMPLATE_SPECIALIZATION (decl)) @@ -2380,6 +2382,8 @@ lookup_template_class (d1, arglist, in_decl, context) if (! template) template = IDENTIFIER_CLASS_VALUE (d1); } + if (template) + context = DECL_CONTEXT (template); } else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1))) { @@ -2938,7 +2942,7 @@ instantiate_class_template (type) tree type; { tree template, template_info, args, pattern, t, *field_chain; - tree typedecl; + tree typedecl, outer_args; if (type == error_mark_node) return error_mark_node; @@ -2954,14 +2958,15 @@ instantiate_class_template (type) if (DECL_TEMPLATE_INFO (template)) { - args = add_to_template_args (DECL_TI_ARGS (template), args); + outer_args = DECL_TI_ARGS (template); while (DECL_TEMPLATE_INFO (template)) template = DECL_TI_TEMPLATE (template); } + else + outer_args = NULL_TREE; - /* FIXME deal with partial specializations of member templates. */ t = most_specialized_class - (DECL_TEMPLATE_SPECIALIZATIONS (template), args); + (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args); if (t == error_mark_node) { @@ -2969,7 +2974,8 @@ instantiate_class_template (type) cp_error ("ambiguous class template instantiation for `%#T'", type); for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t)) { - if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args)) + if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), + args, outer_args)) { cp_error_at ("%s %+#T", str, TREE_TYPE (t)); str = " "; @@ -2987,7 +2993,11 @@ instantiate_class_template (type) return type; if (t) - args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args); + args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), + args, outer_args); + + if (outer_args) + args = add_to_template_args (outer_args, args); if (pedantic && uses_template_parms (args)) /* If there are still template parameters amongst the args, then @@ -3617,7 +3627,7 @@ tsubst (t, args, in_decl) if (PRIMARY_TEMPLATE_P (t)) TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl; - /* FIXME deal with partial specializations. */ + /* We don't partially instantiate partial specializations. */ if (TREE_CODE (decl) == TYPE_DECL) return tmpl; @@ -5651,12 +5661,14 @@ more_specialized_class (pat1, pat2) int winner = 0; targs = get_class_bindings - (TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2)); + (TREE_VALUE (pat1), TREE_PURPOSE (pat1), + TREE_PURPOSE (pat2), NULL_TREE); if (targs) --winner; targs = get_class_bindings - (TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1)); + (TREE_VALUE (pat2), TREE_PURPOSE (pat2), + TREE_PURPOSE (pat1), NULL_TREE); if (targs) ++winner; @@ -5718,12 +5730,18 @@ get_bindings (fn, decl, explicit_args) } static tree -get_class_bindings (tparms, parms, args) - tree tparms, parms, args; +get_class_bindings (tparms, parms, args, outer_args) + tree tparms, parms, args, outer_args; { int i, dummy, ntparms = TREE_VEC_LENGTH (tparms); tree vec = make_temp_vec (ntparms); + if (outer_args) + { + tparms = tsubst (tparms, outer_args, NULL_TREE); + parms = tsubst (parms, outer_args, NULL_TREE); + } + for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms, @@ -5803,15 +5821,16 @@ most_specialized (fns, decl, explicit_args) SPECS that can produce an instantiation matching ARGS. */ tree -most_specialized_class (specs, mainargs) - tree specs, mainargs; +most_specialized_class (specs, mainargs, outer_args) + tree specs, mainargs, outer_args; { tree list = NULL_TREE, t, args, champ; int fate; for (t = specs; t; t = TREE_CHAIN (t)) { - args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), mainargs); + args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), + mainargs, outer_args); if (args) { list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list); -- cgit v1.1