Commit 8d019cef by Jason Merrill Committed by Jason Merrill

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
parent 5987a4f3
Fri Feb 27 11:17:50 1998 Jason Merrill <jason@yorick.cygnus.com>
* 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 <jason@yorick.cygnus.com> Fri Feb 27 02:25:16 1998 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst, TEMPLATE_DECL): Support member class templates. * pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
......
...@@ -4375,6 +4375,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4375,6 +4375,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
/* Check for inconsistent use of this name in the class body. /* Check for inconsistent use of this name in the class body.
Enums, types and static vars have already been checked. */ Enums, types and static vars have already been checked. */
if (TREE_CODE (x) != TYPE_DECL && TREE_CODE (x) != USING_DECL 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_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
{ {
tree name = DECL_NAME (x); tree name = DECL_NAME (x);
......
...@@ -2458,7 +2458,7 @@ extern void end_tree PROTO((void)); ...@@ -2458,7 +2458,7 @@ extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree)); extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void)); extern void pop_tinst_level PROTO((void));
extern tree most_specialized PROTO((tree, tree, tree)); 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 int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void)); extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree)); extern int is_member_template PROTO((tree));
......
...@@ -3503,13 +3503,24 @@ pushdecl_with_scope (x, level) ...@@ -3503,13 +3503,24 @@ pushdecl_with_scope (x, level)
tree x; tree x;
struct binding_level *level; struct binding_level *level;
{ {
register struct binding_level *b = current_binding_level; register struct binding_level *b;
tree function_decl = current_function_decl; tree function_decl = current_function_decl;
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
current_binding_level = level; if (level->parm_flag == 2)
x = pushdecl (x); {
current_binding_level = b; 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; current_function_decl = function_decl;
return x; return x;
} }
......
...@@ -1386,8 +1386,8 @@ check_member_template (tmpl) ...@@ -1386,8 +1386,8 @@ check_member_template (tmpl)
with member templates. */ with member templates. */
DECL_IGNORED_P (tmpl) = 1; DECL_IGNORED_P (tmpl) = 1;
} }
else if (TREE_CODE (decl) == TYPE_DECL && else if (TREE_CODE (decl) == TYPE_DECL
AGGREGATE_TYPE_P (TREE_TYPE (decl))) && IS_AGGR_TYPE (TREE_TYPE (decl)))
{ {
if (current_function_decl) if (current_function_decl)
/* 14.5.2.2 [temp.mem] /* 14.5.2.2 [temp.mem]
......
...@@ -77,7 +77,7 @@ static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree)); ...@@ -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 tree tsubst_expr_values PROTO((tree, tree));
static int comp_template_args PROTO((tree, tree)); static int comp_template_args PROTO((tree, tree));
static int list_eq 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 coerce_template_parms PROTO((tree, tree, tree, int, int, int));
static tree tsubst_enum PROTO((tree, tree, tree *)); static tree tsubst_enum PROTO((tree, tree, tree *));
static tree add_to_template_args PROTO((tree, tree)); static tree add_to_template_args PROTO((tree, tree));
...@@ -109,12 +109,14 @@ finish_member_template_decl (template_parameters, decl) ...@@ -109,12 +109,14 @@ finish_member_template_decl (template_parameters, decl)
{ {
/* Assume that the class is the only declspec. */ /* Assume that the class is the only declspec. */
decl = TREE_VALUE (decl); 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); tree tmpl = CLASSTYPE_TI_TEMPLATE (decl);
check_member_template (tmpl); check_member_template (tmpl);
return tmpl; return tmpl;
} }
return NULL_TREE;
} }
else if (DECL_TEMPLATE_INFO (decl) && else if (DECL_TEMPLATE_INFO (decl) &&
!DECL_TEMPLATE_SPECIALIZATION (decl)) !DECL_TEMPLATE_SPECIALIZATION (decl))
...@@ -2380,6 +2382,8 @@ lookup_template_class (d1, arglist, in_decl, context) ...@@ -2380,6 +2382,8 @@ lookup_template_class (d1, arglist, in_decl, context)
if (! template) if (! template)
template = IDENTIFIER_CLASS_VALUE (d1); template = IDENTIFIER_CLASS_VALUE (d1);
} }
if (template)
context = DECL_CONTEXT (template);
} }
else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1))) else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
{ {
...@@ -2938,7 +2942,7 @@ instantiate_class_template (type) ...@@ -2938,7 +2942,7 @@ instantiate_class_template (type)
tree type; tree type;
{ {
tree template, template_info, args, pattern, t, *field_chain; tree template, template_info, args, pattern, t, *field_chain;
tree typedecl; tree typedecl, outer_args;
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -2954,14 +2958,15 @@ instantiate_class_template (type) ...@@ -2954,14 +2958,15 @@ instantiate_class_template (type)
if (DECL_TEMPLATE_INFO (template)) 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)) while (DECL_TEMPLATE_INFO (template))
template = DECL_TI_TEMPLATE (template); template = DECL_TI_TEMPLATE (template);
} }
else
outer_args = NULL_TREE;
/* FIXME deal with partial specializations of member templates. */
t = most_specialized_class t = most_specialized_class
(DECL_TEMPLATE_SPECIALIZATIONS (template), args); (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args);
if (t == error_mark_node) if (t == error_mark_node)
{ {
...@@ -2969,7 +2974,8 @@ instantiate_class_template (type) ...@@ -2969,7 +2974,8 @@ instantiate_class_template (type)
cp_error ("ambiguous class template instantiation for `%#T'", type); cp_error ("ambiguous class template instantiation for `%#T'", type);
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t)) 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)); cp_error_at ("%s %+#T", str, TREE_TYPE (t));
str = " "; str = " ";
...@@ -2987,7 +2993,11 @@ instantiate_class_template (type) ...@@ -2987,7 +2993,11 @@ instantiate_class_template (type)
return type; return type;
if (t) 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 (pedantic && uses_template_parms (args))
/* If there are still template parameters amongst the args, then /* If there are still template parameters amongst the args, then
...@@ -3617,7 +3627,7 @@ tsubst (t, args, in_decl) ...@@ -3617,7 +3627,7 @@ tsubst (t, args, in_decl)
if (PRIMARY_TEMPLATE_P (t)) if (PRIMARY_TEMPLATE_P (t))
TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl; 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) if (TREE_CODE (decl) == TYPE_DECL)
return tmpl; return tmpl;
...@@ -5651,12 +5661,14 @@ more_specialized_class (pat1, pat2) ...@@ -5651,12 +5661,14 @@ more_specialized_class (pat1, pat2)
int winner = 0; int winner = 0;
targs = get_class_bindings 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) if (targs)
--winner; --winner;
targs = get_class_bindings 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) if (targs)
++winner; ++winner;
...@@ -5718,12 +5730,18 @@ get_bindings (fn, decl, explicit_args) ...@@ -5718,12 +5730,18 @@ get_bindings (fn, decl, explicit_args)
} }
static tree static tree
get_class_bindings (tparms, parms, args) get_class_bindings (tparms, parms, args, outer_args)
tree tparms, parms, args; tree tparms, parms, args, outer_args;
{ {
int i, dummy, ntparms = TREE_VEC_LENGTH (tparms); int i, dummy, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_temp_vec (ntparms); 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) for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{ {
switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms, switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms,
...@@ -5803,15 +5821,16 @@ most_specialized (fns, decl, explicit_args) ...@@ -5803,15 +5821,16 @@ most_specialized (fns, decl, explicit_args)
SPECS that can produce an instantiation matching ARGS. */ SPECS that can produce an instantiation matching ARGS. */
tree tree
most_specialized_class (specs, mainargs) most_specialized_class (specs, mainargs, outer_args)
tree specs, mainargs; tree specs, mainargs, outer_args;
{ {
tree list = NULL_TREE, t, args, champ; tree list = NULL_TREE, t, args, champ;
int fate; int fate;
for (t = specs; t; t = TREE_CHAIN (t)) 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) if (args)
{ {
list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list); list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
......
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