aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@gcc.gnu.org>1997-09-06 04:10:07 -0400
committerJason Merrill <jason@gcc.gnu.org>1997-09-06 04:10:07 -0400
commit98c1c668807d74ad4dfab8c0413499b31f638258 (patch)
tree770f6f78bc4ec8479312fa2a69e6db566c0ed9b9
parentdbfcb4beace35e1426c1ce1e9bf2f20c7d5a0f56 (diff)
downloadgcc-98c1c668807d74ad4dfab8c0413499b31f638258.zip
gcc-98c1c668807d74ad4dfab8c0413499b31f638258.tar.gz
gcc-98c1c668807d74ad4dfab8c0413499b31f638258.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog101
-rw-r--r--gcc/cp/call.c143
-rw-r--r--gcc/cp/class.c45
-rw-r--r--gcc/cp/cp-tree.def2
-rw-r--r--gcc/cp/cp-tree.h22
-rw-r--r--gcc/cp/decl.c64
-rw-r--r--gcc/cp/decl2.c87
-rw-r--r--gcc/cp/error.c79
-rw-r--r--gcc/cp/lex.c8
-rw-r--r--gcc/cp/method.c4
-rw-r--r--gcc/cp/parse.y33
-rw-r--r--gcc/cp/pt.c541
-rw-r--r--gcc/cp/search.c17
-rw-r--r--gcc/cp/tree.c3
-rw-r--r--gcc/cp/typeck.c6
15 files changed, 925 insertions, 230 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 21f2c6c..effd434 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,104 @@
+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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b30f78f..0631614 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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,
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a9624a6..af735e9 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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)
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index a92bf8a..6c6dff7 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e138397..0daf874 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index eb574e8..c77dac8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index e78b00d..2de7fce 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index b3d68ce..ce2bc3b 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -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
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 83ac1a7..7fca8a2 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -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;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 0a67b80..8a50dab 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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);
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 47302a0..7d9d5db 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -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? ^^^ */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9ba46ac..3620253 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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));
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 29f8ef3..078793c 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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);
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index e12050d..bf542af 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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)))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a442d4e..b000efb 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);