diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 541 |
1 files changed, 441 insertions, 100 deletions
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)); |