Commit 98c1c668 by Jason Merrill

class.c (grow_method): Remove check for redeclaration.

	* class.c (grow_method): Remove check for redeclaration.

Fri Sep  5 01:37:17 1997  Mark Mitchell  <mmitchell@usa.net>

	* cp-tree.h (INNERMOST_TEMPLATE_PARMS): New macro.
	(DECL_INNERMOST_TEMPLATE_PARMS): Likewise.
	(PRIMARY_TEMPLATE_P): Use it.
	* call.c (build_overload_call_real): Use it.
	* class.c (instantiate_type): Likewise.
	* decl.c (decls_match): Likewise.
	* method.c (build_overload_identifier): Likewise.
	* pt.c (push_template_decl): Likewise.
	(classtype_mangled_name): Likewise.
	(lookup_template_class): Likewise.

	* cp-tree.h (DECL_NTPARMS): Change name from DECL_NT_PARMS to
	DECL_NTPARMS to conform to usage elsewhere.
	* call.c (add_template_candidate): Likewise.
	* class.c (instantiate_type): Likewise.
	* pt.c (instantiate_template): Likewise.
	(get_bindings): Likewise.

	* class.c (grow_method): Use DECL_FUNCTION_TEMPLATE_P instead of
	is_member_template.

	* pt.c (unify): Undo changes to allow multiple levels of template
	parameters.
	(type_unification): Likewise.
	(fn_type_unification): Likewise.
	(get_class_bindings): Likewise.
	* cp-tree.h (Likewise).

	* decl.c (replace_defarg): Check that the type of the default
	parameter does not invlove a template type before complaining
	about the initialization.

	* error.c (dump_expr): Deal with template constant parameters in
	member templates correctly.

	* pt.c (is_member_template): Deal with class specializations
	correctly.
	(tsubst): Handle "partial instantiation" of member templates
	correctly.

Wed Sep  3 12:30:24 1997  Mark Mitchell  <mmitchell@usa.net>

	* pt.c (type_unification): Change calling squence to allow for
	multiple levels of template parameters.
	(tsubst_expr): Likewise.
	(tsubst): Likewise.
	(tsubst_copy): Likewise.
	(instantiate_template): Likewise.
	(unify): Likewise.
	* call.c (build_overload_call_real): Use it.
	(add_builtin_candidate): Use it.
	(build_new_method_call): Use it.
	* class.c (instantiate_type): Use it.
	* decl.c (grokdeclarator): Use it.
	* decl2.c (finish_file): Use it.
	* method.c (build_overload_identifier): Use it.

	* call.c (add_template_candidate):  Add additional parameter for
	the function return type.  Call fn_type_unification istead of
	type_unification.
	(build_user_type_conversion_1): Handle member templates.
	(build_new_function_call): Likewise.
	(build_new_op): Likewise.
	(build_new_method_call): Likewise.

	* class.c (grow_method): Don't give an error message indicating
 	that two member templates with the same name are ambiguous.
	(finish_struct): Treat member template functions just like member
 	functions.

	* cp-tree.h (check_member_template): Add declaration.
	(begin_member_template_processing): Likewise.
	(end_member_template_processing): Likewise.
	(fn_type_unification): Likewise.
	(is_member_template): Likewise.
	(tsubst): Change prototype.
	(tsubst_expr): Likewise.
	(tsubst_copy): Likewise.
	(instantiate_template): Likewise.
	(get_bindings): Likewise.

	* decl.c (decls_match): Handle multiple levels of template
	parameters.
	(pushdecl): Handle template type params just like other type
	declarations.
	(push_class_level_binding): Return immediately if the
	class_binding_level is NULL.
	(grokfndecl): If check_classfn() returns a member_template, use
	the result of the template, not the template itself.

	* decl2.c (check_member_template): New function.  Check to see
	that the entity declared to be a member template can be one.
	(check_classfn): Allow redeclaration of member template functions
	with different types; the new functions can be specializations or
	explicit instantiations.

	* error.c (dump_decl): Handle multiple levels of template
	parameters.
	(dump_function_decl): Update to handle function	templates.

	* lex.c (do_pending_inlines): Set up template parameter context
	for member templates.
	(process_next_inline): Likewise.

	* method. (build_overload_identifier): Adjust for multiple levels
	of template parameters.

	* parse.y (fn.def2): Add member templates.
	(component_decl_1): Likewise.

	* pt.c (begin_member_template_processing): New function.
	(end_member_template_processing): Likewise.
	(is_member_template): Likewise.
	(fn_type_unification): Likewise.
	(current_template_parms): Return a vector of all the template
	parms, not just the innermost level of parms.
	(push_template_decl): Deal with the possibility of member
	templates.
	(lookup_template_class): Likewise.
	(uses_template_parms): Likewise.
	(tsubst): Modify processing to TEMPLATE_TYPE_PARM and
	TEMPLATE_CONST_PARM to deal with multiple levels of template
	arguments.   Add processing of TEMPLATE_DECL to produce new
	TEMPLATE_DECLs from old ones.
	(do_decl_instantiation): Handle member templates.

	* search.c (lookup_fnfields_1): Handle member template conversion
	operators.

	* tree.c (cp_tree_equal): Check the levels, as well as the
	indices, of TEMPLATE_CONST_PARMs.

	* typeck.c (comptypes): Check the levels, as well as the indices,
	fo TEMPLATE_TYPE_PARMs.
	(build_x_function_call): Treat member templates like member
	functions.

Member templates.

From-SVN: r15130
parent dbfcb4be
Fri Sep 5 17:27:38 1997 Jason Merrill <jason@yorick.cygnus.com>
* class.c (grow_method): Remove check for redeclaration.
Wed Sep 3 12:30:24 1997 Mark Mitchell <mmitchell@usa.net>
* pt.c (type_unification): Change calling squence to allow for
multiple levels of template parameters.
(tsubst_expr): Likewise.
(tsubst): Likewise.
(tsubst_copy): Likewise.
(instantiate_template): Likewise.
(unify): Likewise.
* call.c (build_overload_call_real): Use it.
(add_builtin_candidate): Use it.
(build_new_method_call): Use it.
* class.c (instantiate_type): Use it.
* decl.c (grokdeclarator): Use it.
* decl2.c (finish_file): Use it.
* method.c (build_overload_identifier): Use it.
* call.c (add_template_candidate): Add additional parameter for
the function return type. Call fn_type_unification istead of
type_unification.
(build_user_type_conversion_1): Handle member templates.
(build_new_function_call): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
* class.c (grow_method): Don't give an error message indicating
that two member templates with the same name are ambiguous.
(finish_struct): Treat member template functions just like member
functions.
* cp-tree.h (check_member_template): Add declaration.
(begin_member_template_processing): Likewise.
(end_member_template_processing): Likewise.
(fn_type_unification): Likewise.
(is_member_template): Likewise.
(tsubst): Change prototype.
(tsubst_expr): Likewise.
(tsubst_copy): Likewise.
(instantiate_template): Likewise.
(get_bindings): Likewise.
* decl.c (decls_match): Handle multiple levels of template
parameters.
(pushdecl): Handle template type params just like other type
declarations.
(push_class_level_binding): Return immediately if the
class_binding_level is NULL.
(grokfndecl): If check_classfn() returns a member_template, use
the result of the template, not the template itself.
* decl2.c (check_member_template): New function. Check to see
that the entity declared to be a member template can be one.
(check_classfn): Allow redeclaration of member template functions
with different types; the new functions can be specializations or
explicit instantiations.
* error.c (dump_decl): Handle multiple levels of template
parameters.
(dump_function_decl): Update to handle function templates.
* lex.c (do_pending_inlines): Set up template parameter context
for member templates.
(process_next_inline): Likewise.
* method. (build_overload_identifier): Adjust for multiple levels
of template parameters.
* parse.y (fn.def2): Add member templates.
(component_decl_1): Likewise.
* pt.c (begin_member_template_processing): New function.
(end_member_template_processing): Likewise.
(is_member_template): Likewise.
(fn_type_unification): Likewise.
(current_template_parms): Return a vector of all the template
parms, not just the innermost level of parms.
(push_template_decl): Deal with the possibility of member
templates.
(lookup_template_class): Likewise.
(uses_template_parms): Likewise.
(tsubst): Modify processing to TEMPLATE_TYPE_PARM and
TEMPLATE_CONST_PARM to deal with multiple levels of template
arguments. Add processing of TEMPLATE_DECL to produce new
TEMPLATE_DECLs from old ones.
(do_decl_instantiation): Handle member templates.
* search.c (lookup_fnfields_1): Handle member template conversion
operators.
* tree.c (cp_tree_equal): Check the levels, as well as the
indices, of TEMPLATE_CONST_PARMs.
* typeck.c (comptypes): Check the levels, as well as the indices,
fo TEMPLATE_TYPE_PARMs.
(build_x_function_call): Treat member templates like member
functions.
Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com> Wed Sep 3 11:09:25 1997 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (c_expand_return): Always convert_for_initialization * typeck.c (c_expand_return): Always convert_for_initialization
......
...@@ -77,7 +77,7 @@ static tree build_this PROTO((tree)); ...@@ -77,7 +77,7 @@ static tree build_this PROTO((tree));
static struct z_candidate * splice_viable PROTO((struct z_candidate *)); static struct z_candidate * splice_viable PROTO((struct z_candidate *));
static int any_viable PROTO((struct z_candidate *)); static int any_viable PROTO((struct z_candidate *));
static struct z_candidate * add_template_candidate static struct z_candidate * add_template_candidate
PROTO((struct z_candidate *, tree, tree, int)); PROTO((struct z_candidate *, tree, tree, tree, int));
static struct z_candidate * add_builtin_candidates static struct z_candidate * add_builtin_candidates
PROTO((struct z_candidate *, enum tree_code, enum tree_code, PROTO((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int)); tree, tree *, int));
...@@ -2838,11 +2838,12 @@ build_overload_call_real (fnname, parms, flags, final_cp, require_complete) ...@@ -2838,11 +2838,12 @@ build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
} }
if (TREE_CODE (function) == TEMPLATE_DECL) if (TREE_CODE (function) == TEMPLATE_DECL)
{ {
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function)); int ntparms = DECL_NTPARMS (function);
tree *targs = (tree *) alloca (sizeof (tree) * ntparms); tree targs = make_tree_vec (ntparms);
int i; int i;
i = type_unification (DECL_TEMPLATE_PARMS (function), targs, i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
&TREE_VEC_ELT (targs, 0),
TYPE_ARG_TYPES (TREE_TYPE (function)), TYPE_ARG_TYPES (TREE_TYPE (function)),
parms, &template_cost, 0, 0); parms, &template_cost, 0, 0);
if (i == 0) if (i == 0)
...@@ -4144,20 +4145,19 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags) ...@@ -4144,20 +4145,19 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
} }
static struct z_candidate * static struct z_candidate *
add_template_candidate (candidates, tmpl, arglist, flags) add_template_candidate (candidates, tmpl, arglist, return_type, flags)
struct z_candidate *candidates; struct z_candidate *candidates;
tree tmpl, arglist; tree tmpl, arglist, return_type;
int flags; int flags;
{ {
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); int ntparms = DECL_NTPARMS (tmpl);
tree *targs = (tree *) alloca (sizeof (tree) * ntparms); tree targs = make_tree_vec (ntparms);
struct z_candidate *cand; struct z_candidate *cand;
int i, dummy = 0; int i;
tree fn; tree fn;
i = type_unification (DECL_TEMPLATE_PARMS (tmpl), targs, i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
TYPE_ARG_TYPES (TREE_TYPE (tmpl)),
arglist, &dummy, 0, 0);
if (i != 0) if (i != 0)
return candidates; return candidates;
...@@ -4253,6 +4253,7 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -4253,6 +4253,7 @@ build_user_type_conversion_1 (totype, expr, flags)
tree fromtype = TREE_TYPE (expr); tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, *p; tree ctors = NULL_TREE, convs = NULL_TREE, *p;
tree args; tree args;
tree templates = NULL_TREE;
if (IS_AGGR_TYPE (totype)) if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
...@@ -4279,9 +4280,22 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -4279,9 +4280,22 @@ build_user_type_conversion_1 (totype, expr, flags)
if (DECL_NONCONVERTING_P (ctors)) if (DECL_NONCONVERTING_P (ctors))
continue; continue;
candidates = add_function_candidate (candidates, ctors, args, flags); if (TREE_CODE (ctors) == TEMPLATE_DECL)
candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); {
candidates->basetype_path = TYPE_BINFO (totype); templates = decl_tree_cons (NULL_TREE, ctors, templates);
candidates =
add_template_candidate (candidates, ctors,
args, NULL_TREE, flags);
}
else
candidates = add_function_candidate (candidates, ctors,
args, flags);
if (candidates)
{
candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
candidates->basetype_path = TYPE_BINFO (totype);
}
} }
if (convs) if (convs)
...@@ -4308,11 +4322,24 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -4308,11 +4322,24 @@ build_user_type_conversion_1 (totype, expr, flags)
else if (ics) else if (ics)
for (; fn; fn = DECL_CHAIN (fn)) for (; fn; fn = DECL_CHAIN (fn))
{ {
candidates = add_function_candidate (candidates, fn, args, flags); if (TREE_CODE (fn) == TEMPLATE_DECL)
candidates->second_conv = ics; {
candidates->basetype_path = TREE_PURPOSE (convs); templates = decl_tree_cons (NULL_TREE, fn, templates);
if (candidates->viable == 1 && ICS_BAD_FLAG (ics)) candidates =
candidates->viable = -1; add_template_candidate (candidates, fn, args,
totype, flags);
}
else
candidates = add_function_candidate (candidates, fn,
args, flags);
if (candidates)
{
candidates->second_conv = ics;
candidates->basetype_path = TREE_PURPOSE (convs);
if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
candidates->viable = -1;
}
} }
} }
...@@ -4354,6 +4381,13 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -4354,6 +4381,13 @@ build_user_type_conversion_1 (totype, expr, flags)
for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
p = &(TREE_OPERAND (*p, 0)); p = &(TREE_OPERAND (*p, 0));
/* Pedantically, normal function declarations are never considered
to refer to template instantiations, but we won't implement that
until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
&& TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
add_maybe_template (cand->fn, templates);
*p = build *p = build
(USER_CONV, (USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn) (DECL_CONSTRUCTOR_P (cand->fn)
...@@ -4427,7 +4461,7 @@ build_new_function_call (fn, args, obj) ...@@ -4427,7 +4461,7 @@ build_new_function_call (fn, args, obj)
{ {
templates = decl_tree_cons (NULL_TREE, t, templates); templates = decl_tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate candidates = add_template_candidate
(candidates, t, args, LOOKUP_NORMAL); (candidates, t, args, NULL_TREE, LOOKUP_NORMAL);
} }
else else
candidates = add_function_candidate candidates = add_function_candidate
...@@ -4713,7 +4747,7 @@ build_new_op (code, flags, arg1, arg2, arg3) ...@@ -4713,7 +4747,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
{ {
templates = decl_tree_cons (NULL_TREE, fns, templates); templates = decl_tree_cons (NULL_TREE, fns, templates);
candidates = add_template_candidate candidates = add_template_candidate
(candidates, fns, arglist, flags); (candidates, fns, arglist, TREE_TYPE (fnname), flags);
} }
else else
candidates = add_function_candidate (candidates, fns, arglist, flags); candidates = add_function_candidate (candidates, fns, arglist, flags);
...@@ -4730,13 +4764,27 @@ build_new_op (code, flags, arg1, arg2, arg3) ...@@ -4730,13 +4764,27 @@ build_new_op (code, flags, arg1, arg2, arg3)
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist)); mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
for (; fn; fn = DECL_CHAIN (fn)) for (; fn; fn = DECL_CHAIN (fn))
{ {
tree this_arglist;
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
candidates = add_function_candidate this_arglist = mem_arglist;
(candidates, fn, mem_arglist, flags);
else else
candidates = add_function_candidate (candidates, fn, arglist, flags); this_arglist = arglist;
candidates->basetype_path = TREE_PURPOSE (fns); if (TREE_CODE (fn) == TEMPLATE_DECL)
{
/* A member template. */
templates = decl_tree_cons (NULL_TREE, fn, templates);
candidates = add_template_candidate
(candidates, fn, this_arglist,
TREE_TYPE (fnname), LOOKUP_NORMAL);
}
else
candidates = add_function_candidate
(candidates, fn, this_arglist, flags);
if (candidates)
candidates->basetype_path = TREE_PURPOSE (fns);
} }
} }
...@@ -4827,9 +4875,9 @@ build_new_op (code, flags, arg1, arg2, arg3) ...@@ -4827,9 +4875,9 @@ build_new_op (code, flags, arg1, arg2, arg3)
if (DECL_FUNCTION_MEMBER_P (cand->fn)) if (DECL_FUNCTION_MEMBER_P (cand->fn))
enforce_access (cand->basetype_path, cand->fn); enforce_access (cand->basetype_path, cand->fn);
/* Pedantically, it is ill-formed to define a function that could /* Pedantically, normal function declarations are never considered
also be a template instantiation, but we won't implement that to refer to template instantiations, but we won't implement that
until things settle down. */ until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn) if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
&& TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE) && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
add_maybe_template (cand->fn, templates); add_maybe_template (cand->fn, templates);
...@@ -5188,8 +5236,7 @@ build_over_call (fn, convs, args, flags) ...@@ -5188,8 +5236,7 @@ build_over_call (fn, convs, args, flags)
if (DECL_TEMPLATE_INFO (fn)) if (DECL_TEMPLATE_INFO (fn))
/* This came from a template. Instantiate the default arg here, /* This came from a template. Instantiate the default arg here,
not in tsubst. */ not in tsubst. */
arg = tsubst_expr (arg, arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
&TREE_VEC_ELT (DECL_TI_ARGS (fn), 0),
TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE); TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE);
converted_args = tree_cons converted_args = tree_cons
(NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg), (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
...@@ -5332,6 +5379,7 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -5332,6 +5379,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
tree basetype, mem_args, fns, instance_ptr; tree basetype, mem_args, fns, instance_ptr;
tree pretty_name; tree pretty_name;
tree user_args = args; tree user_args = args;
tree templates = NULL_TREE;
/* If there is an extra argument for controlling virtual bases, /* If there is an extra argument for controlling virtual bases,
remove it for error reporting. */ remove it for error reporting. */
...@@ -5412,17 +5460,34 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -5412,17 +5460,34 @@ build_new_method_call (instance, name, args, basetype_path, flags)
mem_args = tree_cons (NULL_TREE, instance_ptr, args); mem_args = tree_cons (NULL_TREE, instance_ptr, args);
for (; t; t = DECL_CHAIN (t)) for (; t; t = DECL_CHAIN (t))
{ {
tree this_arglist;
/* We can end up here for copy-init of same or base class. */ /* We can end up here for copy-init of same or base class. */
if (name == ctor_identifier if (name == ctor_identifier
&& (flags & LOOKUP_ONLYCONVERTING) && (flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (t)) && DECL_NONCONVERTING_P (t))
continue; continue;
if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE) if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
candidates = add_function_candidate this_arglist = mem_args;
(candidates, t, mem_args, flags);
else else
candidates = add_function_candidate (candidates, t, args, flags); this_arglist = args;
candidates->basetype_path = TREE_PURPOSE (fns);
if (TREE_CODE (t) == TEMPLATE_DECL)
{
/* A member template. */
templates = decl_tree_cons (NULL_TREE, t, templates);
candidates =
add_template_candidate (candidates, t,
this_arglist,
TREE_TYPE (name),
LOOKUP_NORMAL);
}
else
candidates = add_function_candidate (candidates, t,
this_arglist, flags);
if (candidates)
candidates->basetype_path = TREE_PURPOSE (fns);
} }
} }
...@@ -5464,6 +5529,12 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -5464,6 +5529,12 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|| resolves_to_fixed_type_p (instance, 0))) || resolves_to_fixed_type_p (instance, 0)))
flags |= LOOKUP_NONVIRTUAL; flags |= LOOKUP_NONVIRTUAL;
/* Pedantically, normal function declarations are never considered
to refer to template instantiations, but we won't implement that
until we implement full template instantiation syntax. */
if (templates && ! cand->template && ! DECL_INITIAL (cand->fn))
add_maybe_template (cand->fn, templates);
return build_over_call return build_over_call
(cand->fn, cand->convs, (cand->fn, cand->convs,
TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args, TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
......
...@@ -1872,33 +1872,10 @@ grow_method (fndecl, method_vec_ptr) ...@@ -1872,33 +1872,10 @@ grow_method (fndecl, method_vec_ptr)
if (testp < (tree *) obstack_next_free (&class_obstack)) if (testp < (tree *) obstack_next_free (&class_obstack))
{ {
tree x, prev_x; tree *p;
for (p = testp; *p; )
for (x = *testp; x; x = DECL_CHAIN (x)) p = &DECL_CHAIN (*p);
{ *p = fndecl;
if (DECL_NAME (fndecl) == ansi_opname[(int) DELETE_EXPR]
|| DECL_NAME (fndecl) == ansi_opname[(int) VEC_DELETE_EXPR])
{
/* ANSI C++ June 5 1992 WP 12.5.5.1 */
cp_error_at ("`%D' overloaded", fndecl);
cp_error_at ("previous declaration as `%D' here", x);
}
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (x))
{
/* Friend-friend ambiguities are warned about outside
this loop. */
cp_error_at ("ambiguous method `%#D' in structure", fndecl);
break;
}
prev_x = x;
}
if (x == 0)
{
if (*testp)
DECL_CHAIN (prev_x) = fndecl;
else
*testp = fndecl;
}
} }
else else
{ {
...@@ -4384,7 +4361,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4384,7 +4361,8 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
} }
} }
if (TREE_CODE (x) == FUNCTION_DECL) if (TREE_CODE (x) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (x))
{ {
DECL_CLASS_CONTEXT (x) = t; DECL_CLASS_CONTEXT (x) = t;
if (last_x) if (last_x)
...@@ -5062,12 +5040,13 @@ instantiate_type (lhstype, rhs, complain) ...@@ -5062,12 +5040,13 @@ instantiate_type (lhstype, rhs, complain)
for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem)) for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
if (TREE_CODE (elem) == TEMPLATE_DECL) if (TREE_CODE (elem) == TEMPLATE_DECL)
{ {
int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem)); int n = DECL_NTPARMS (elem);
tree *t = (tree *) alloca (sizeof (tree) * n); tree t = make_tree_vec (n);
int i, d = 0; int i, d = 0;
i = type_unification (DECL_TEMPLATE_PARMS (elem), t, i = type_unification
TYPE_ARG_TYPES (TREE_TYPE (elem)), (DECL_INNERMOST_TEMPLATE_PARMS (elem),
TYPE_ARG_TYPES (lhstype), &d, 0, 1); &TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), &d, 0, 1);
if (i == 0) if (i == 0)
{ {
if (save_elem) if (save_elem)
......
...@@ -91,7 +91,7 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", "t", 0) ...@@ -91,7 +91,7 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", "t", 0)
/* Index into a template parameter list. This parameter must not be a /* Index into a template parameter list. This parameter must not be a
type. */ type. */
DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 2) DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", "c", 3)
/* A thunk is a stub function. /* A thunk is a stub function.
......
...@@ -1091,6 +1091,7 @@ struct lang_decl ...@@ -1091,6 +1091,7 @@ struct lang_decl
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE)) #define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE)) #define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE)) #define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE) #define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE) #define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
...@@ -1334,6 +1335,10 @@ extern int flag_new_for_scope; ...@@ -1334,6 +1335,10 @@ extern int flag_new_for_scope;
/* Accessor macros for C++ template decl nodes. */ /* Accessor macros for C++ template decl nodes. */
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE) #define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
#define DECL_NTPARMS(NODE) \
TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE))
/* For class templates. */ /* For class templates. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE) #define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */ /* For function, method, class-data templates. */
...@@ -1346,7 +1351,7 @@ extern int flag_new_for_scope; ...@@ -1346,7 +1351,7 @@ extern int flag_new_for_scope;
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL) && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
#define PRIMARY_TEMPLATE_P(NODE) \ #define PRIMARY_TEMPLATE_P(NODE) \
(TREE_TYPE (DECL_TEMPLATE_PARMS (NODE)) == (NODE)) (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (NODE))
#define CLASSTYPE_TEMPLATE_LEVEL(NODE) \ #define CLASSTYPE_TEMPLATE_LEVEL(NODE) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE)))) (TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
...@@ -2112,6 +2117,7 @@ extern tree grok_alignof PROTO((tree)); ...@@ -2112,6 +2117,7 @@ extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree)); extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int)); extern tree delete_sanity PROTO((tree, tree, int, int));
extern tree check_classfn PROTO((tree, tree)); extern tree check_classfn PROTO((tree, tree));
extern void check_member_template PROTO((tree));
extern tree grokfield PROTO((tree, tree, tree, tree, tree)); extern tree grokfield PROTO((tree, tree, tree, tree, tree));
extern tree grokbitfield PROTO((tree, tree, tree)); extern tree grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree)); extern tree groktypefield PROTO((tree, tree));
...@@ -2299,10 +2305,12 @@ extern void synthesize_method PROTO((tree)); ...@@ -2299,10 +2305,12 @@ extern void synthesize_method PROTO((tree));
extern tree get_id_2 PROTO((char *, tree)); extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */ /* in pt.c */
extern tree tsubst PROTO ((tree, tree*, int, tree)); extern tree tsubst PROTO ((tree, tree, int, tree));
extern tree tsubst_expr PROTO ((tree, tree*, int, tree)); extern tree tsubst_expr PROTO ((tree, tree, int, tree));
extern tree tsubst_copy PROTO ((tree, tree*, int, tree)); extern tree tsubst_copy PROTO ((tree, tree, int, tree));
extern tree tsubst_chain PROTO((tree, tree)); extern tree tsubst_chain PROTO((tree, tree));
extern void begin_member_template_processing PROTO((tree));
extern void end_member_template_processing PROTO((void));
extern void begin_template_parm_list PROTO((void)); extern void begin_template_parm_list PROTO((void));
extern tree process_template_parm PROTO((tree, tree)); extern tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree)); extern tree end_template_parm_list PROTO((tree));
...@@ -2312,8 +2320,9 @@ extern void push_template_decl PROTO((tree)); ...@@ -2312,8 +2320,9 @@ extern void push_template_decl PROTO((tree));
extern tree lookup_template_class PROTO((tree, tree, tree)); extern tree lookup_template_class PROTO((tree, tree, tree));
extern int uses_template_parms PROTO((tree)); extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree)); extern tree instantiate_class_template PROTO((tree));
extern tree instantiate_template PROTO((tree, tree *)); extern tree instantiate_template PROTO((tree, tree));
extern void overload_template_name PROTO((tree)); extern void overload_template_name PROTO((tree));
extern int fn_type_unification PROTO((tree, tree, tree, tree, int));
extern int type_unification PROTO((tree, tree *, tree, tree, int *, int, int)); extern int type_unification PROTO((tree, tree *, tree, tree, int *, int, int));
struct tinst_level *tinst_for_decl PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int)); extern void mark_decl_instantiated PROTO((tree, int));
...@@ -2324,7 +2333,7 @@ extern void do_type_instantiation PROTO((tree, tree)); ...@@ -2324,7 +2333,7 @@ extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree)); extern tree instantiate_decl PROTO((tree));
extern tree lookup_nested_type_by_name PROTO((tree, tree)); extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void)); extern tree do_poplevel PROTO((void));
extern tree *get_bindings PROTO((tree, tree)); extern tree get_bindings PROTO((tree, tree));
/* CONT ... */ /* CONT ... */
extern void add_tree PROTO((tree)); extern void add_tree PROTO((tree));
extern void add_maybe_template PROTO((tree, tree)); extern void add_maybe_template PROTO((tree, tree));
...@@ -2333,6 +2342,7 @@ extern tree most_specialized PROTO((tree, tree)); ...@@ -2333,6 +2342,7 @@ extern tree most_specialized PROTO((tree, tree));
extern tree most_specialized_class PROTO((tree, tree)); extern tree most_specialized_class PROTO((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));
/* in repo.c */ /* in repo.c */
extern void repo_template_used PROTO((tree)); extern void repo_template_used PROTO((tree));
......
...@@ -2306,23 +2306,40 @@ decls_match (newdecl, olddecl) ...@@ -2306,23 +2306,40 @@ decls_match (newdecl, olddecl)
{ {
tree newargs = DECL_TEMPLATE_PARMS (newdecl); tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl); tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
int i, len = TREE_VEC_LENGTH (newargs); int i;
if (TREE_VEC_LENGTH (oldargs) != len) /* Run through all the levels of template parmaters, checking
return 0; that they match. */
while (newargs && oldargs)
for (i = 0; i < len; i++)
{ {
tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i)); int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i));
if (TREE_CODE (newarg) != TREE_CODE (oldarg)) if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
return 0;
else if (TREE_CODE (newarg) == TYPE_DECL)
/* continue */;
else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0; return 0;
for (i = 0; i < len; i++)
{
tree newarg =
TREE_VALUE (TREE_VEC_ELT
(INNERMOST_TEMPLATE_PARMS (newargs), i));
tree oldarg =
TREE_VALUE (TREE_VEC_ELT
(INNERMOST_TEMPLATE_PARMS (oldargs), i));
if (TREE_CODE (newarg) != TREE_CODE (oldarg))
return 0;
else if (TREE_CODE (newarg) == TYPE_DECL)
/* continue */;
else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0;
}
newargs = TREE_CHAIN (newargs);
oldargs = TREE_CHAIN (oldargs);
} }
if ((newargs == NULL_TREE) != (oldargs == NULL_TREE))
/* One declaration has more levels that the other. */
return 0;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL) if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1; types_match = 1;
else else
...@@ -3003,7 +3020,7 @@ pushdecl (x) ...@@ -3003,7 +3020,7 @@ pushdecl (x)
/* Type are looked up using the DECL_NAME, as that is what the rest of the /* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */ compiler wants to use. */
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
|| TREE_CODE (x) == NAMESPACE_DECL) || TREE_CODE (x) == NAMESPACE_DECL || TREE_CODE (x) == TEMPLATE_TYPE_PARM)
name = DECL_NAME (x); name = DECL_NAME (x);
if (name) if (name)
...@@ -3493,6 +3510,11 @@ push_class_level_binding (name, x) ...@@ -3493,6 +3510,11 @@ push_class_level_binding (name, x)
tree name; tree name;
tree x; tree x;
{ {
/* The class_binding_level will be NULL if x is a template
parameter name in a member template. */
if (!class_binding_level)
return;
if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x) if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& purpose_member (name, class_binding_level->class_shadowed)) && purpose_member (name, class_binding_level->class_shadowed))
return; return;
...@@ -7232,6 +7254,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -7232,6 +7254,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (check) if (check)
{ {
tmp = check_classfn (ctype, decl); tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT(tmp);
if (tmp && DECL_ARTIFICIAL (tmp)) if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp); cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp)) if (tmp && duplicate_decls (decl, tmp))
...@@ -7270,6 +7296,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals, ...@@ -7270,6 +7296,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (ctype != NULL_TREE && check) if (ctype != NULL_TREE && check)
{ {
tmp = check_classfn (ctype, decl); tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT(tmp);
if (tmp && DECL_STATIC_FUNCTION_P (tmp) if (tmp && DECL_STATIC_FUNCTION_P (tmp)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{ {
...@@ -8934,8 +8964,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -8934,8 +8964,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& uses_template_parms (current_class_type)) && uses_template_parms (current_class_type))
{ {
tree args = current_template_args (); tree args = current_template_args ();
type = tsubst (type, &TREE_VEC_ELT (args, 0), type = tsubst (type, args,
TREE_VEC_LENGTH (args), NULL_TREE); TREE_VEC_LENGTH (TREE_VEC_ELT
(args, 0)),
NULL_TREE);
} }
/* This pop_nested_class corresponds to the /* This pop_nested_class corresponds to the
...@@ -10038,7 +10070,7 @@ void ...@@ -10038,7 +10070,7 @@ void
replace_defarg (arg, init) replace_defarg (arg, init)
tree arg, init; tree arg, init;
{ {
if (! processing_template_decl if (! processing_template_decl && ! uses_template_parms (TREE_VALUE (arg))
&& ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init)) && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
cp_pedwarn ("invalid type `%T' for default argument to `%T'", cp_pedwarn ("invalid type `%T' for default argument to `%T'",
TREE_TYPE (init), TREE_VALUE (arg)); TREE_TYPE (init), TREE_VALUE (arg));
......
...@@ -1282,6 +1282,59 @@ delete_sanity (exp, size, doing_vec, use_global_delete) ...@@ -1282,6 +1282,59 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
} }
} }
/* Report an error if the indicated template declaration is not the
sort of thing that should be a member template. */
void
check_member_template (tmpl)
tree tmpl;
{
tree decl;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
decl = DECL_TEMPLATE_RESULT (tmpl);
if (TREE_CODE (decl) == FUNCTION_DECL)
{
if (current_function_decl)
/* 14.5.2.2 [temp.mem]
A local class shall not have member templates. */
cp_error ("declaration of of member template `%#D' in local class",
decl);
if (DECL_VIRTUAL_P (decl))
{
/* 14.5.2.3 [temp.mem]
A member function template shall not be virtual. */
cp_error
("invalid use of `virtual' in template declaration of `%#D'",
decl);
DECL_VIRTUAL_P (decl) = 0;
}
/* The debug-information generating code doesn't know what to do
with member templates. */
DECL_IGNORED_P (tmpl) = 1;
}
else if (TREE_CODE (decl) == TYPE_DECL &&
AGGREGATE_TYPE_P (TREE_TYPE (decl)))
{
if (current_function_decl)
/* 14.5.2.2 [temp.mem]
A local class shall not have member templates. */
cp_error ("declaration of of member template `%#D' in local class",
decl);
/* We don't handle member template classes yet. */
sorry ("member templates classes");
}
else
cp_error ("template declaration of `%#D'", decl);
}
/* Sanity check: report error if this function FUNCTION is not /* Sanity check: report error if this function FUNCTION is not
really a member of the class (CTYPE) it is supposed to belong to. really a member of the class (CTYPE) it is supposed to belong to.
CNAME is the same here as it is for grokclassfn above. */ CNAME is the same here as it is for grokclassfn above. */
...@@ -1295,6 +1348,7 @@ check_classfn (ctype, function) ...@@ -1295,6 +1348,7 @@ check_classfn (ctype, function)
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype)); tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0; tree *methods = 0;
tree *end = 0; tree *end = 0;
tree templates = NULL_TREE;
if (method_vec != 0) if (method_vec != 0)
{ {
...@@ -1311,6 +1365,7 @@ check_classfn (ctype, function) ...@@ -1311,6 +1365,7 @@ check_classfn (ctype, function)
while (++methods != end) while (++methods != end)
{ {
fndecl = *methods;
if (fn_name == DECL_NAME (*methods)) if (fn_name == DECL_NAME (*methods))
{ {
got_it: got_it:
...@@ -1342,14 +1397,39 @@ check_classfn (ctype, function) ...@@ -1342,14 +1397,39 @@ check_classfn (ctype, function)
TREE_TYPE (TREE_TYPE (fndecl)), 1) TREE_TYPE (TREE_TYPE (fndecl)), 1)
&& compparms (p1, p2, 3)) && compparms (p1, p2, 3))
return fndecl; return fndecl;
if (is_member_template (fndecl))
/* This function might be an instantiation
or specialization of fndecl. */
templates =
tree_cons (NULL_TREE, fndecl, templates);
} }
#endif #endif
fndecl = DECL_CHAIN (fndecl); fndecl = DECL_CHAIN (fndecl);
} }
break; /* loser */ break; /* loser */
} }
} else if (TREE_CODE (fndecl) == TEMPLATE_DECL
} && IDENTIFIER_TYPENAME_P (DECL_NAME (fndecl))
&& IDENTIFIER_TYPENAME_P (fn_name))
/* The method in the class is a member template
conversion operator. We are declaring another
conversion operator. It is possible that even though
the names don't match, there is some specialization
occurring. */
templates =
tree_cons (NULL_TREE, fndecl, templates);
}
}
if (templates)
/* This function might be an instantiation or a specialization.
We should verify that this is possible. If it is, we must
somehow add the new declaration to the method vector for the
class. Perhaps we should use add_method? For now, we simply
return NULL_TREE, which lets the caller know that this
function is new, but we don't print an error message. */
return NULL_TREE;
if (methods != end) if (methods != end)
{ {
...@@ -2792,7 +2872,7 @@ finish_file () ...@@ -2792,7 +2872,7 @@ finish_file ()
for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname)) for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
{ {
tree *args, fn, decl = TREE_VALUE (fnname); tree args, fn, decl = TREE_VALUE (fnname);
if (DECL_INITIAL (decl)) if (DECL_INITIAL (decl))
continue; continue;
...@@ -2800,7 +2880,6 @@ finish_file () ...@@ -2800,7 +2880,6 @@ finish_file ()
fn = TREE_PURPOSE (fnname); fn = TREE_PURPOSE (fnname);
args = get_bindings (fn, decl); args = get_bindings (fn, decl);
fn = instantiate_template (fn, args); fn = instantiate_template (fn, args);
free (args);
instantiate_decl (fn); instantiate_decl (fn);
} }
......
...@@ -722,33 +722,42 @@ dump_decl (t, v) ...@@ -722,33 +722,42 @@ dump_decl (t, v)
case TEMPLATE_DECL: case TEMPLATE_DECL:
{ {
tree args = DECL_TEMPLATE_PARMS (t); tree orig_args = DECL_TEMPLATE_PARMS (t);
int i, len = args ? TREE_VEC_LENGTH (args) : 0; tree args;
OB_PUTS ("template <"); int i;
for (i = 0; i < len; i++) for (args = orig_args = nreverse (orig_args);
args;
args = TREE_CHAIN (args))
{ {
tree arg = TREE_VEC_ELT (args, i); int len = TREE_VEC_LENGTH (TREE_VALUE (args));
tree defval = TREE_PURPOSE (arg);
arg = TREE_VALUE (arg);
if (TREE_CODE (arg) == TYPE_DECL)
{
OB_PUTS ("class ");
OB_PUTID (DECL_NAME (arg));
}
else
dump_decl (arg, 1);
if (defval) OB_PUTS ("template <");
for (i = 0; i < len; i++)
{ {
OB_PUTS (" = "); tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
dump_decl (defval, 1); tree defval = TREE_PURPOSE (arg);
} arg = TREE_VALUE (arg);
if (TREE_CODE (arg) == TYPE_DECL)
{
OB_PUTS ("class ");
OB_PUTID (DECL_NAME (arg));
}
else
dump_decl (arg, 1);
if (defval)
{
OB_PUTS (" = ");
dump_decl (defval, 1);
}
OB_PUTC2 (',', ' '); OB_PUTC2 (',', ' ');
}
if (len != 0)
OB_UNPUT (2);
OB_PUTC2 ('>', ' ');
} }
if (len != 0) nreverse(orig_args);
OB_UNPUT (2);
OB_PUTC2 ('>', ' ');
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL) if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
dump_type (TREE_TYPE (t), v); dump_type (TREE_TYPE (t), v);
...@@ -801,11 +810,18 @@ dump_function_decl (t, v) ...@@ -801,11 +810,18 @@ dump_function_decl (t, v)
tree t; tree t;
int v; int v;
{ {
tree name = DECL_ASSEMBLER_NAME (t); tree name;
tree fntype = TREE_TYPE (t); tree fntype;
tree parmtypes = TYPE_ARG_TYPES (fntype); tree parmtypes;
tree cname = NULL_TREE; tree cname = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_DECL)
t = DECL_TEMPLATE_RESULT (t);
name = DECL_ASSEMBLER_NAME (t);
fntype = TREE_TYPE (t);
parmtypes = TYPE_ARG_TYPES (fntype);
/* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */ /* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT. */
if (DECL_CONTEXT (t)) if (DECL_CONTEXT (t))
cname = DECL_CLASS_CONTEXT (t); cname = DECL_CLASS_CONTEXT (t);
...@@ -1349,8 +1365,17 @@ dump_expr (t, nop) ...@@ -1349,8 +1365,17 @@ dump_expr (t, nop)
case TEMPLATE_CONST_PARM: case TEMPLATE_CONST_PARM:
if (current_template_parms) if (current_template_parms)
{ {
tree r = TREE_VEC_ELT (TREE_VALUE (current_template_parms), int i;
TEMPLATE_CONST_IDX (t)); tree parms;
tree r;
for (parms = current_template_parms;
TREE_CHAIN (parms);
parms = TREE_CHAIN (parms))
;
r = TREE_VEC_ELT (TREE_VALUE (parms),
TEMPLATE_CONST_IDX (t));
dump_decl (TREE_VALUE (r), -1); dump_decl (TREE_VALUE (r), -1);
} }
else else
......
...@@ -1190,6 +1190,8 @@ do_pending_inlines () ...@@ -1190,6 +1190,8 @@ do_pending_inlines ()
context = hack_decl_function_context (t->fndecl); context = hack_decl_function_context (t->fndecl);
if (context) if (context)
push_cp_function_context (context); push_cp_function_context (context);
if (is_member_template (t->fndecl))
begin_member_template_processing (DECL_TI_ARGS (t->fndecl));
if (t->len > 0) if (t->len > 0)
{ {
feed_input (t->buf, t->len); feed_input (t->buf, t->len);
...@@ -1226,7 +1228,9 @@ process_next_inline (t) ...@@ -1226,7 +1228,9 @@ process_next_inline (t)
{ {
tree context; tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t); struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl); context = hack_decl_function_context (i->fndecl);
if (is_member_template (i->fndecl))
end_member_template_processing ();
if (context) if (context)
pop_cp_function_context (context); pop_cp_function_context (context);
i = i->next; i = i->next;
...@@ -1249,6 +1253,8 @@ process_next_inline (t) ...@@ -1249,6 +1253,8 @@ process_next_inline (t)
context = hack_decl_function_context (i->fndecl); context = hack_decl_function_context (i->fndecl);
if (context) if (context)
push_cp_function_context (context); push_cp_function_context (context);
if (is_member_template (i->fndecl))
begin_member_template_processing (DECL_TI_ARGS (i->fndecl));
feed_input (i->buf, i->len); feed_input (i->buf, i->len);
lineno = i->lineno; lineno = i->lineno;
input_filename = i->filename; input_filename = i->filename;
......
...@@ -648,7 +648,7 @@ build_overload_identifier (name) ...@@ -648,7 +648,7 @@ build_overload_identifier (name)
arglist = TREE_VALUE (template); arglist = TREE_VALUE (template);
template = TREE_PURPOSE (template); template = TREE_PURPOSE (template);
tname = DECL_NAME (template); tname = DECL_NAME (template);
parmlist = DECL_ARGUMENTS (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
nparms = TREE_VEC_LENGTH (parmlist); nparms = TREE_VEC_LENGTH (parmlist);
OB_PUTC ('t'); OB_PUTC ('t');
icat (IDENTIFIER_LENGTH (tname)); icat (IDENTIFIER_LENGTH (tname));
...@@ -666,7 +666,7 @@ build_overload_identifier (name) ...@@ -666,7 +666,7 @@ build_overload_identifier (name)
} }
else else
{ {
parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0), parm = tsubst (parm, arglist,
TREE_VEC_LENGTH (arglist), NULL_TREE); TREE_VEC_LENGTH (arglist), NULL_TREE);
/* It's a PARM_DECL. */ /* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0); build_overload_name (TREE_TYPE (parm), 0, 0);
......
...@@ -699,6 +699,22 @@ fn.def2: ...@@ -699,6 +699,22 @@ fn.def2:
$$ = start_method (specs, $2); goto rest_of_mdef; } $$ = start_method (specs, $2); goto rest_of_mdef; }
| constructor_declarator | constructor_declarator
{ $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; } { $$ = start_method (NULL_TREE, $$); goto rest_of_mdef; }
| template_header fn.def2
{
end_template_decl ();
if ($2 && DECL_TEMPLATE_INFO ($2))
{
$$ = DECL_TI_TEMPLATE ($2);
check_member_template ($$);
}
else if ($2)
$$ = $2;
else
{
cp_error("invalid member template declaration");
$$ = NULL_TREE;
}
}
; ;
return_id: return_id:
...@@ -2711,7 +2727,22 @@ component_decl_1: ...@@ -2711,7 +2727,22 @@ component_decl_1:
build_tree_list ($3, NULL_TREE)); } build_tree_list ($3, NULL_TREE)); }
| using_decl | using_decl
{ $$ = do_class_using_decl ($1); } { $$ = do_class_using_decl ($1); }
; | template_header component_decl_1
{
end_template_decl ();
if ($2 && DECL_TEMPLATE_INFO ($2))
{
$$ = DECL_TI_TEMPLATE ($2);
check_member_template ($$);
}
else if ($2)
$$ = $2;
else
{
cp_error("invalid member template declaration");
$$ = NULL_TREE;
}
}
/* The case of exactly one component is handled directly by component_decl. */ /* The case of exactly one component is handled directly by component_decl. */
/* ??? Huh? ^^^ */ /* ??? Huh? ^^^ */
......
...@@ -76,7 +76,148 @@ static int comp_template_args PROTO((tree, tree)); ...@@ -76,7 +76,148 @@ 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));
static tree coerce_template_parms PROTO((tree, tree, tree)); static tree coerce_template_parms PROTO((tree, tree, tree));
static tree tsubst_enum PROTO((tree, tree *, int)); static tree tsubst_enum PROTO((tree, tree, int));
static tree add_to_template_args PROTO((tree, tree));
/* Restore the template parameter context. */
void
begin_member_template_processing (parms)
tree parms;
{
int i;
++processing_template_decl;
current_template_parms
= tree_cons (build_int_2 (0, processing_template_decl),
parms, current_template_parms);
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VEC_ELT (parms, i);
switch (TREE_CODE (parm))
{
case TEMPLATE_TYPE_PARM:
pushdecl (TYPE_NAME (parm));
break;
case TEMPLATE_CONST_PARM:
pushdecl (parm);
break;
default:
my_friendly_abort (0);
}
}
}
/* Undo the effects of begin_member_template_processing. */
void
end_member_template_processing ()
{
if (! processing_template_decl)
return;
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
}
/* Returns non-zero iff T is a member template function. Works if T
is either a FUNCTION_DECL or a TEMPLATE_DECL. */
int
is_member_template (t)
tree t;
{
int r = 0;
if (DECL_FUNCTION_MEMBER_P (t) ||
(TREE_CODE (t) == TEMPLATE_DECL &&
DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
{
tree tmpl = NULL_TREE;
if (DECL_FUNCTION_TEMPLATE_P (t))
tmpl = t;
else if (DECL_TEMPLATE_INFO (t)
&& DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
tmpl = DECL_TI_TEMPLATE (t);
if (tmpl)
{
tree parms = DECL_TEMPLATE_PARMS (tmpl);
int parm_levels = list_length (parms);
int template_class_levels = 0;
tree ctx = DECL_CLASS_CONTEXT (t);
if (CLASSTYPE_TEMPLATE_INFO (ctx))
{
tree args;
/* Here, we should really count the number of levels
deep ctx is, making sure not to count any levels that
are just specializations. Since there are no member
template classes yet, we don't have to do all that. */
if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
template_class_levels = 1;
else
{
int i;
args = CLASSTYPE_TI_ARGS (ctx);
if (args == NULL_TREE)
template_class_levels = 1;
else
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
if (uses_template_parms (TREE_VEC_ELT (args, i)))
{
template_class_levels++;
break;
}
}
}
if (parm_levels > template_class_levels)
r = 1;
}
}
return r;
}
/* Return a new template argument vector which contains all of ARGS,
but has as its innermost set of arguments the EXTRA_ARGS. */
tree
add_to_template_args (args, extra_args)
tree args;
tree extra_args;
{
tree new_args;
if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
{
new_args = make_tree_vec (2);
TREE_VEC_ELT (new_args, 0) = args;
}
else
{
int i;
new_args = make_tree_vec (TREE_VEC_LENGTH (args) - 1);
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
}
TREE_VEC_ELT (new_args,
TREE_VEC_LENGTH (new_args) - 1) = extra_args;
return new_args;
}
/* We've got a template header coming up; push to a new level for storing /* We've got a template header coming up; push to a new level for storing
the parms. */ the parms. */
...@@ -216,7 +357,10 @@ tree ...@@ -216,7 +357,10 @@ tree
current_template_args () current_template_args ()
{ {
tree header = current_template_parms; tree header = current_template_parms;
tree args = NULL_TREE; int length = list_length (header);
tree args = make_tree_vec (length);
int l = length;
while (header) while (header)
{ {
tree a = copy_node (TREE_VALUE (header)); tree a = copy_node (TREE_VALUE (header));
...@@ -224,20 +368,26 @@ current_template_args () ...@@ -224,20 +368,26 @@ current_template_args ()
TREE_TYPE (a) = NULL_TREE; TREE_TYPE (a) = NULL_TREE;
while (i--) while (i--)
{ {
tree t = TREE_VALUE (TREE_VEC_ELT (a, i)); tree t = TREE_VEC_ELT (a, i);
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t); /* t will be a list if we are called from within a
else begin/end_template_parm_list pair, but a vector directly
t = DECL_INITIAL (t); if within a begin/end_member_template_processing pair. */
if (TREE_CODE (t) == TREE_LIST)
{
t = TREE_VALUE (t);
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
else
t = DECL_INITIAL (t);
}
TREE_VEC_ELT (a, i) = t; TREE_VEC_ELT (a, i) = t;
} }
args = tree_cons (TREE_PURPOSE (header), a, args); TREE_VEC_ELT (args, --l) = a;
header = TREE_CHAIN (header); header = TREE_CHAIN (header);
} }
args = nreverse (args);
/* FIXME Remove this when we support member templates. */
args = TREE_VALUE (args);
return args; return args;
} }
...@@ -290,12 +440,15 @@ push_template_decl (decl) ...@@ -290,12 +440,15 @@ push_template_decl (decl)
if (! ctx || TYPE_BEING_DEFINED (ctx)) if (! ctx || TYPE_BEING_DEFINED (ctx))
{ {
tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE); tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = TREE_VALUE (current_template_parms); DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl); DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
if (DECL_LANG_SPECIFIC (decl))
DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
} }
else else
{ {
tree t; tree t;
tree a;
if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx)) if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
cp_error ("must specialize `%#T' before defining member `%#D'", cp_error ("must specialize `%#T' before defining member `%#D'",
...@@ -309,19 +462,54 @@ push_template_decl (decl) ...@@ -309,19 +462,54 @@ push_template_decl (decl)
} }
else else
tmpl = DECL_TI_TEMPLATE (decl); tmpl = DECL_TI_TEMPLATE (decl);
if (is_member_template (tmpl))
{
a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
t = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
if (TREE_VEC_LENGTH (t)
!= TREE_VEC_LENGTH (a))
{
cp_error ("got %d template parameters for `%#D'",
TREE_VEC_LENGTH (a), decl);
cp_error (" but %d required", TREE_VEC_LENGTH (t));
}
if (TREE_VEC_LENGTH (args) > 1)
/* Get the template parameters for the enclosing template
class. */
a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2);
else
a = NULL_TREE;
}
else
a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
t = NULL_TREE;
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx)) if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx)); {
else /* When processing an inline member template of a
t = DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx)); specialized class, there is no CLASSTYPE_TI_SPEC_INFO. */
if (CLASSTYPE_TI_SPEC_INFO (ctx))
t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
}
else if (CLASSTYPE_TEMPLATE_INFO (ctx))
t = DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
/* There should be template arguments if and only if there is a
template class. */
my_friendly_assert((a != NULL_TREE) == (t != NULL_TREE), 0);
if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (args)) if (t != NULL_TREE
&& TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
{ {
cp_error ("got %d template parameters for `%#D'", cp_error ("got %d template parameters for `%#D'",
TREE_VEC_LENGTH (args), decl); TREE_VEC_LENGTH (a), decl);
cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t)); cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
} }
} }
/* Get the innermost set of template arguments. */
args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
DECL_TEMPLATE_RESULT (tmpl) = decl; DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl); TREE_TYPE (tmpl) = TREE_TYPE (decl);
...@@ -330,7 +518,7 @@ push_template_decl (decl) ...@@ -330,7 +518,7 @@ push_template_decl (decl)
tmpl = pushdecl_top_level (tmpl); tmpl = pushdecl_top_level (tmpl);
if (primary) if (primary)
TREE_TYPE (DECL_TEMPLATE_PARMS (tmpl)) = tmpl; TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
info = perm_tree_cons (tmpl, args, NULL_TREE); info = perm_tree_cons (tmpl, args, NULL_TREE);
...@@ -345,8 +533,6 @@ push_template_decl (decl) ...@@ -345,8 +533,6 @@ push_template_decl (decl)
DECL_TEMPLATE_INFO (decl) = info; DECL_TEMPLATE_INFO (decl) = info;
} }
tree tsubst PROTO ((tree, tree*, int, tree));
/* Convert all template arguments to their appropriate types, and return /* Convert all template arguments to their appropriate types, and return
a vector containing the resulting values. If any error occurs, return a vector containing the resulting values. If any error occurs, return
error_mark_node. */ error_mark_node. */
...@@ -401,10 +587,10 @@ coerce_template_parms (parms, arglist, in_decl) ...@@ -401,10 +587,10 @@ coerce_template_parms (parms, arglist, in_decl)
else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i))) else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
== TYPE_DECL) == TYPE_DECL)
arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)), arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
&TREE_VEC_ELT (vec, 0), i, in_decl); vec, i, in_decl);
else else
arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)), arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
&TREE_VEC_ELT (vec, 0), i, in_decl); vec, i, in_decl);
TREE_VEC_ELT (vec, i) = arg; TREE_VEC_ELT (vec, i) = arg;
} }
...@@ -460,7 +646,7 @@ coerce_template_parms (parms, arglist, in_decl) ...@@ -460,7 +646,7 @@ coerce_template_parms (parms, arglist, in_decl)
} }
else else
{ {
tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0), tree t = tsubst (TREE_TYPE (parm), vec,
TREE_VEC_LENGTH (vec), in_decl); TREE_VEC_LENGTH (vec), in_decl);
if (processing_template_decl) if (processing_template_decl)
val = arg; val = arg;
...@@ -656,7 +842,7 @@ classtype_mangled_name (t) ...@@ -656,7 +842,7 @@ classtype_mangled_name (t)
tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t)); tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
char *mangled_name = mangle_class_name_for_template char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name), (IDENTIFIER_POINTER (name),
DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)), DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
CLASSTYPE_TI_ARGS (t)); CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name); tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name; IDENTIFIER_TEMPLATE (id) = name;
...@@ -740,7 +926,7 @@ lookup_template_class (d1, arglist, in_decl) ...@@ -740,7 +926,7 @@ lookup_template_class (d1, arglist, in_decl)
if (PRIMARY_TEMPLATE_P (template)) if (PRIMARY_TEMPLATE_P (template))
{ {
parmlist = DECL_TEMPLATE_PARMS (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, template); arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node) if (arglist == error_mark_node)
...@@ -1209,7 +1395,7 @@ instantiate_class_template (type) ...@@ -1209,7 +1395,7 @@ instantiate_class_template (type)
tree elt; tree elt;
TREE_VEC_ELT (bases, i) = elt TREE_VEC_ELT (bases, i) = elt
= tsubst (TREE_VEC_ELT (pbases, i), &TREE_VEC_ELT (args, 0), = tsubst (TREE_VEC_ELT (pbases, i), args,
TREE_VEC_LENGTH (args), NULL_TREE); TREE_VEC_LENGTH (args), NULL_TREE);
BINFO_INHERITANCE_CHAIN (elt) = binfo; BINFO_INHERITANCE_CHAIN (elt) = binfo;
...@@ -1241,7 +1427,7 @@ instantiate_class_template (type) ...@@ -1241,7 +1427,7 @@ instantiate_class_template (type)
/* These will add themselves to CLASSTYPE_TAGS for the new type. */ /* These will add themselves to CLASSTYPE_TAGS for the new type. */
if (TREE_CODE (tag) == ENUMERAL_TYPE) if (TREE_CODE (tag) == ENUMERAL_TYPE)
{ {
tree e, newtag = tsubst_enum (tag, &TREE_VEC_ELT (args, 0), tree e, newtag = tsubst_enum (tag, args,
TREE_VEC_LENGTH (args)); TREE_VEC_LENGTH (args));
*field_chain = grok_enum_decls (newtag, NULL_TREE); *field_chain = grok_enum_decls (newtag, NULL_TREE);
...@@ -1252,7 +1438,7 @@ instantiate_class_template (type) ...@@ -1252,7 +1438,7 @@ instantiate_class_template (type)
} }
} }
else else
tsubst (tag, &TREE_VEC_ELT (args, 0), tsubst (tag, args,
TREE_VEC_LENGTH (args), NULL_TREE); TREE_VEC_LENGTH (args), NULL_TREE);
} }
...@@ -1260,7 +1446,7 @@ instantiate_class_template (type) ...@@ -1260,7 +1446,7 @@ instantiate_class_template (type)
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t)) for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) != CONST_DECL) if (TREE_CODE (t) != CONST_DECL)
{ {
tree r = tsubst (t, &TREE_VEC_ELT (args, 0), tree r = tsubst (t, args,
TREE_VEC_LENGTH (args), NULL_TREE); TREE_VEC_LENGTH (args), NULL_TREE);
if (TREE_CODE (r) == VAR_DECL) if (TREE_CODE (r) == VAR_DECL)
{ {
...@@ -1288,18 +1474,18 @@ instantiate_class_template (type) ...@@ -1288,18 +1474,18 @@ instantiate_class_template (type)
DECL_FRIENDLIST (TYPE_MAIN_DECL (type)) DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
= tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)), = tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)),
&TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), NULL_TREE); args, TREE_VEC_LENGTH (args), NULL_TREE);
{ {
tree d = CLASSTYPE_FRIEND_CLASSES (type) tree d = CLASSTYPE_FRIEND_CLASSES (type)
= tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), &TREE_VEC_ELT (args, 0), = tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), args,
TREE_VEC_LENGTH (args), NULL_TREE); TREE_VEC_LENGTH (args), NULL_TREE);
/* This does injection for friend classes. */ /* This does injection for friend classes. */
for (; d; d = TREE_CHAIN (d)) for (; d; d = TREE_CHAIN (d))
TREE_VALUE (d) = xref_tag_from_type (TREE_VALUE (d), NULL_TREE, 1); TREE_VALUE (d) = xref_tag_from_type (TREE_VALUE (d), NULL_TREE, 1);
d = tsubst (DECL_TEMPLATE_INJECT (template), &TREE_VEC_ELT (args, 0), d = tsubst (DECL_TEMPLATE_INJECT (template), args,
TREE_VEC_LENGTH (args), NULL_TREE); TREE_VEC_LENGTH (args), NULL_TREE);
for (; d; d = TREE_CHAIN (d)) for (; d; d = TREE_CHAIN (d))
...@@ -1382,7 +1568,7 @@ lookup_nested_type_by_name (ctype, name) ...@@ -1382,7 +1568,7 @@ lookup_nested_type_by_name (ctype, name)
tree tree
tsubst (t, args, nargs, in_decl) tsubst (t, args, nargs, in_decl)
tree t, *args; tree t, args;
int nargs; int nargs;
tree in_decl; tree in_decl;
{ {
...@@ -1471,15 +1657,108 @@ tsubst (t, args, nargs, in_decl) ...@@ -1471,15 +1657,108 @@ tsubst (t, args, nargs, in_decl)
} }
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
case TEMPLATE_CONST_PARM:
{ {
tree arg = args[TEMPLATE_TYPE_IDX (t)]; int idx;
return cp_build_type_variant int level;
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t)); if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
idx = TEMPLATE_TYPE_IDX (t);
level = TEMPLATE_TYPE_LEVEL (t);
}
else
{
idx = TEMPLATE_CONST_IDX (t);
level = TEMPLATE_CONST_LEVEL (t);
}
if (TREE_VEC_LENGTH (args) > 0)
{
tree arg = NULL_TREE;
if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
{
if (TREE_VEC_LENGTH (args) >= level - 1)
arg = TREE_VEC_ELT
(TREE_VEC_ELT (args, level - 1), idx);
}
else if (level == 1)
arg = TREE_VEC_ELT (args, idx);
if (arg != NULL_TREE)
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
else
return arg;
}
}
/* If we get here, we must have been looking at a parm for a
more deeply nested template. */
my_friendly_assert((TREE_CODE (t) == TEMPLATE_CONST_PARM
&& TEMPLATE_CONST_LEVEL (t) > 1)
|| (TREE_CODE (t) == TEMPLATE_TYPE_PARM
&& TEMPLATE_TYPE_LEVEL (t) > 1),
0);
return t;
} }
case TEMPLATE_CONST_PARM: case TEMPLATE_DECL:
return args[TEMPLATE_CONST_IDX (t)]; {
/* We can get here when processing a member template function
of a template class. */
tree tmpl;
tree decl = DECL_TEMPLATE_RESULT (t);
tree new_decl;
tree parms;
int i;
/* We might already have an instance of this template. */
tree instances = DECL_TEMPLATE_INSTANTIATIONS (t);
tree ctx = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, in_decl);
for (; instances; instances = TREE_CHAIN (instances))
if (DECL_CLASS_CONTEXT (TREE_VALUE (instances)) == ctx)
return TREE_VALUE (instances);
/* Make a new template decl. It will be similar to the
original, but will record the current template arguments.
We also create a new function declaration, which is just
like the old one, but points to this new template, rather
than the old one. */
tmpl = copy_node (t);
copy_lang_decl (tmpl);
my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
DECL_CHAIN (tmpl) = NULL_TREE;
TREE_CHAIN (tmpl) = NULL_TREE;
DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
new_decl = tsubst (decl, args, nargs, in_decl);
DECL_RESULT (tmpl) = new_decl;
DECL_INITIAL (new_decl) = DECL_INITIAL (decl);
DECL_TI_TEMPLATE (new_decl) = tmpl;
TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
DECL_TEMPLATE_INSTANTIATIONS(tmpl) = NULL_TREE;
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
DECL_TEMPLATE_PARMS (tmpl)
= copy_node (DECL_TEMPLATE_PARMS (tmpl));
for (parms = DECL_TEMPLATE_PARMS (tmpl);
TREE_CHAIN (parms) != NULL_TREE;
parms = TREE_CHAIN (parms))
TREE_CHAIN (parms) = copy_node (TREE_CHAIN (parms));
/* Record this partial instantiation. */
DECL_TEMPLATE_INSTANTIATIONS (t)
= perm_tree_cons (NULL_TREE, tmpl,
DECL_TEMPLATE_INSTANTIATIONS (t));
return tmpl;
}
case FUNCTION_DECL: case FUNCTION_DECL:
{ {
...@@ -1516,7 +1795,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1516,7 +1795,7 @@ tsubst (t, args, nargs, in_decl)
/* Do we already have this instantiation? */ /* Do we already have this instantiation? */
if (DECL_TEMPLATE_INFO (t) != NULL_TREE) if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
{ {
tree tmpl = TREE_PURPOSE (DECL_TEMPLATE_INFO (t)); tree tmpl = DECL_TI_TEMPLATE (t);
tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl); tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
for (; decls; decls = TREE_CHAIN (decls)) for (; decls; decls = TREE_CHAIN (decls))
...@@ -1622,8 +1901,10 @@ tsubst (t, args, nargs, in_decl) ...@@ -1622,8 +1901,10 @@ tsubst (t, args, nargs, in_decl)
{ {
tree tmpl = DECL_TI_TEMPLATE (t); tree tmpl = DECL_TI_TEMPLATE (t);
tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl); tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)), tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
args, nargs, in_decl);
if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
argvec = add_to_template_args (DECL_TI_ARGS (tmpl), argvec);
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
*declsp = perm_tree_cons (argvec, r, *declsp); *declsp = perm_tree_cons (argvec, r, *declsp);
...@@ -1727,8 +2008,7 @@ tsubst (t, args, nargs, in_decl) ...@@ -1727,8 +2008,7 @@ tsubst (t, args, nargs, in_decl)
{ {
tree tmpl = DECL_TI_TEMPLATE (t); tree tmpl = DECL_TI_TEMPLATE (t);
tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl); tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)), tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
args, nargs, in_decl);
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
*declsp = perm_tree_cons (argvec, r, *declsp); *declsp = perm_tree_cons (argvec, r, *declsp);
...@@ -2013,7 +2293,7 @@ do_poplevel () ...@@ -2013,7 +2293,7 @@ do_poplevel ()
tree tree
tsubst_copy (t, args, nargs, in_decl) tsubst_copy (t, args, nargs, in_decl)
tree t, *args; tree t, args;
int nargs; int nargs;
tree in_decl; tree in_decl;
{ {
...@@ -2048,6 +2328,12 @@ tsubst_copy (t, args, nargs, in_decl) ...@@ -2048,6 +2328,12 @@ tsubst_copy (t, args, nargs, in_decl)
mark_used (t); mark_used (t);
return t; return t;
case TEMPLATE_DECL:
if (is_member_template (t))
return tsubst (t, args, nargs, in_decl);
else
return t;
#if 0 #if 0
case IDENTIFIER_NODE: case IDENTIFIER_NODE:
return do_identifier (t, 0); return do_identifier (t, 0);
...@@ -2241,7 +2527,7 @@ tsubst_copy (t, args, nargs, in_decl) ...@@ -2241,7 +2527,7 @@ tsubst_copy (t, args, nargs, in_decl)
tree tree
tsubst_expr (t, args, nargs, in_decl) tsubst_expr (t, args, nargs, in_decl)
tree t, *args; tree t, args;
int nargs; int nargs;
tree in_decl; tree in_decl;
{ {
...@@ -2543,7 +2829,7 @@ tsubst_expr (t, args, nargs, in_decl) ...@@ -2543,7 +2829,7 @@ tsubst_expr (t, args, nargs, in_decl)
tree tree
instantiate_template (tmpl, targ_ptr) instantiate_template (tmpl, targ_ptr)
tree tmpl, *targ_ptr; tree tmpl, targ_ptr;
{ {
tree fndecl; tree fndecl;
int i, len; int i, len;
...@@ -2555,12 +2841,12 @@ instantiate_template (tmpl, targ_ptr) ...@@ -2555,12 +2841,12 @@ instantiate_template (tmpl, targ_ptr)
function_maybepermanent_obstack = &permanent_obstack; function_maybepermanent_obstack = &permanent_obstack;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283); my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); len = DECL_NTPARMS (tmpl);
i = len; i = len;
while (i--) while (i--)
{ {
tree t = targ_ptr [i]; tree t = TREE_VEC_ELT (targ_ptr, i);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{ {
tree nt = target_type (t); tree nt = target_type (t);
...@@ -2572,9 +2858,12 @@ instantiate_template (tmpl, targ_ptr) ...@@ -2572,9 +2858,12 @@ instantiate_template (tmpl, targ_ptr)
goto out; goto out;
} }
} }
targ_ptr[i] = copy_to_permanent (t); TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
} }
if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
targ_ptr = add_to_template_args (DECL_TI_ARGS (tmpl), targ_ptr);
/* substitute template parameters */ /* substitute template parameters */
fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl); fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
...@@ -2606,6 +2895,42 @@ overload_template_name (type) ...@@ -2606,6 +2895,42 @@ overload_template_name (type)
pushdecl_class_level (decl); pushdecl_class_level (decl);
} }
/* Like type_unfication but designed specially to handle conversion
operators. */
int
fn_type_unification (fn, targs, args, return_type, strict)
tree fn, targs, args, return_type;
int strict;
{
int i, dummy = 0;
tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
tree decl_arg_types = args;
my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn)))
{
/* This is a template conversion operator. Use the return types
as well as the argument types. */
fn_arg_types = tree_cons (NULL_TREE,
TREE_TYPE (TREE_TYPE (fn)),
fn_arg_types);
decl_arg_types = tree_cons (NULL_TREE,
return_type,
decl_arg_types);
}
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
&TREE_VEC_ELT (targs, 0),
fn_arg_types,
decl_arg_types,
&dummy, 0, strict);
return i;
}
/* Type unification. /* Type unification.
We have a function template signature with one or more references to We have a function template signature with one or more references to
...@@ -2718,10 +3043,11 @@ type_unification (tparms, targs, parms, args, nsubsts, subr, strict) ...@@ -2718,10 +3043,11 @@ type_unification (tparms, targs, parms, args, nsubsts, subr, strict)
/* Have to back unify here */ /* Have to back unify here */
arg = TREE_VALUE (arg); arg = TREE_VALUE (arg);
nsubsts = 0; nsubsts = 0;
ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg)); ntparms = DECL_NTPARMS (arg);
targs = (tree *) alloca (sizeof (tree) * ntparms); targs = (tree *) alloca (sizeof (tree) * ntparms);
parm = tree_cons (NULL_TREE, parm, NULL_TREE); parm = tree_cons (NULL_TREE, parm, NULL_TREE);
return type_unification (DECL_TEMPLATE_PARMS (arg), targs, return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
targs,
TYPE_ARG_TYPES (TREE_TYPE (arg)), TYPE_ARG_TYPES (TREE_TYPE (arg)),
parm, &nsubsts, 0, strict); parm, &nsubsts, 0, strict);
} }
...@@ -3022,20 +3348,18 @@ int ...@@ -3022,20 +3348,18 @@ int
more_specialized (pat1, pat2) more_specialized (pat1, pat2)
tree pat1, pat2; tree pat1, pat2;
{ {
tree *targs; tree targs;
int winner = 0; int winner = 0;
targs = get_bindings (pat1, pat2); targs = get_bindings (pat1, pat2);
if (targs) if (targs)
{ {
free (targs);
--winner; --winner;
} }
targs = get_bindings (pat2, pat1); targs = get_bindings (pat2, pat1);
if (targs) if (targs)
{ {
free (targs);
++winner; ++winner;
} }
...@@ -3071,20 +3395,21 @@ more_specialized_class (pat1, pat2) ...@@ -3071,20 +3395,21 @@ more_specialized_class (pat1, pat2)
/* Return the template arguments that will produce the function signature /* Return the template arguments that will produce the function signature
DECL from the function template FN. */ DECL from the function template FN. */
tree * tree
get_bindings (fn, decl) get_bindings (fn, decl)
tree fn, decl; tree fn, decl;
{ {
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn)); int ntparms = DECL_NTPARMS (fn);
tree *targs = (tree *) malloc (sizeof (tree) * ntparms); tree targs = make_tree_vec (ntparms);
int i, dummy = 0; int i;
i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
TYPE_ARG_TYPES (TREE_TYPE (fn)), i = fn_type_unification (fn, targs,
TYPE_ARG_TYPES (TREE_TYPE (decl)), TYPE_ARG_TYPES (TREE_TYPE (decl)),
&dummy, 0, 1); TREE_TYPE (TREE_TYPE (decl)),
1);
if (i == 0) if (i == 0)
return targs; return targs;
free (targs);
return 0; return 0;
} }
...@@ -3122,7 +3447,7 @@ tree ...@@ -3122,7 +3447,7 @@ tree
most_specialized (fns, decl) most_specialized (fns, decl)
tree fns, decl; tree fns, decl;
{ {
tree fn, champ, *args, *p; tree fn, champ, args, *p;
int fate; int fate;
for (p = &fns; *p; ) for (p = &fns; *p; )
...@@ -3130,7 +3455,6 @@ most_specialized (fns, decl) ...@@ -3130,7 +3455,6 @@ most_specialized (fns, decl)
args = get_bindings (TREE_VALUE (*p), decl); args = get_bindings (TREE_VALUE (*p), decl);
if (args) if (args)
{ {
free (args);
p = &TREE_CHAIN (*p); p = &TREE_CHAIN (*p);
} }
else else
...@@ -3234,6 +3558,7 @@ do_decl_instantiation (declspecs, declarator, storage) ...@@ -3234,6 +3558,7 @@ do_decl_instantiation (declspecs, declarator, storage)
tree fn; tree fn;
tree result = NULL_TREE; tree result = NULL_TREE;
int extern_p = 0; int extern_p = 0;
tree templates = NULL_TREE;
if (! DECL_LANG_SPECIFIC (decl)) if (! DECL_LANG_SPECIFIC (decl))
{ {
...@@ -3261,43 +3586,61 @@ do_decl_instantiation (declspecs, declarator, storage) ...@@ -3261,43 +3586,61 @@ do_decl_instantiation (declspecs, declarator, storage)
fn = IDENTIFIER_GLOBAL_VALUE (name), fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (fn)) fn && DECL_TEMPLATE_INSTANTIATION (fn))
result = fn; result = fn;
else
{
/* Maybe this is an instantiation of a member template
function. */
tree ctype = DECL_CONTEXT (decl);
name = DECL_NAME (decl);
fn = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
if (fn)
fn = TREE_VALUE (fn);
for (; fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl) && DECL_DEFER_OUTPUT (fn))
{
result = fn;
break;
}
else if (TREE_CODE (fn) == TEMPLATE_DECL)
templates = decl_tree_cons (NULL_TREE, fn, templates);
}
} }
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn) else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{ {
tree templates = NULL_TREE;
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn)) for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl) if (decls_match (fn, decl) && DECL_DEFER_OUTPUT (fn))
&& DECL_DEFER_OUTPUT (fn))
{ {
result = fn; result = fn;
break; break;
} }
else if (TREE_CODE (fn) == TEMPLATE_DECL) else if (TREE_CODE (fn) == TEMPLATE_DECL)
templates = decl_tree_cons (NULL_TREE, fn, templates); templates = decl_tree_cons (NULL_TREE, fn, templates);
}
if (! result) if (templates && !result)
{
tree args;
result = most_specialized (templates, decl);
if (result == error_mark_node)
{ {
tree *args; char *str = "candidates are:";
result = most_specialized (templates, decl); cp_error ("ambiguous template instantiation for `%D' requested", decl);
if (result == error_mark_node) for (fn = templates; fn; fn = TREE_CHAIN (fn))
{ {
char *str = "candidates are:"; cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
cp_error ("ambiguous template instantiation for `%D' requested", decl); str = " ";
for (fn = templates; fn; fn = TREE_CHAIN (fn))
{
cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
str = " ";
}
return;
}
else if (result)
{
args = get_bindings (result, decl);
result = instantiate_template (result, args);
free (args);
} }
return;
}
else if (result)
{
args = get_bindings (result, decl);
result = instantiate_template (result, args);
} }
} }
if (! result) if (! result)
{ {
cp_error ("no matching template for `%D' found", decl); cp_error ("no matching template for `%D' found", decl);
...@@ -3477,7 +3820,7 @@ instantiate_decl (d) ...@@ -3477,7 +3820,7 @@ instantiate_decl (d)
{ {
pushclass (DECL_CONTEXT (d), 2); pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (d) = tsubst_expr DECL_INITIAL (d) = tsubst_expr
(DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0), (DECL_INITIAL (pattern), args,
TREE_VEC_LENGTH (args), tmpl); TREE_VEC_LENGTH (args), tmpl);
popclass (1); popclass (1);
} }
...@@ -3527,7 +3870,7 @@ instantiate_decl (d) ...@@ -3527,7 +3870,7 @@ instantiate_decl (d)
/* Trick tsubst into giving us a new decl in case the template changed. */ /* Trick tsubst into giving us a new decl in case the template changed. */
save_ti = DECL_TEMPLATE_INFO (pattern); save_ti = DECL_TEMPLATE_INFO (pattern);
DECL_TEMPLATE_INFO (pattern) = NULL_TREE; DECL_TEMPLATE_INFO (pattern) = NULL_TREE;
td = tsubst (pattern, &TREE_VEC_ELT (args, 0), TREE_VEC_LENGTH (args), tmpl); td = tsubst (pattern, args, TREE_VEC_LENGTH (args), tmpl);
DECL_TEMPLATE_INFO (pattern) = save_ti; DECL_TEMPLATE_INFO (pattern) = save_ti;
/* And set up DECL_INITIAL, since tsubst doesn't. */ /* And set up DECL_INITIAL, since tsubst doesn't. */
...@@ -3535,7 +3878,7 @@ instantiate_decl (d) ...@@ -3535,7 +3878,7 @@ instantiate_decl (d)
{ {
pushclass (DECL_CONTEXT (d), 2); pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (td) = tsubst_expr DECL_INITIAL (td) = tsubst_expr
(DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0), (DECL_INITIAL (pattern), args,
TREE_VEC_LENGTH (args), tmpl); TREE_VEC_LENGTH (args), tmpl);
popclass (1); popclass (1);
} }
...@@ -3570,7 +3913,7 @@ instantiate_decl (d) ...@@ -3570,7 +3913,7 @@ instantiate_decl (d)
{ {
store_return_init store_return_init
(TREE_OPERAND (t, 0), (TREE_OPERAND (t, 0),
tsubst_expr (TREE_OPERAND (t, 1), &TREE_VEC_ELT (args, 0), tsubst_expr (TREE_OPERAND (t, 1), args,
TREE_VEC_LENGTH (args), tmpl)); TREE_VEC_LENGTH (args), tmpl));
t = TREE_CHAIN (t); t = TREE_CHAIN (t);
} }
...@@ -3591,8 +3934,7 @@ instantiate_decl (d) ...@@ -3591,8 +3934,7 @@ instantiate_decl (d)
keep_next_level (); keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42); my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
tsubst_expr (t, &TREE_VEC_ELT (args, 0), tsubst_expr (t, args, TREE_VEC_LENGTH (args), tmpl);
TREE_VEC_LENGTH (args), tmpl);
finish_function (lineno, 0, nested); finish_function (lineno, 0, nested);
} }
...@@ -3613,14 +3955,13 @@ tsubst_chain (t, argvec) ...@@ -3613,14 +3955,13 @@ tsubst_chain (t, argvec)
{ {
if (t) if (t)
{ {
tree first = tsubst (t, &TREE_VEC_ELT (argvec, 0), tree first = tsubst (t, argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE); TREE_VEC_LENGTH (argvec), NULL_TREE);
tree last = first; tree last = first;
for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t)) for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
{ {
tree x = tsubst (t, &TREE_VEC_ELT (argvec, 0), tree x = tsubst (t, argvec, TREE_VEC_LENGTH (argvec), NULL_TREE);
TREE_VEC_LENGTH (argvec), NULL_TREE);
TREE_CHAIN (last) = x; TREE_CHAIN (last) = x;
last = x; last = x;
} }
...@@ -3639,9 +3980,9 @@ tsubst_expr_values (t, argvec) ...@@ -3639,9 +3980,9 @@ tsubst_expr_values (t, argvec)
for (; t; t = TREE_CHAIN (t)) for (; t; t = TREE_CHAIN (t))
{ {
tree pur = tsubst_copy (TREE_PURPOSE (t), &TREE_VEC_ELT (argvec, 0), tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE); TREE_VEC_LENGTH (argvec), NULL_TREE);
tree val = tsubst_expr (TREE_VALUE (t), &TREE_VEC_ELT (argvec, 0), tree val = tsubst_expr (TREE_VALUE (t), argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE); TREE_VEC_LENGTH (argvec), NULL_TREE);
*p = build_tree_list (pur, val); *p = build_tree_list (pur, val);
p = &TREE_CHAIN (*p); p = &TREE_CHAIN (*p);
...@@ -3691,7 +4032,7 @@ add_maybe_template (d, fns) ...@@ -3691,7 +4032,7 @@ add_maybe_template (d, fns)
static tree static tree
tsubst_enum (tag, args, nargs) tsubst_enum (tag, args, nargs)
tree tag, *args; tree tag, args;
int nargs; int nargs;
{ {
tree newtag = start_enum (TYPE_IDENTIFIER (tag)); tree newtag = start_enum (TYPE_IDENTIFIER (tag));
......
...@@ -1637,6 +1637,23 @@ lookup_fnfields_1 (type, name) ...@@ -1637,6 +1637,23 @@ lookup_fnfields_1 (type, name)
if (DECL_NAME (*methods) == name) if (DECL_NAME (*methods) == name)
break; break;
} }
/* If we didn't find it, it might have been a template
conversion operator. (Note that we don't look for this case
above so that we will always find specializations first.) */
if (methods == end
&& IDENTIFIER_TYPENAME_P (name))
{
methods = &TREE_VEC_ELT (method_vec, 0) + 1;
while (++methods != end)
{
if (TREE_CODE (*methods) == TEMPLATE_DECL
&& IDENTIFIER_TYPENAME_P (DECL_NAME (*methods)))
break;
}
}
if (methods != end) if (methods != end)
return methods - &TREE_VEC_ELT (method_vec, 0); return methods - &TREE_VEC_ELT (method_vec, 0);
} }
......
...@@ -2005,7 +2005,8 @@ cp_tree_equal (t1, t2) ...@@ -2005,7 +2005,8 @@ cp_tree_equal (t1, t2)
return 0; return 0;
case TEMPLATE_CONST_PARM: case TEMPLATE_CONST_PARM:
return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2); return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
&& TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
case SIZEOF_EXPR: case SIZEOF_EXPR:
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0))) if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
......
...@@ -832,7 +832,8 @@ comptypes (type1, type2, strict) ...@@ -832,7 +832,8 @@ comptypes (type1, type2, strict)
break; break;
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2); return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
&& TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
case TYPENAME_TYPE: case TYPENAME_TYPE:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2)) if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
...@@ -2296,7 +2297,8 @@ build_x_function_call (function, params, decl) ...@@ -2296,7 +2297,8 @@ build_x_function_call (function, params, decl)
{ {
tree basetype = NULL_TREE; tree basetype = NULL_TREE;
if (TREE_CODE (function) == FUNCTION_DECL) if (TREE_CODE (function) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (function))
{ {
basetype = DECL_CLASS_CONTEXT (function); basetype = DECL_CLASS_CONTEXT (function);
......
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