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? ^^^ */
......
...@@ -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