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>
* pt.c (tsubst, TEMPLATE_DECL): Support member class templates.
......
......@@ -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);
......
......@@ -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));
......
......@@ -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;
}
......
......@@ -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]
......
......@@ -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);
......
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