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>
* typeck.c (c_expand_return): Always convert_for_initialization
......
......@@ -77,7 +77,7 @@ static tree build_this PROTO((tree));
static struct z_candidate * splice_viable PROTO((struct z_candidate *));
static int any_viable PROTO((struct z_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
PROTO((struct z_candidate *, enum tree_code, enum tree_code,
tree, tree *, int));
......@@ -2838,11 +2838,12 @@ build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
}
if (TREE_CODE (function) == TEMPLATE_DECL)
{
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function));
tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
int ntparms = DECL_NTPARMS (function);
tree targs = make_tree_vec (ntparms);
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)),
parms, &template_cost, 0, 0);
if (i == 0)
......@@ -4144,20 +4145,19 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
}
static struct z_candidate *
add_template_candidate (candidates, tmpl, arglist, flags)
add_template_candidate (candidates, tmpl, arglist, return_type, flags)
struct z_candidate *candidates;
tree tmpl, arglist;
tree tmpl, arglist, return_type;
int flags;
{
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
struct z_candidate *cand;
int i, dummy = 0;
int i;
tree fn;
i = type_unification (DECL_TEMPLATE_PARMS (tmpl), targs,
TYPE_ARG_TYPES (TREE_TYPE (tmpl)),
arglist, &dummy, 0, 0);
i = fn_type_unification (tmpl, targs, arglist, return_type, 0);
if (i != 0)
return candidates;
......@@ -4253,6 +4253,7 @@ build_user_type_conversion_1 (totype, expr, flags)
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, *p;
tree args;
tree templates = NULL_TREE;
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
......@@ -4279,9 +4280,22 @@ build_user_type_conversion_1 (totype, expr, flags)
if (DECL_NONCONVERTING_P (ctors))
continue;
candidates = add_function_candidate (candidates, ctors, args, flags);
candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
candidates->basetype_path = TYPE_BINFO (totype);
if (TREE_CODE (ctors) == TEMPLATE_DECL)
{
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)
......@@ -4308,11 +4322,24 @@ build_user_type_conversion_1 (totype, expr, flags)
else if (ics)
for (; fn; fn = DECL_CHAIN (fn))
{
candidates = add_function_candidate (candidates, fn, args, flags);
candidates->second_conv = ics;
candidates->basetype_path = TREE_PURPOSE (convs);
if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
candidates->viable = -1;
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
templates = decl_tree_cons (NULL_TREE, fn, templates);
candidates =
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)
for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
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
(USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn)
......@@ -4427,7 +4461,7 @@ build_new_function_call (fn, args, obj)
{
templates = decl_tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate
(candidates, t, args, LOOKUP_NORMAL);
(candidates, t, args, NULL_TREE, LOOKUP_NORMAL);
}
else
candidates = add_function_candidate
......@@ -4713,7 +4747,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
{
templates = decl_tree_cons (NULL_TREE, fns, templates);
candidates = add_template_candidate
(candidates, fns, arglist, flags);
(candidates, fns, arglist, TREE_TYPE (fnname), flags);
}
else
candidates = add_function_candidate (candidates, fns, arglist, flags);
......@@ -4730,13 +4764,27 @@ build_new_op (code, flags, arg1, arg2, arg3)
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
for (; fn; fn = DECL_CHAIN (fn))
{
tree this_arglist;
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
candidates = add_function_candidate
(candidates, fn, mem_arglist, flags);
this_arglist = mem_arglist;
else
candidates = add_function_candidate (candidates, fn, arglist, flags);
candidates->basetype_path = TREE_PURPOSE (fns);
this_arglist = arglist;
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)
if (DECL_FUNCTION_MEMBER_P (cand->fn))
enforce_access (cand->basetype_path, cand->fn);
/* Pedantically, it is ill-formed to define a function that could
also be a template instantiation, but we won't implement that
until things settle down. */
/* 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);
......@@ -5188,8 +5236,7 @@ build_over_call (fn, convs, args, flags)
if (DECL_TEMPLATE_INFO (fn))
/* This came from a template. Instantiate the default arg here,
not in tsubst. */
arg = tsubst_expr (arg,
&TREE_VEC_ELT (DECL_TI_ARGS (fn), 0),
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE);
converted_args = tree_cons
(NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
......@@ -5332,6 +5379,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
tree basetype, mem_args, fns, instance_ptr;
tree pretty_name;
tree user_args = args;
tree templates = NULL_TREE;
/* If there is an extra argument for controlling virtual bases,
remove it for error reporting. */
......@@ -5412,17 +5460,34 @@ build_new_method_call (instance, name, args, basetype_path, flags)
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
for (; t; t = DECL_CHAIN (t))
{
tree this_arglist;
/* We can end up here for copy-init of same or base class. */
if (name == ctor_identifier
&& (flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (t))
continue;
if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
candidates = add_function_candidate
(candidates, t, mem_args, flags);
this_arglist = mem_args;
else
candidates = add_function_candidate (candidates, t, args, flags);
candidates->basetype_path = TREE_PURPOSE (fns);
this_arglist = args;
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)
|| resolves_to_fixed_type_p (instance, 0)))
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
(cand->fn, cand->convs,
TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
......
......@@ -1872,33 +1872,10 @@ grow_method (fndecl, method_vec_ptr)
if (testp < (tree *) obstack_next_free (&class_obstack))
{
tree x, prev_x;
for (x = *testp; x; x = DECL_CHAIN (x))
{
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;
}
tree *p;
for (p = testp; *p; )
p = &DECL_CHAIN (*p);
*p = fndecl;
}
else
{
......@@ -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;
if (last_x)
......@@ -5062,12 +5040,13 @@ instantiate_type (lhstype, rhs, complain)
for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
if (TREE_CODE (elem) == TEMPLATE_DECL)
{
int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
tree *t = (tree *) alloca (sizeof (tree) * n);
int n = DECL_NTPARMS (elem);
tree t = make_tree_vec (n);
int i, d = 0;
i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), &d, 0, 1);
i = type_unification
(DECL_INNERMOST_TEMPLATE_PARMS (elem),
&TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
TYPE_ARG_TYPES (lhstype), &d, 0, 1);
if (i == 0)
{
if (save_elem)
......
......@@ -91,7 +91,7 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", "t", 0)
/* Index into a template parameter list. This parameter must not be a
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.
......
......@@ -1091,6 +1091,7 @@ struct lang_decl
#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_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 COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
......@@ -1334,6 +1335,10 @@ extern int flag_new_for_scope;
/* Accessor macros for C++ template decl nodes. */
#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. */
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
/* For function, method, class-data templates. */
......@@ -1346,7 +1351,7 @@ extern int flag_new_for_scope;
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
#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) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (CLASSTYPE_TI_TEMPLATE (NODE))))
......@@ -2112,6 +2117,7 @@ extern tree grok_alignof PROTO((tree));
extern tree grok_array_decl PROTO((tree, tree));
extern tree delete_sanity PROTO((tree, tree, int, int));
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 grokbitfield PROTO((tree, tree, tree));
extern tree groktypefield PROTO((tree, tree));
......@@ -2299,10 +2305,12 @@ extern void synthesize_method PROTO((tree));
extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */
extern tree tsubst 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 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_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 tree process_template_parm PROTO((tree, tree));
extern tree end_template_parm_list PROTO((tree));
......@@ -2312,8 +2320,9 @@ extern void push_template_decl PROTO((tree));
extern tree lookup_template_class PROTO((tree, tree, tree));
extern int uses_template_parms 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 int fn_type_unification PROTO((tree, tree, tree, tree, int));
extern int type_unification PROTO((tree, tree *, tree, tree, int *, int, int));
struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int));
......@@ -2324,7 +2333,7 @@ extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree));
extern tree lookup_nested_type_by_name PROTO((tree, tree));
extern tree do_poplevel PROTO((void));
extern tree *get_bindings PROTO((tree, tree));
extern tree get_bindings PROTO((tree, tree));
/* CONT ... */
extern void add_tree PROTO((tree));
extern void add_maybe_template PROTO((tree, tree));
......@@ -2333,6 +2342,7 @@ extern tree most_specialized PROTO((tree, tree));
extern tree most_specialized_class PROTO((tree, tree));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
/* in repo.c */
extern void repo_template_used PROTO((tree));
......
......@@ -2306,23 +2306,40 @@ decls_match (newdecl, olddecl)
{
tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
int i, len = TREE_VEC_LENGTH (newargs);
int i;
if (TREE_VEC_LENGTH (oldargs) != len)
return 0;
for (i = 0; i < len; i++)
/* Run through all the levels of template parmaters, checking
that they match. */
while (newargs && oldargs)
{
tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i));
tree oldarg = TREE_VALUE (TREE_VEC_ELT (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))
int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
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)
types_match = 1;
else
......@@ -3003,7 +3020,7 @@ pushdecl (x)
/* Type are looked up using the DECL_NAME, as that is what the rest of the
compiler wants to use. */
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);
if (name)
......@@ -3493,6 +3510,11 @@ push_class_level_binding (name, x)
tree name;
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)
&& purpose_member (name, class_binding_level->class_shadowed))
return;
......@@ -7232,6 +7254,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (check)
{
tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT(tmp);
if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
......@@ -7270,6 +7296,10 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
if (ctype != NULL_TREE && check)
{
tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT(tmp);
if (tmp && DECL_STATIC_FUNCTION_P (tmp)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{
......@@ -8934,8 +8964,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
type = tsubst (type, &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), NULL_TREE);
type = tsubst (type, args,
TREE_VEC_LENGTH (TREE_VEC_ELT
(args, 0)),
NULL_TREE);
}
/* This pop_nested_class corresponds to the
......@@ -10038,7 +10070,7 @@ void
replace_defarg (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))
cp_pedwarn ("invalid type `%T' for default argument to `%T'",
TREE_TYPE (init), TREE_VALUE (arg));
......
......@@ -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
really a member of the class (CTYPE) it is supposed to belong to.
CNAME is the same here as it is for grokclassfn above. */
......@@ -1295,6 +1348,7 @@ check_classfn (ctype, function)
tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
tree *methods = 0;
tree *end = 0;
tree templates = NULL_TREE;
if (method_vec != 0)
{
......@@ -1311,6 +1365,7 @@ check_classfn (ctype, function)
while (++methods != end)
{
fndecl = *methods;
if (fn_name == DECL_NAME (*methods))
{
got_it:
......@@ -1342,14 +1397,39 @@ check_classfn (ctype, function)
TREE_TYPE (TREE_TYPE (fndecl)), 1)
&& compparms (p1, p2, 3))
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
fndecl = DECL_CHAIN (fndecl);
}
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)
{
......@@ -2792,7 +2872,7 @@ finish_file ()
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))
continue;
......@@ -2800,7 +2880,6 @@ finish_file ()
fn = TREE_PURPOSE (fnname);
args = get_bindings (fn, decl);
fn = instantiate_template (fn, args);
free (args);
instantiate_decl (fn);
}
......
......@@ -722,33 +722,42 @@ dump_decl (t, v)
case TEMPLATE_DECL:
{
tree args = DECL_TEMPLATE_PARMS (t);
int i, len = args ? TREE_VEC_LENGTH (args) : 0;
OB_PUTS ("template <");
for (i = 0; i < len; i++)
tree orig_args = DECL_TEMPLATE_PARMS (t);
tree args;
int i;
for (args = orig_args = nreverse (orig_args);
args;
args = TREE_CHAIN (args))
{
tree arg = TREE_VEC_ELT (args, i);
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);
int len = TREE_VEC_LENGTH (TREE_VALUE (args));
if (defval)
OB_PUTS ("template <");
for (i = 0; i < len; i++)
{
OB_PUTS (" = ");
dump_decl (defval, 1);
}
tree arg = TREE_VEC_ELT (TREE_VALUE (args), i);
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)
OB_UNPUT (2);
OB_PUTC2 ('>', ' ');
nreverse(orig_args);
if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
dump_type (TREE_TYPE (t), v);
......@@ -801,11 +810,18 @@ dump_function_decl (t, v)
tree t;
int v;
{
tree name = DECL_ASSEMBLER_NAME (t);
tree fntype = TREE_TYPE (t);
tree parmtypes = TYPE_ARG_TYPES (fntype);
tree name;
tree fntype;
tree parmtypes;
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. */
if (DECL_CONTEXT (t))
cname = DECL_CLASS_CONTEXT (t);
......@@ -1349,8 +1365,17 @@ dump_expr (t, nop)
case TEMPLATE_CONST_PARM:
if (current_template_parms)
{
tree r = TREE_VEC_ELT (TREE_VALUE (current_template_parms),
TEMPLATE_CONST_IDX (t));
int i;
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);
}
else
......
......@@ -1190,6 +1190,8 @@ do_pending_inlines ()
context = hack_decl_function_context (t->fndecl);
if (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)
{
feed_input (t->buf, t->len);
......@@ -1226,7 +1228,9 @@ process_next_inline (t)
{
tree context;
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)
pop_cp_function_context (context);
i = i->next;
......@@ -1249,6 +1253,8 @@ process_next_inline (t)
context = hack_decl_function_context (i->fndecl);
if (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);
lineno = i->lineno;
input_filename = i->filename;
......
......@@ -648,7 +648,7 @@ build_overload_identifier (name)
arglist = TREE_VALUE (template);
template = TREE_PURPOSE (template);
tname = DECL_NAME (template);
parmlist = DECL_ARGUMENTS (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
nparms = TREE_VEC_LENGTH (parmlist);
OB_PUTC ('t');
icat (IDENTIFIER_LENGTH (tname));
......@@ -666,7 +666,7 @@ build_overload_identifier (name)
}
else
{
parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0),
parm = tsubst (parm, arglist,
TREE_VEC_LENGTH (arglist), NULL_TREE);
/* It's a PARM_DECL. */
build_overload_name (TREE_TYPE (parm), 0, 0);
......
......@@ -699,6 +699,22 @@ fn.def2:
$$ = start_method (specs, $2); goto rest_of_mdef; }
| constructor_declarator
{ $$ = 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:
......@@ -2711,7 +2727,22 @@ component_decl_1:
build_tree_list ($3, NULL_TREE)); }
| using_decl
{ $$ = 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. */
/* ??? Huh? ^^^ */
......
......@@ -76,7 +76,148 @@ static int comp_template_args PROTO((tree, tree));
static int list_eq PROTO((tree, tree));
static tree get_class_bindings PROTO((tree, tree, tree));
static tree 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
the parms. */
......@@ -216,7 +357,10 @@ tree
current_template_args ()
{
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)
{
tree a = copy_node (TREE_VALUE (header));
......@@ -224,20 +368,26 @@ current_template_args ()
TREE_TYPE (a) = NULL_TREE;
while (i--)
{
tree t = TREE_VALUE (TREE_VEC_ELT (a, i));
if (TREE_CODE (t) == TYPE_DECL)
t = TREE_TYPE (t);
else
t = DECL_INITIAL (t);
tree t = TREE_VEC_ELT (a, i);
/* t will be a list if we are called from within a
begin/end_template_parm_list pair, but a vector directly
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;
}
args = tree_cons (TREE_PURPOSE (header), a, args);
TREE_VEC_ELT (args, --l) = a;
header = TREE_CHAIN (header);
}
args = nreverse (args);
/* FIXME Remove this when we support member templates. */
args = TREE_VALUE (args);
return args;
}
......@@ -290,12 +440,15 @@ push_template_decl (decl)
if (! ctx || TYPE_BEING_DEFINED (ctx))
{
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);
if (DECL_LANG_SPECIFIC (decl))
DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl);
}
else
{
tree t;
tree a;
if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
cp_error ("must specialize `%#T' before defining member `%#D'",
......@@ -309,19 +462,54 @@ push_template_decl (decl)
}
else
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))
t = TREE_VALUE (CLASSTYPE_TI_SPEC_INFO (ctx));
else
t = DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (ctx));
{
/* When processing an inline member template of a
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'",
TREE_VEC_LENGTH (args), decl);
TREE_VEC_LENGTH (a), decl);
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;
TREE_TYPE (tmpl) = TREE_TYPE (decl);
......@@ -330,7 +518,7 @@ push_template_decl (decl)
tmpl = pushdecl_top_level (tmpl);
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);
......@@ -345,8 +533,6 @@ push_template_decl (decl)
DECL_TEMPLATE_INFO (decl) = info;
}
tree tsubst PROTO ((tree, tree*, int, tree));
/* Convert all template arguments to their appropriate types, and return
a vector containing the resulting values. If any error occurs, return
error_mark_node. */
......@@ -401,10 +587,10 @@ coerce_template_parms (parms, arglist, in_decl)
else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
== TYPE_DECL)
arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
&TREE_VEC_ELT (vec, 0), i, in_decl);
vec, i, in_decl);
else
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;
}
......@@ -460,7 +646,7 @@ coerce_template_parms (parms, arglist, in_decl)
}
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);
if (processing_template_decl)
val = arg;
......@@ -656,7 +842,7 @@ classtype_mangled_name (t)
tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name),
DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name;
......@@ -740,7 +926,7 @@ lookup_template_class (d1, arglist, in_decl)
if (PRIMARY_TEMPLATE_P (template))
{
parmlist = DECL_TEMPLATE_PARMS (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, template);
if (arglist == error_mark_node)
......@@ -1209,7 +1395,7 @@ instantiate_class_template (type)
tree 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);
BINFO_INHERITANCE_CHAIN (elt) = binfo;
......@@ -1241,7 +1427,7 @@ instantiate_class_template (type)
/* These will add themselves to CLASSTYPE_TAGS for the new 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));
*field_chain = grok_enum_decls (newtag, NULL_TREE);
......@@ -1252,7 +1438,7 @@ instantiate_class_template (type)
}
}
else
tsubst (tag, &TREE_VEC_ELT (args, 0),
tsubst (tag, args,
TREE_VEC_LENGTH (args), NULL_TREE);
}
......@@ -1260,7 +1446,7 @@ instantiate_class_template (type)
for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
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);
if (TREE_CODE (r) == VAR_DECL)
{
......@@ -1288,18 +1474,18 @@ instantiate_class_template (type)
DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
= 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)
= tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), &TREE_VEC_ELT (args, 0),
= tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), args,
TREE_VEC_LENGTH (args), NULL_TREE);
/* This does injection for friend classes. */
for (; d; d = TREE_CHAIN (d))
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);
for (; d; d = TREE_CHAIN (d))
......@@ -1382,7 +1568,7 @@ lookup_nested_type_by_name (ctype, name)
tree
tsubst (t, args, nargs, in_decl)
tree t, *args;
tree t, args;
int nargs;
tree in_decl;
{
......@@ -1471,15 +1657,108 @@ tsubst (t, args, nargs, in_decl)
}
case TEMPLATE_TYPE_PARM:
case TEMPLATE_CONST_PARM:
{
tree arg = args[TEMPLATE_TYPE_IDX (t)];
return cp_build_type_variant
(arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
int idx;
int level;
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:
return args[TEMPLATE_CONST_IDX (t)];
case TEMPLATE_DECL:
{
/* 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:
{
......@@ -1516,7 +1795,7 @@ tsubst (t, args, nargs, in_decl)
/* Do we already have this instantiation? */
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);
for (; decls; decls = TREE_CHAIN (decls))
......@@ -1622,8 +1901,10 @@ tsubst (t, args, nargs, in_decl)
{
tree tmpl = DECL_TI_TEMPLATE (t);
tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
args, nargs, in_decl);
tree argvec = tsubst (DECL_TI_ARGS (t), 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);
*declsp = perm_tree_cons (argvec, r, *declsp);
......@@ -1727,8 +2008,7 @@ tsubst (t, args, nargs, in_decl)
{
tree tmpl = DECL_TI_TEMPLATE (t);
tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
tree argvec = tsubst (TREE_VALUE (DECL_TEMPLATE_INFO (t)),
args, nargs, in_decl);
tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
*declsp = perm_tree_cons (argvec, r, *declsp);
......@@ -2013,7 +2293,7 @@ do_poplevel ()
tree
tsubst_copy (t, args, nargs, in_decl)
tree t, *args;
tree t, args;
int nargs;
tree in_decl;
{
......@@ -2048,6 +2328,12 @@ tsubst_copy (t, args, nargs, in_decl)
mark_used (t);
return t;
case TEMPLATE_DECL:
if (is_member_template (t))
return tsubst (t, args, nargs, in_decl);
else
return t;
#if 0
case IDENTIFIER_NODE:
return do_identifier (t, 0);
......@@ -2241,7 +2527,7 @@ tsubst_copy (t, args, nargs, in_decl)
tree
tsubst_expr (t, args, nargs, in_decl)
tree t, *args;
tree t, args;
int nargs;
tree in_decl;
{
......@@ -2543,7 +2829,7 @@ tsubst_expr (t, args, nargs, in_decl)
tree
instantiate_template (tmpl, targ_ptr)
tree tmpl, *targ_ptr;
tree tmpl, targ_ptr;
{
tree fndecl;
int i, len;
......@@ -2555,12 +2841,12 @@ instantiate_template (tmpl, targ_ptr)
function_maybepermanent_obstack = &permanent_obstack;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
len = DECL_NTPARMS (tmpl);
i = len;
while (i--)
{
tree t = targ_ptr [i];
tree t = TREE_VEC_ELT (targ_ptr, i);
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{
tree nt = target_type (t);
......@@ -2572,9 +2858,12 @@ instantiate_template (tmpl, targ_ptr)
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 */
fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
......@@ -2606,6 +2895,42 @@ overload_template_name (type)
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.
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)
/* Have to back unify here */
arg = TREE_VALUE (arg);
nsubsts = 0;
ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg));
ntparms = DECL_NTPARMS (arg);
targs = (tree *) alloca (sizeof (tree) * ntparms);
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)),
parm, &nsubsts, 0, strict);
}
......@@ -3022,20 +3348,18 @@ int
more_specialized (pat1, pat2)
tree pat1, pat2;
{
tree *targs;
tree targs;
int winner = 0;
targs = get_bindings (pat1, pat2);
if (targs)
{
free (targs);
--winner;
}
targs = get_bindings (pat2, pat1);
if (targs)
{
free (targs);
++winner;
}
......@@ -3071,20 +3395,21 @@ more_specialized_class (pat1, pat2)
/* Return the template arguments that will produce the function signature
DECL from the function template FN. */
tree *
tree
get_bindings (fn, decl)
tree fn, decl;
{
int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
int i, dummy = 0;
i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl)),
&dummy, 0, 1);
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
int i;
i = fn_type_unification (fn, targs,
TYPE_ARG_TYPES (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (decl)),
1);
if (i == 0)
return targs;
free (targs);
return 0;
}
......@@ -3122,7 +3447,7 @@ tree
most_specialized (fns, decl)
tree fns, decl;
{
tree fn, champ, *args, *p;
tree fn, champ, args, *p;
int fate;
for (p = &fns; *p; )
......@@ -3130,7 +3455,6 @@ most_specialized (fns, decl)
args = get_bindings (TREE_VALUE (*p), decl);
if (args)
{
free (args);
p = &TREE_CHAIN (*p);
}
else
......@@ -3234,6 +3558,7 @@ do_decl_instantiation (declspecs, declarator, storage)
tree fn;
tree result = NULL_TREE;
int extern_p = 0;
tree templates = NULL_TREE;
if (! DECL_LANG_SPECIFIC (decl))
{
......@@ -3261,43 +3586,61 @@ do_decl_instantiation (declspecs, declarator, storage)
fn = IDENTIFIER_GLOBAL_VALUE (name),
fn && DECL_TEMPLATE_INSTANTIATION (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)
{
tree templates = NULL_TREE;
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
if (decls_match (fn, decl)
&& DECL_DEFER_OUTPUT (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);
}
if (! result)
if (templates && !result)
{
tree args;
result = most_specialized (templates, decl);
if (result == error_mark_node)
{
tree *args;
result = most_specialized (templates, decl);
if (result == error_mark_node)
char *str = "candidates are:";
cp_error ("ambiguous template instantiation for `%D' requested", decl);
for (fn = templates; fn; fn = TREE_CHAIN (fn))
{
char *str = "candidates are:";
cp_error ("ambiguous template instantiation for `%D' requested", decl);
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);
cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
str = " ";
}
return;
}
else if (result)
{
args = get_bindings (result, decl);
result = instantiate_template (result, args);
}
}
if (! result)
{
cp_error ("no matching template for `%D' found", decl);
......@@ -3477,7 +3820,7 @@ instantiate_decl (d)
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (d) = tsubst_expr
(DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0),
(DECL_INITIAL (pattern), args,
TREE_VEC_LENGTH (args), tmpl);
popclass (1);
}
......@@ -3527,7 +3870,7 @@ instantiate_decl (d)
/* Trick tsubst into giving us a new decl in case the template changed. */
save_ti = DECL_TEMPLATE_INFO (pattern);
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;
/* And set up DECL_INITIAL, since tsubst doesn't. */
......@@ -3535,7 +3878,7 @@ instantiate_decl (d)
{
pushclass (DECL_CONTEXT (d), 2);
DECL_INITIAL (td) = tsubst_expr
(DECL_INITIAL (pattern), &TREE_VEC_ELT (args, 0),
(DECL_INITIAL (pattern), args,
TREE_VEC_LENGTH (args), tmpl);
popclass (1);
}
......@@ -3570,7 +3913,7 @@ instantiate_decl (d)
{
store_return_init
(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));
t = TREE_CHAIN (t);
}
......@@ -3591,8 +3934,7 @@ instantiate_decl (d)
keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
tsubst_expr (t, &TREE_VEC_ELT (args, 0),
TREE_VEC_LENGTH (args), tmpl);
tsubst_expr (t, args, TREE_VEC_LENGTH (args), tmpl);
finish_function (lineno, 0, nested);
}
......@@ -3613,14 +3955,13 @@ tsubst_chain (t, argvec)
{
if (t)
{
tree first = tsubst (t, &TREE_VEC_ELT (argvec, 0),
tree first = tsubst (t, argvec,
TREE_VEC_LENGTH (argvec), NULL_TREE);
tree last = first;
for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
{
tree x = tsubst (t, &TREE_VEC_ELT (argvec, 0),
TREE_VEC_LENGTH (argvec), NULL_TREE);
tree x = tsubst (t, argvec, TREE_VEC_LENGTH (argvec), NULL_TREE);
TREE_CHAIN (last) = x;
last = x;
}
......@@ -3639,9 +3980,9 @@ tsubst_expr_values (t, argvec)
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 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);
*p = build_tree_list (pur, val);
p = &TREE_CHAIN (*p);
......@@ -3691,7 +4032,7 @@ add_maybe_template (d, fns)
static tree
tsubst_enum (tag, args, nargs)
tree tag, *args;
tree tag, args;
int nargs;
{
tree newtag = start_enum (TYPE_IDENTIFIER (tag));
......
......@@ -1637,6 +1637,23 @@ lookup_fnfields_1 (type, name)
if (DECL_NAME (*methods) == name)
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)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
......
......@@ -2005,7 +2005,8 @@ cp_tree_equal (t1, t2)
return 0;
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:
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
......
......@@ -832,7 +832,8 @@ comptypes (type1, type2, strict)
break;
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:
if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
......@@ -2296,7 +2297,8 @@ build_x_function_call (function, params, decl)
{
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);
......
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