From 98c1c668807d74ad4dfab8c0413499b31f638258 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 6 Sep 1997 04:10:07 -0400 Subject: [PATCH] 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 * 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 * 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 --- gcc/cp/ChangeLog | 101 +++++++++ gcc/cp/call.c | 143 +++++++++--- gcc/cp/class.c | 45 +--- gcc/cp/cp-tree.def | 2 +- gcc/cp/cp-tree.h | 22 +- gcc/cp/decl.c | 64 ++++-- gcc/cp/decl2.c | 87 +++++++- gcc/cp/error.c | 79 ++++--- gcc/cp/lex.c | 8 +- gcc/cp/method.c | 4 +- gcc/cp/parse.y | 33 ++- gcc/cp/pt.c | 541 ++++++++++++++++++++++++++++++++++++--------- gcc/cp/search.c | 17 ++ gcc/cp/tree.c | 3 +- gcc/cp/typeck.c | 6 +- 15 files changed, 925 insertions(+), 230 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 21f2c6c982ea..effd43423c1d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,104 @@ +Fri Sep 5 17:27:38 1997 Jason Merrill + + * class.c (grow_method): Remove check for redeclaration. + +Wed Sep 3 12:30:24 1997 Mark Mitchell + + * 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 * typeck.c (c_expand_return): Always convert_for_initialization diff --git a/gcc/cp/call.c b/gcc/cp/call.c index b30f78fcd4a0..06316143a2ba 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 a9624a6deaf3..af735e98fcf4 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 a92bf8a6f112..6c6dff78c5cf 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 e13839787057..0daf874dde40 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 eb574e81a91a..c77dac80396c 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 e78b00d25a79..2de7fcede6e9 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 b3d68ce0668f..ce2bc3b88dc5 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 83ac1a7de5bd..7fca8a2138d4 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 0a67b802f7bf..8a50dabac993 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 47302a0cc578..7d9d5db7a343 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 9ba46ac21b2b..3620253a6b58 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 29f8ef345198..078793c8cfa4 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 e12050ddd30c..bf542af547ff 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 a442d4ec85a4..b000efbead5a 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); -- 2.43.5