diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-05-11 07:25:25 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-05-11 07:25:25 +0000 |
commit | 32b5f03edf1f72bf8607cef500ef9808fb52b4db (patch) | |
tree | 3eb441453df3706bae901aecf80a665eda32abc2 | |
parent | 6a12f047b22aee0fade9ab7f046be492664d9576 (diff) | |
download | gcc-32b5f03edf1f72bf8607cef500ef9808fb52b4db.tar.gz |
* call.c (add_template_candidate): Adjust for changes to
fn_type_unification.
(add_template_candidate_real): Likewise.
(add_template_conv_candidate): Likewise.
(build_user_type_conversion_1): Likewise.
(build_new_function_call): Likewise.
(build_object_call): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
* class.c (instantiate_type): Likewise.
* cp-tree.h (unification_kind_t): New type.
(fn_type_unification): Adjust prototype.
(type_unificaiton): Likewise.
* pt.c (UNIFY_ALLOW_NONE): New macro.
(UNIFY_ALLOW_MORE_CV_QUAL): Likewise.
(UNIFY_ALLOW_LESS_CV_QUAL): Likewise.
(UNIFY_ALLOW_DERIVED): Likewise.
(unify): Change prototype.
(maybe_adjust_types_for_deduction): New function.
(check_cv_quals_for_unify): Likewise.
(determine_specialization): Adjust.
(fn_type_unification): Likewise.
(type_unification): Likewise.
(type_unification_real): Likewise. Use
maybe_adjust_types_for_deduction. Fix mishandling of
back-unification of template functions passed as arguments. Pass
appropriate combination of UNIFY_ALLOW_* to unify.
(unify): Remove unused NTPARMS parameter. Use
check_cv_quals_for_unify. Remove bogus code that allowed
too-generous unification in order to adhere more closely to standard.
(get_bindings_real): Adjust.
(get_class_bindings): Likewise.
* method.c (build_overload_identifier): Only use the innermost
template arguments when mangling.
* pt.c (tsubst_template_argument_vector): New function.
(complete_template_args): Deal with the situation where the
extra_args contain more than one level of arguments.
(lookup_template_class): Deal with member template classes, which
may have more than one level of arguments.
(tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE.
Improve handling of member template classes. Use
DECL_PRIMARY_TEMPLATE instead of inline expansion. Use
tsubst_template_argument_vector where appropriate.
(regenerate_decl_from_template): Break out from ...
(instantiate_decl): Here.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@19663 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 47 | ||||
-rw-r--r-- | gcc/cp/call.c | 35 | ||||
-rw-r--r-- | gcc/cp/class.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 14 | ||||
-rw-r--r-- | gcc/cp/method.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 672 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/conv1.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/memclass9.C | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/unify3.C | 22 |
9 files changed, 638 insertions, 207 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6e9b82d3c3d..03fae3fe225 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,52 @@ Mon May 11 07:16:30 1998 Mark Mitchell <mmitchell@usa.net> + * call.c (add_template_candidate): Adjust for changes to + fn_type_unification. + (add_template_candidate_real): Likewise. + (add_template_conv_candidate): Likewise. + (build_user_type_conversion_1): Likewise. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_op): Likewise. + (build_new_method_call): Likewise. + * class.c (instantiate_type): Likewise. + * cp-tree.h (unification_kind_t): New type. + (fn_type_unification): Adjust prototype. + (type_unificaiton): Likewise. + * pt.c (UNIFY_ALLOW_NONE): New macro. + (UNIFY_ALLOW_MORE_CV_QUAL): Likewise. + (UNIFY_ALLOW_LESS_CV_QUAL): Likewise. + (UNIFY_ALLOW_DERIVED): Likewise. + (unify): Change prototype. + (maybe_adjust_types_for_deduction): New function. + (check_cv_quals_for_unify): Likewise. + (determine_specialization): Adjust. + (fn_type_unification): Likewise. + (type_unification): Likewise. + (type_unification_real): Likewise. Use + maybe_adjust_types_for_deduction. Fix mishandling of + back-unification of template functions passed as arguments. Pass + appropriate combination of UNIFY_ALLOW_* to unify. + (unify): Remove unused NTPARMS parameter. Use + check_cv_quals_for_unify. Remove bogus code that allowed + too-generous unification in order to adhere more closely to standard. + (get_bindings_real): Adjust. + (get_class_bindings): Likewise. + + * method.c (build_overload_identifier): Only use the innermost + template arguments when mangling. + * pt.c (tsubst_template_argument_vector): New function. + (complete_template_args): Deal with the situation where the + extra_args contain more than one level of arguments. + (lookup_template_class): Deal with member template classes, which + may have more than one level of arguments. + (tsubst): Don't tsbust into the TREE_TYPE of an IDENTIFIER_NODE. + Improve handling of member template classes. Use + DECL_PRIMARY_TEMPLATE instead of inline expansion. Use + tsubst_template_argument_vector where appropriate. + (regenerate_decl_from_template): Break out from ... + (instantiate_decl): Here. + * lex.c (yyprint): Remove TYPENAME_ELLIPSIS. * parse.h: Regenerated. * parse.c: Really regenerated. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e9ca9af376e..5eafd87289a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -61,9 +61,11 @@ 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, tree, tree, int)); + PROTO((struct z_candidate *, tree, tree, tree, tree, int, + unification_kind_t)); static struct z_candidate * add_template_candidate_real - PROTO((struct z_candidate *, tree, tree, tree, tree, int, tree)); + PROTO((struct z_candidate *, tree, tree, tree, tree, int, + tree, unification_kind_t)); static struct z_candidate * add_template_conv_candidate PROTO((struct z_candidate *, tree, tree, tree, tree)); static struct z_candidate * add_builtin_candidates @@ -1865,11 +1867,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags) static struct z_candidate* add_template_candidate_real (candidates, tmpl, explicit_targs, arglist, return_type, flags, - obj) + obj, strict) struct z_candidate *candidates; tree tmpl, explicit_targs, arglist, return_type; int flags; tree obj; + unification_kind_t strict; { int ntparms = DECL_NTPARMS (tmpl); tree targs = make_scratch_vec (ntparms); @@ -1878,7 +1881,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs, tree fn; i = fn_type_unification (tmpl, explicit_targs, targs, arglist, - return_type, 0, NULL_TREE); + return_type, strict, NULL_TREE); if (i != 0) return candidates; @@ -1920,14 +1923,16 @@ add_template_candidate_real (candidates, tmpl, explicit_targs, static struct z_candidate * add_template_candidate (candidates, tmpl, explicit_targs, - arglist, return_type, flags) + arglist, return_type, flags, strict) struct z_candidate *candidates; tree tmpl, explicit_targs, arglist, return_type; int flags; + unification_kind_t strict; { return add_template_candidate_real (candidates, tmpl, explicit_targs, - arglist, return_type, flags, NULL_TREE); + arglist, return_type, flags, + NULL_TREE, strict); } @@ -1938,7 +1943,7 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type) { return add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist, - return_type, 0, obj); + return_type, 0, obj, DEDUCE_CONV); } @@ -2058,7 +2063,8 @@ build_user_type_conversion_1 (totype, expr, flags) templates = scratch_tree_cons (NULL_TREE, ctor, templates); candidates = add_template_candidate (candidates, ctor, - NULL_TREE, args, NULL_TREE, flags); + NULL_TREE, args, NULL_TREE, flags, + DEDUCE_CALL); } else candidates = add_function_candidate (candidates, ctor, @@ -2107,7 +2113,8 @@ build_user_type_conversion_1 (totype, expr, flags) templates = scratch_tree_cons (NULL_TREE, fn, templates); candidates = add_template_candidate (candidates, fn, NULL_TREE, - args, totype, flags); + args, totype, flags, + DEDUCE_CONV); } else candidates = add_function_candidate (candidates, fn, @@ -2261,7 +2268,7 @@ build_new_function_call (fn, args) templates = scratch_tree_cons (NULL_TREE, t, templates); candidates = add_template_candidate (candidates, t, explicit_targs, args, NULL_TREE, - LOOKUP_NORMAL); + LOOKUP_NORMAL, DEDUCE_CALL); } else if (! template_only) candidates = add_function_candidate @@ -2346,7 +2353,7 @@ build_object_call (obj, args) candidates = add_template_candidate (candidates, fn, NULL_TREE, mem_args, NULL_TREE, - LOOKUP_NORMAL); + LOOKUP_NORMAL, DEDUCE_CALL); } else candidates = add_function_candidate @@ -2603,7 +2610,7 @@ build_new_op (code, flags, arg1, arg2, arg3) candidates = add_template_candidate (candidates, fn, NULL_TREE, arglist, TREE_TYPE (fnname), - flags); + flags, DEDUCE_CALL); } else candidates = add_function_candidate (candidates, fn, arglist, flags); @@ -2639,7 +2646,7 @@ build_new_op (code, flags, arg1, arg2, arg3) candidates = add_template_candidate (candidates, fn, NULL_TREE, this_arglist, TREE_TYPE (fnname), - flags); + flags, DEDUCE_CALL); } else candidates = add_function_candidate @@ -3591,7 +3598,7 @@ build_new_method_call (instance, name, args, basetype_path, flags) candidates = add_template_candidate (candidates, t, explicit_targs, this_arglist, - TREE_TYPE (name), flags); + TREE_TYPE (name), flags, DEDUCE_CALL); } else if (! template_only) candidates = add_function_candidate (candidates, t, diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 9ba28245940..17cfe2bf9b4 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5151,7 +5151,7 @@ instantiate_type (lhstype, rhs, complain) i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (elem), t, TYPE_ARG_TYPES (TREE_TYPE (elem)), - TYPE_ARG_TYPES (lhstype), explicit_targs, 1, 1); + TYPE_ARG_TYPES (lhstype), explicit_targs, DEDUCE_EXACT, 1); if (i == 0) { if (save_elem) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f044553d9ff..e76c85b3e8d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1683,6 +1683,16 @@ extern tree null_node; /* in pt.c */ +/* These values are used for the `STRICT' parameter to type_unfication and + fn_type_unification. Their meanings are described with the + documentation for fn_type_unification. */ + +typedef enum unification_kind_t { + DEDUCE_CALL, + DEDUCE_CONV, + DEDUCE_EXACT +} unification_kind_t; + extern tree current_template_parms; extern HOST_WIDE_INT processing_template_decl; extern tree last_tree; @@ -2504,8 +2514,8 @@ extern int uses_template_parms PROTO((tree)); extern tree instantiate_class_template PROTO((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, tree, int, tree)); -extern int type_unification PROTO((tree, tree, tree, tree, tree, int, int)); +extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, tree)); +extern int type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, int)); struct tinst_level *tinst_for_decl PROTO((void)); extern void mark_decl_instantiated PROTO((tree, int)); extern int more_specialized PROTO((tree, tree, tree)); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 9d8b8f0d778..ef048f3b900 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -893,7 +893,7 @@ build_overload_identifier (name) { tree template, parmlist, arglist, tname; template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); - arglist = TREE_VALUE (template); + arglist = innermost_args (TREE_VALUE (template), 0); template = TREE_PURPOSE (template); tname = DECL_NAME (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f30164f30ba..e9e6304b4e6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -70,7 +70,12 @@ static tree saved_trees; #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free -static int unify PROTO((tree, tree, int, tree, tree, int, int*)); +#define UNIFY_ALLOW_NONE 0 +#define UNIFY_ALLOW_MORE_CV_QUAL 1 +#define UNIFY_ALLOW_LESS_CV_QUAL 2 +#define UNIFY_ALLOW_DERIVED 4 + +static int unify PROTO((tree, tree, tree, tree, int, int*)); static void add_pending_template PROTO((tree)); static int push_tinst_level PROTO((tree)); static tree classtype_mangled_name PROTO((tree)); @@ -81,8 +86,10 @@ static tree get_class_bindings PROTO((tree, tree, tree, tree)); static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int)); static tree tsubst_enum PROTO((tree, tree, tree *)); static tree add_to_template_args PROTO((tree, tree)); +static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*, + tree*)); static int type_unification_real PROTO((tree, tree, tree, tree, - int, int, int, int*)); + int, unification_kind_t, int, int*)); static tree complete_template_args PROTO((tree, tree, int)); static void note_template_header PROTO((int)); static tree maybe_fold_nontype_arg PROTO((tree)); @@ -104,6 +111,9 @@ static tree tsubst_friend_class PROTO((tree, tree)); static tree get_bindings_real PROTO((tree, tree, tree, int)); static int template_decl_level PROTO((tree)); static tree maybe_get_template_decl_from_type_decl PROTO((tree)); +static int check_cv_quals_for_unify PROTO((int, tree, tree)); +static tree tsubst_template_arg_vector PROTO((tree, tree)); +static void regenerate_decl_from_template PROTO((tree, tree)); /* Do any processing required when DECL (a member template declaration using TEMPLATE_PARAMETERS as its innermost parameter list) is @@ -360,7 +370,7 @@ is_member_template (t) } /* Return a new template argument vector which contains all of ARGS - for all outer templates TYPE is contained in, but has as its + for all outer templates TMPL is contained in, but has as its innermost set of arguments the EXTRA_ARGS. If UNBOUND_ONLY, we are only interested in unbound template arguments, not arguments from enclosing templates that have been instantiated already. */ @@ -373,10 +383,16 @@ complete_template_args (tmpl, extra_args, unbound_only) /* depth is the number of levels of enclosing args we're adding. */ int depth, i; tree args, new_args, spec_args = NULL_TREE; - + int extra_arg_depth; + my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0); + if (TREE_CODE (TREE_VEC_ELT (extra_args, 0)) == TREE_VEC) + extra_arg_depth = TREE_VEC_LENGTH (extra_args); + else + extra_arg_depth = 1; + if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only) { /* A specialization of a member template of a template class shows up @@ -405,7 +421,7 @@ complete_template_args (tmpl, extra_args, unbound_only) template args. */ depth = 0; - new_args = make_tree_vec (depth + 1 + (!!spec_args)); + new_args = make_tree_vec (depth + extra_arg_depth + (!!spec_args)); if (depth == 1) TREE_VEC_ELT (new_args, 0) = args; @@ -427,7 +443,7 @@ complete_template_args (tmpl, extra_args, unbound_only) if (depth == 0) return extra_args; - new_args = make_tree_vec (depth + 1); + new_args = make_tree_vec (depth + extra_arg_depth); /* If this isn't a member template, extra_args is for the innermost template class, so skip over it. */ @@ -447,10 +463,14 @@ complete_template_args (tmpl, extra_args, unbound_only) } } - TREE_VEC_ELT (new_args, depth) = extra_args; + if (extra_arg_depth == 1) + TREE_VEC_ELT (new_args, depth++) = extra_args; + else + for (i = 0; i < extra_arg_depth; ++i) + TREE_VEC_ELT (new_args, depth++) = TREE_VEC_ELT (extra_args, i); if (spec_args) - TREE_VEC_ELT (new_args, depth + 1) = spec_args; + TREE_VEC_ELT (new_args, depth) = spec_args; return new_args; } @@ -776,7 +796,7 @@ determine_specialization (template_id, decl, targs_out, NULL_TREE, NULL_TREE, targs_in, - 1, 1); + DEDUCE_EXACT, 1); if (i == 0) /* Unification was successful. */ @@ -1814,8 +1834,15 @@ push_template_decl_real (decl, is_friend) cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t)); } } - /* Get the innermost set of template arguments. */ - args = innermost_args (args, 0); + /* Get the innermost set of template arguments. We don't do this + for a non-template member function of a nested template class + because there we will never get a `partial instantiation' of the + function containing the outer arguments, and so we must save all + of the arguments here. */ + if (TREE_CODE (decl) != FUNCTION_DECL + || template_class_depth (ctx) <= 1 + || primary) + args = innermost_args (args, 0); DECL_TEMPLATE_RESULT (tmpl) = decl; TREE_TYPE (tmpl) = TREE_TYPE (decl); @@ -2904,11 +2931,36 @@ lookup_template_class (d1, arglist, in_decl, context) || (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template))) == FUNCTION_DECL)) { + tree arglist_for_mangling; + parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); - arglist = coerce_template_parms (parmlist, arglist, template, - 1, 1, 0); - if (arglist == error_mark_node) + if (/* ARGLIST can be NULL_TREE if there are default arguments. */ + arglist != NULL_TREE + && TREE_CODE (arglist) == TREE_VEC + && TREE_VEC_LENGTH (arglist) > 1 + && list_length (DECL_TEMPLATE_PARMS (template)) > 1) + { + /* We have multiple levels of arguments to coerce, at once. */ + tree new_args = + make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template))); + int i; + + for (i = TREE_VEC_LENGTH (arglist) - 1, + t = DECL_TEMPLATE_PARMS (template); + i >= 0 && t != NULL_TREE; + --i, t = TREE_CHAIN (t)) + TREE_VEC_ELT (new_args, i) = + coerce_template_parms (TREE_VALUE (t), + TREE_VEC_ELT (arglist, i), + template, 1, 1, 0); + arglist = new_args; + } + else + arglist = coerce_template_parms (parmlist, + innermost_args (arglist, 0), + template, 1, 1, 0); + if (arglist == error_mark_node) return error_mark_node; if (uses_template_parms (arglist)) { @@ -2937,10 +2989,15 @@ lookup_template_class (d1, arglist, in_decl, context) } } + if (TREE_CODE (arglist) == TREE_VEC) + arglist_for_mangling = innermost_args (arglist, 0); + else + arglist_for_mangling = arglist; + /* FIXME avoid duplication. */ mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1), parmlist, - arglist, + arglist_for_mangling, id_context); id = get_identifier (mangled_name); IDENTIFIER_TEMPLATE (id) = d1; @@ -3875,11 +3932,46 @@ innermost_args (args, is_spec) tree args; int is_spec; { - if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) + if (args != NULL_TREE && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec); return args; } +/* Substitute ARGS into the vector of template arguments T. */ + +tree +tsubst_template_arg_vector (t, args) + tree t; + tree args; +{ + int len = TREE_VEC_LENGTH (t), need_new = 0, i; + tree *elts = (tree *) alloca (len * sizeof (tree)); + + bzero ((char *) elts, len * sizeof (tree)); + + for (i = 0; i < len; i++) + { + if (TREE_VEC_ELT (t, i) != NULL_TREE + && TREE_CODE (TREE_VEC_ELT (t, i)) == TREE_VEC) + elts[i] = tsubst_template_arg_vector (TREE_VEC_ELT (t, i), args); + else + elts[i] = maybe_fold_nontype_arg + (tsubst_expr (TREE_VEC_ELT (t, i), args, NULL_TREE)); + + if (elts[i] != TREE_VEC_ELT (t, i)) + need_new = 1; + } + + if (!need_new) + return t; + + t = make_tree_vec (len); + for (i = 0; i < len; i++) + TREE_VEC_ELT (t, i) = elts[i]; + + return t; +} + /* Take the tree structure T and replace template parameters used therein with the argument vector ARGS. IN_DECL is an associated decl for diagnostics. @@ -3907,7 +3999,9 @@ tsubst (t, args, in_decl) type = TREE_TYPE (t); if (type == unknown_type_node) my_friendly_abort (42); + if (type && TREE_CODE (t) != FUNCTION_DECL + && TREE_CODE (t) != IDENTIFIER_NODE && TREE_CODE (t) != TYPENAME_TYPE && TREE_CODE (t) != TEMPLATE_DECL && TREE_CODE (t) != IDENTIFIER_NODE) @@ -3932,14 +4026,33 @@ tsubst (t, args, in_decl) tree context; tree r; - context = - TYPE_CONTEXT (t) - ? tsubst (TYPE_CONTEXT (t), args, in_decl) : NULL_TREE; + if (TYPE_CONTEXT (t) != NULL_TREE) + { + context = tsubst (TYPE_CONTEXT (t), args, in_decl); + + if (TREE_CODE (context) != FUNCTION_DECL + && TREE_CODE (context) != NAMESPACE_DECL) + { + /* For a member class template, we need all the + template arguments. */ + if (CLASSTYPE_IS_TEMPLATE (TYPE_CONTEXT (t))) + argvec = + add_to_template_args (CLASSTYPE_TI_ARGS (context), + argvec); + + if (CLASSTYPE_TEMPLATE_INFO (context)) + argvec = + complete_template_args (CLASSTYPE_TI_TEMPLATE (context), + argvec, 0); + } + } + else + context = NULL_TREE; r = lookup_template_class (t, argvec, in_decl, context); return cp_build_type_variant (r, TYPE_READONLY (t), - TYPE_VOLATILE (t)); + TYPE_VOLATILE (t)); } /* else fall through */ @@ -4208,7 +4321,7 @@ tsubst (t, args, in_decl) } if (PRIMARY_TEMPLATE_P (t)) - TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl; + DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; /* We don't partially instantiate partial specializations. */ if (TREE_CODE (decl) == TYPE_DECL) @@ -4646,30 +4759,8 @@ tsubst (t, args, in_decl) } /* Otherwise, a vector of template arguments. */ - { - int len = TREE_VEC_LENGTH (t), need_new = 0, i; - tree *elts = (tree *) alloca (len * sizeof (tree)); - - bzero ((char *) elts, len * sizeof (tree)); - - for (i = 0; i < len; i++) - { - elts[i] = maybe_fold_nontype_arg - (tsubst_expr (TREE_VEC_ELT (t, i), args, in_decl)); - - if (elts[i] != TREE_VEC_ELT (t, i)) - need_new = 1; - } - - if (!need_new) - return t; + return tsubst_template_arg_vector (t, args); - t = make_tree_vec (len); - for (i = 0; i < len; i++) - TREE_VEC_ELT (t, i) = elts[i]; - - return t; - } case POINTER_TYPE: case REFERENCE_TYPE: { @@ -5493,7 +5584,7 @@ int fn_type_unification (fn, explicit_targs, targs, args, return_type, strict, extra_fn_arg) tree fn, explicit_targs, targs, args, return_type; - int strict; + unification_kind_t strict; tree extra_fn_arg; { int i; @@ -5553,22 +5644,37 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, a function or method parameter of a function template), so don't zero out targs and don't fail on an incomplete match. - If STRICT is 1, the match must be exact (for casts of overloaded - addresses, explicit instantiation, and more_specialized). */ + The parameter STRICT is one of: + + DEDUCE_CALL: + We are deducing arguments for a function call, as in + [temp.deduct.call]. + + DEDUCE_CONV: + We are deducing arguments for a conversion function, as in + [temp.deduct.conv]. + + DEDUCE_EXACT: + We are deducing arguments when calculating the partial + ordering between specializations of function or class + templates, as in [temp.func.order] and [temp.class.order], + when doing an explicit instantiation as in [temp.explicit], + when determiningan explicit specialization as in + [temp.expl.spec], or when taking the address of a function + template, as in [temp.deduct.funcaddr]. */ int type_unification (tparms, targs, parms, args, targs_in, strict, allow_incomplete) tree tparms, targs, parms, args, targs_in; - int strict, allow_incomplete; + unification_kind_t strict; + int allow_incomplete; { - int ntparms = TREE_VEC_LENGTH (tparms); tree arg; int* explicit_mask; int i; - int r; - for (i = 0; i < ntparms; i++) + for (i = 0; i < TREE_VEC_LENGTH (tparms); i++) TREE_VEC_ELT (targs, i) = NULL_TREE; if (targs_in != NULL_TREE) @@ -5596,10 +5702,84 @@ type_unification (tparms, targs, parms, args, targs_in, else explicit_mask = 0; - r = type_unification_real (tparms, targs, parms, args, 0, - strict, allow_incomplete, explicit_mask); + return + type_unification_real (tparms, targs, parms, args, 0, + strict, allow_incomplete, explicit_mask); +} + +/* Adjust types before performing type deduction, as described in + [temp.deduct.call] and [temp.deduct.conv]. The rules in these two + sections are symmetric. For calls, the value passed as PARM should + be a parameter to the template function, while ARG should be the + actual argument used in the call. For conversions, PARM should be + the type required as the result of the conversion, while ARG should + be the return type of the template conversion function. */ + +void +maybe_adjust_types_for_deduction (strict, parm, arg) + unification_kind_t strict; + tree* parm; + tree* arg; +{ + switch (strict) + { + case DEDUCE_CALL: + break; + + case DEDUCE_CONV: + { + /* Swap PARM and ARG; the handling is precisely symmetric since + PARM will initialize ARG rather than vice versa. */ + tree* temp = parm; + parm = arg; + arg = temp; + break; + } + + case DEDUCE_EXACT: + /* There is nothing to do in this case. */ + return; + + default: + my_friendly_abort (0); + } - return r; + if (TREE_CODE (*parm) != REFERENCE_TYPE) + { + /* [temp.deduct.call] + + If P is not a reference type: + + --If A is an array type, the pointer type produced by the + array-to-pointer standard conversion (_conv.array_) is + used in place of A for type deduction; otherwise, + + --If A is a function type, the pointer type produced by + the function-to-pointer standard conversion + (_conv.func_) is used in place of A for type deduction; + otherwise, + + --If A is a cv-qualified type, the top level + cv-qualifiers of A's type are ignored for type + deduction. */ + if (TREE_CODE (*arg) == ARRAY_TYPE) + *arg = build_pointer_type (TREE_TYPE (*arg)); + else if (TREE_CODE (*arg) == FUNCTION_TYPE + || TREE_CODE (*arg) == METHOD_TYPE) + *arg = build_pointer_type (*arg); + else + *arg = TYPE_MAIN_VARIANT (*arg); + } + + /* [temp.deduct.call] + + If P is a cv-qualified type, the top level cv-qualifiers + of P's type are ignored for type deduction. If P is a + reference type, the type referred to by P is used for + type deduction. */ + *parm = TYPE_MAIN_VARIANT (*parm); + if (TREE_CODE (*parm) == REFERENCE_TYPE) + *parm = TREE_TYPE (*parm); } /* Like type_unfication. EXPLICIT_MASK, if non-NULL, is an array of @@ -5610,12 +5790,15 @@ static int type_unification_real (tparms, targs, parms, args, subr, strict, allow_incomplete, explicit_mask) tree tparms, targs, parms, args; - int subr, strict, allow_incomplete; + int subr; + unification_kind_t strict; + int allow_incomplete; int* explicit_mask; { tree parm, arg; int i; int ntparms = TREE_VEC_LENGTH (tparms); + int sub_strict; my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289); my_friendly_assert (parms == NULL_TREE @@ -5626,6 +5809,24 @@ type_unification_real (tparms, targs, parms, args, subr, my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291); my_friendly_assert (ntparms > 0, 292); + switch (strict) + { + case DEDUCE_CALL: + sub_strict = UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_DERIVED; + break; + + case DEDUCE_CONV: + sub_strict = UNIFY_ALLOW_LESS_CV_QUAL; + break; + + case DEDUCE_EXACT: + sub_strict = UNIFY_ALLOW_NONE; + break; + + default: + my_friendly_abort (0); + } + while (parms && parms != void_list_node && args @@ -5657,7 +5858,7 @@ type_unification_real (tparms, targs, parms, args, subr, arg = NULL_TREE; } - if (strict) + if (strict == DEDUCE_EXACT) { if (comptypes (parm, type, 1)) continue; @@ -5683,20 +5884,20 @@ type_unification_real (tparms, targs, parms, args, subr, if (TREE_CODE (arg) == OVERLOAD && TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL) { - int ntparms; tree targs; + tree arg_type; /* Have to back unify here */ arg = OVL_FUNCTION (arg); - ntparms = DECL_NTPARMS (arg); - targs = make_scratch_vec (ntparms); + targs = make_scratch_vec (DECL_NTPARMS (arg)); + arg_type = TREE_TYPE (arg); + maybe_adjust_types_for_deduction (strict, &parm, &arg_type); parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE); + arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE); return type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), - targs, - TYPE_ARG_TYPES (TREE_TYPE (arg)), - parm, NULL_TREE, strict, - allow_incomplete); + targs, arg_type, parm, NULL_TREE, + DEDUCE_EXACT, allow_incomplete); } arg = TREE_TYPE (arg); } @@ -5707,21 +5908,10 @@ type_unification_real (tparms, targs, parms, args, subr, arg = ptr_type_node; } - if (! subr && TREE_CODE (arg) == REFERENCE_TYPE) - arg = TREE_TYPE (arg); + if (!subr) + maybe_adjust_types_for_deduction (strict, &parm, &arg); - if (! subr && TREE_CODE (parm) != REFERENCE_TYPE) - { - if (TREE_CODE (arg) == FUNCTION_TYPE - || TREE_CODE (arg) == METHOD_TYPE) - arg = build_pointer_type (arg); - else if (TREE_CODE (arg) == ARRAY_TYPE) - arg = build_pointer_type (TREE_TYPE (arg)); - else - arg = TYPE_MAIN_VARIANT (arg); - } - - switch (unify (tparms, targs, ntparms, parm, arg, strict, + switch (unify (tparms, targs, parm, arg, sub_strict, explicit_mask)) { case 0: @@ -5771,12 +5961,43 @@ template_decl_level (decl) } } -/* Tail recursion is your friend. */ +/* Decide whether ARG can be unified with PARM, considering only the + cv-qualifiers of each type, given STRICT as documented for unify. + Returns non-zero iff the unification is OK on that basis.*/ -static int -unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) +int +check_cv_quals_for_unify (strict, arg, parm) + int strict; + tree arg; + tree parm; +{ + return !((!(strict & UNIFY_ALLOW_MORE_CV_QUAL) + && (TYPE_READONLY (arg) < TYPE_READONLY (parm) + || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm))) + || (!(strict & UNIFY_ALLOW_LESS_CV_QUAL) + && (TYPE_READONLY (arg) > TYPE_READONLY (parm) + || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm)))); +} + +/* Takes parameters as for type_unification. Returns 0 if the + type deduction suceeds, 1 otherwise. The parameter STRICT is a + bitwise or of the following flags: + + UNIFY_ALLOW_NONE: + Require an exact match between PARM and ARG. + UNIFY_ALLOW_MORE_CV_QUAL: + Allow the deduced ARG to be more cv-qualified than ARG. + UNIFY_ALLOW_LESS_CV_QUAL: + Allow the deduced ARG to be less cv-qualified than ARG. + UNIFY_ALLOW_DERIVED: + Allow the deduced ARG to be a template base class of ARG, + or a pointer to a template base class of the type pointed to by + ARG. */ + +int +unify (tparms, targs, parm, arg, strict, explicit_mask) tree tparms, targs, parm, arg; - int ntparms, strict; + int strict; int* explicit_mask; { int idx; @@ -5801,11 +6022,16 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) if (arg == parm && !uses_template_parms (parm)) return 0; - /* We can't remove cv-quals when strict. */ - if (strict && TREE_CODE (arg) == TREE_CODE (parm) + /* Immediately reject some pairs that won't unify because of + cv-qualification mismatches. */ + if (TREE_CODE (arg) == TREE_CODE (parm) && TREE_CODE_CLASS (TREE_CODE (arg)) == 't' - && (TYPE_READONLY (arg) < TYPE_READONLY (parm) - || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm))) + /* We check the cv-qualifiers when unifying with template type + parameters below. We want to allow ARG `const T' to unify with + PARM `T' for example, when computing which of two templates + is more specialized, for example. */ + && TREE_CODE (arg) != TEMPLATE_TYPE_PARM + && !check_cv_quals_for_unify (strict, arg, parm)) return 1; switch (TREE_CODE (parm)) @@ -5885,8 +6111,9 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) /* This argument can be deduced. */ - if (unify (tparms, targs, ntparms, t, - TREE_VEC_ELT (argvec, i), strict, explicit_mask)) + if (unify (tparms, targs, t, + TREE_VEC_ELT (argvec, i), + UNIFY_ALLOW_NONE, explicit_mask)) return 1; } } @@ -5895,25 +6122,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) } else { - if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm) - || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm))) + /* If PARM is `const T' and ARG is only `int', we don't have + a match unless we are allowing additional qualification. + If ARG is `const int' and PARM is just `T' that's OK; + that binds `const int' to `T'. */ + if (!check_cv_quals_for_unify (strict | UNIFY_ALLOW_LESS_CV_QUAL, + arg, parm)) return 1; -#if 0 - /* Template type parameters cannot contain cv-quals; i.e. - template <class T> void f (T& a, T& b) will not generate - void f (const int& a, const int& b). */ - if (TYPE_READONLY (arg) > TYPE_READONLY (parm) - || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm)) - return 1; - arg = TYPE_MAIN_VARIANT (arg); -#else - { - int constp = TYPE_READONLY (arg) > TYPE_READONLY (parm); - int volatilep = TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm); - arg = cp_build_type_variant (arg, constp, volatilep); - } -#endif + /* Consider the case where ARG is `const volatile int' and + PARM is `const T'. Then, T should be `volatile int'. */ + arg = + cp_build_type_variant (arg, + TYPE_READONLY (arg) > TYPE_READONLY (parm), + TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm)); } /* Simple cases: Value already set, does match or doesn't. */ @@ -5954,20 +6176,48 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) return 0; case POINTER_TYPE: - if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg)) - return unify (tparms, targs, ntparms, parm, - TYPE_PTRMEMFUNC_FN_TYPE (arg), strict, explicit_mask); + { + int sub_strict; - if (TREE_CODE (arg) != POINTER_TYPE) - return 1; - return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), - strict, explicit_mask); + if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg)) + return (unify (tparms, targs, parm, + TYPE_PTRMEMFUNC_FN_TYPE (arg), strict, + explicit_mask)); + + if (TREE_CODE (arg) != POINTER_TYPE) + return 1; + + /* [temp.deduct.call] + + A can be another pointer or pointer to member type that can + be converted to the deduced A via a qualification + conversion (_conv.qual_). + + We pass down STRICT here rather than UNIFY_ALLOW_NONE. + This will allow for additional cv-qualification of the + pointed-to types if appropriate. In general, this is a bit + too generous; we are only supposed to allow qualification + conversions and this method will allow an ARG of char** and + a deduced ARG of const char**. However, overload + resolution will subsequently invalidate the candidate, so + this is probably OK. */ + sub_strict = strict; + + if (TREE_CODE (TREE_TYPE (arg)) != RECORD_TYPE + || TYPE_PTRMEMFUNC_FLAG (TREE_TYPE (arg))) + /* The derived-to-base conversion only persists through one + level of pointers. */ + sub_strict &= ~UNIFY_ALLOW_DERIVED; + + return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE + (arg), sub_strict, explicit_mask); + } case REFERENCE_TYPE: - if (TREE_CODE (arg) == REFERENCE_TYPE) - arg = TREE_TYPE (arg); - return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, - strict, explicit_mask); + if (TREE_CODE (arg) != REFERENCE_TYPE) + return 1; + return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), + UNIFY_ALLOW_NONE, explicit_mask); case ARRAY_TYPE: if (TREE_CODE (arg) != ARRAY_TYPE) @@ -5976,11 +6226,11 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) != (TYPE_DOMAIN (arg) == NULL_TREE)) return 1; if (TYPE_DOMAIN (parm) != NULL_TREE - && unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), - TYPE_DOMAIN (arg), strict, explicit_mask) != 0) + && unify (tparms, targs, TYPE_DOMAIN (parm), + TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE, explicit_mask) != 0) return 1; - return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), - strict, explicit_mask); + return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), + UNIFY_ALLOW_NONE, explicit_mask); case REAL_TYPE: case COMPLEX_TYPE: @@ -5993,16 +6243,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) if (TREE_CODE (parm) == INTEGER_TYPE) { if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) - && unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm), - TYPE_MIN_VALUE (arg), strict, explicit_mask)) + && unify (tparms, targs, TYPE_MIN_VALUE (parm), + TYPE_MIN_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask)) return 1; if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg) - && unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm), - TYPE_MAX_VALUE (arg), strict, explicit_mask)) + && unify (tparms, targs, TYPE_MAX_VALUE (parm), + TYPE_MAX_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask)) return 1; } else if (TREE_CODE (parm) == REAL_TYPE - && TYPE_MAIN_VARIANT (arg) != TYPE_MAIN_VARIANT (parm)) + /* We use the TYPE_MAIN_VARIANT since we have already + checked cv-qualification at the top of the + function. */ + && !comptypes (TYPE_MAIN_VARIANT (arg), + TYPE_MAIN_VARIANT (parm), 1)) return 1; /* As far as unification is concerned, this wins. Later checks @@ -6027,28 +6281,32 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg)) return 1; for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--) - if (unify (tparms, targs, ntparms, + if (unify (tparms, targs, TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i), - strict, explicit_mask)) + UNIFY_ALLOW_NONE, explicit_mask)) return 1; return 0; } case RECORD_TYPE: if (TYPE_PTRMEMFUNC_FLAG (parm)) - return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm), + return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm), arg, strict, explicit_mask); - /* Allow trivial conversions. */ - if (TREE_CODE (arg) != RECORD_TYPE - || TYPE_READONLY (parm) < TYPE_READONLY (arg) - || TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg)) + if (TREE_CODE (arg) != RECORD_TYPE) return 1; - + if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm)) { tree t = NULL_TREE; - if (! strict) + if (strict & UNIFY_ALLOW_DERIVED) + /* [temp.deduct.call] + + If P is a class, and P has the form template-id, then A + can be a derived class of the deduced A. Likewise, if + P is a pointer to a class of the form template-id, A + can be a pointer to a derived class pointed to by the + deduced A. */ t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg); else if (CLASSTYPE_TEMPLATE_INFO (arg) @@ -6057,40 +6315,38 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) if (! t || t == error_mark_node) return 1; - return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm), - CLASSTYPE_TI_ARGS (t), strict, explicit_mask); + return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm), + CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, + explicit_mask); } - else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg)) + else if (!comptypes (TYPE_MAIN_VARIANT (parm), + TYPE_MAIN_VARIANT (arg), 1)) return 1; return 0; case METHOD_TYPE: - if (TREE_CODE (arg) != METHOD_TYPE) - return 1; - goto check_args; - case FUNCTION_TYPE: - if (TREE_CODE (arg) != FUNCTION_TYPE) + if (TREE_CODE (arg) != TREE_CODE (parm)) return 1; - check_args: - if (unify (tparms, targs, ntparms, TREE_TYPE (parm), - TREE_TYPE (arg), strict, explicit_mask)) + + if (unify (tparms, targs, TREE_TYPE (parm), + TREE_TYPE (arg), UNIFY_ALLOW_NONE, explicit_mask)) return 1; return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), TYPE_ARG_TYPES (arg), 1, - strict, 0, explicit_mask); + DEDUCE_EXACT, 0, explicit_mask); case OFFSET_TYPE: if (TREE_CODE (arg) != OFFSET_TYPE) return 1; - if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm), - TYPE_OFFSET_BASETYPE (arg), strict, explicit_mask)) + if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm), + TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, explicit_mask)) return 1; - return unify (tparms, targs, ntparms, TREE_TYPE (parm), - TREE_TYPE (arg), strict, explicit_mask); + return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), + UNIFY_ALLOW_NONE, explicit_mask); case CONST_DECL: - if (arg != decl_constant_value (parm)) + if (arg != decl_constant_value (parm)) return 1; return 0; @@ -6138,13 +6394,13 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) integer_type_node, arg, t2)); - return unify (tparms, targs, ntparms, t1, t, - strict, explicit_mask); + return unify (tparms, targs, t1, t, UNIFY_ALLOW_NONE, + explicit_mask); } if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) /* Good, we mangaged to simplify the exression. */ - return unify (tparms, targs, ntparms, t, arg, strict, + return unify (tparms, targs, t, arg, UNIFY_ALLOW_NONE, explicit_mask); else /* Bad, we couldn't simplify this. Assume it doesn't @@ -6282,7 +6538,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype) i = fn_type_unification (fn, explicit_args, targs, decl_arg_types, TREE_TYPE (TREE_TYPE (decl)), - 1, + DEDUCE_EXACT, extra_fn_arg); if (i != 0) @@ -6335,9 +6591,9 @@ get_class_bindings (tparms, parms, args, outer_args) for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { - switch (unify (tparms, vec, ntparms, + switch (unify (tparms, vec, TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i), - 1, 0)) + UNIFY_ALLOW_NONE, 0)) { case 0: break; @@ -6628,6 +6884,75 @@ do_type_instantiation (t, storage) } } +/* Given a function DECL, which is a specialization of TEMP, modify + DECL to be a re-instantiation of TEMPL with the same template + arguments. + + One reason for doing this is a scenario like this: + + template <class T> + void f(const T&, int i); + + void g() { f(3, 7); } + + template <class T> + void f(const T& t, const int i) { } + + Note that when the template is first instantiated, with + instantiate_template, the resulting DECL will have no name for the + first parameter, and the wrong type for the second. So, when we go + to instantiate the DECL, we regenerate it. */ + +void +regenerate_decl_from_template (decl, tmpl) + tree decl; + tree tmpl; +{ + tree args; + tree save_ti; + tree code_pattern; + tree new_decl; + + args = DECL_TI_ARGS (decl); + code_pattern = DECL_TEMPLATE_RESULT (tmpl); + + /* Trick tsubst into giving us a new decl. CODE_PATTERN must be the + most distant ancestor of DECL, since that's the one that will + actually be altered by a redefinition. */ + save_ti = DECL_TEMPLATE_INFO (code_pattern); + DECL_TEMPLATE_INFO (code_pattern) = NULL_TREE; + new_decl = tsubst (code_pattern, args, NULL_TREE); + SET_DECL_IMPLICIT_INSTANTIATION (new_decl); + DECL_TEMPLATE_INFO (code_pattern) = save_ti; + + if (TREE_CODE (decl) == VAR_DECL) + { + /* Set up DECL_INITIAL, since tsubst doesn't. */ + pushclass (DECL_CONTEXT (decl), 2); + DECL_INITIAL (new_decl) = + tsubst_expr (DECL_INITIAL (code_pattern), args, + DECL_TI_TEMPLATE (decl)); + popclass (1); + } + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + /* Convince duplicate_decls to use the DECL_ARGUMENTS from the + new decl. */ + DECL_INITIAL (new_decl) = error_mark_node; + + if (DECL_TEMPLATE_SPECIALIZATION (new_decl) + && !DECL_TEMPLATE_INFO (new_decl)) + /* Set up the information about what is being specialized. */ + DECL_TEMPLATE_INFO (new_decl) = DECL_TEMPLATE_INFO (decl); + } + + duplicate_decls (new_decl, decl); + + if (TREE_CODE (decl) == FUNCTION_DECL) + DECL_INITIAL (new_decl) = NULL_TREE; +} + /* Produce the definition of D, a _DECL generated from a template. */ tree @@ -6637,7 +6962,7 @@ instantiate_decl (d) tree ti = DECL_TEMPLATE_INFO (d); tree tmpl = TI_TEMPLATE (ti); tree args = TI_ARGS (ti); - tree td, temp; + tree td; tree decl_pattern, code_pattern; tree save_ti; int nested = in_function_p (); @@ -6747,38 +7072,7 @@ instantiate_decl (d) lineno = DECL_SOURCE_LINE (d); input_filename = DECL_SOURCE_FILE (d); - /* Trick tsubst into giving us a new decl in case the template changed. */ - save_ti = DECL_TEMPLATE_INFO (decl_pattern); - DECL_TEMPLATE_INFO (decl_pattern) = NULL_TREE; - /* decl_pattern has all but one level of template parms bound. Only pass - in that one level of args. */ - temp = innermost_args (args, DECL_TEMPLATE_SPECIALIZATION (decl_pattern)); - td = tsubst (decl_pattern, temp, tmpl); - SET_DECL_IMPLICIT_INSTANTIATION (td); - DECL_TEMPLATE_INFO (decl_pattern) = save_ti; - - /* And set up DECL_INITIAL, since tsubst doesn't. */ - if (TREE_CODE (td) == VAR_DECL) - { - pushclass (DECL_CONTEXT (d), 2); - DECL_INITIAL (td) = tsubst_expr (DECL_INITIAL (code_pattern), args, - tmpl); - popclass (1); - } - - if (TREE_CODE (d) == FUNCTION_DECL) - { - /* Convince duplicate_decls to use the DECL_ARGUMENTS from the - new decl. */ - DECL_INITIAL (td) = error_mark_node; - - if (DECL_TEMPLATE_SPECIALIZATION (td) && !DECL_TEMPLATE_INFO (td)) - /* Set up the information about what is being specialized. */ - DECL_TEMPLATE_INFO (td) = DECL_TEMPLATE_INFO (d); - } - duplicate_decls (td, d); - if (TREE_CODE (d) == FUNCTION_DECL) - DECL_INITIAL (td) = 0; + regenerate_decl_from_template (d, td); if (TREE_CODE (d) == VAR_DECL) { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/conv1.C b/gcc/testsuite/g++.old-deja/g++.pt/conv1.C new file mode 100644 index 00000000000..19e433e2f70 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/conv1.C @@ -0,0 +1,19 @@ +// Build don't link: + +template <class T> +struct S1 {}; + +struct S2 +{ + template <class T> + operator S1<T>*(); +}; + +struct D: public S1<int> { +}; + +void f() +{ + S2 s; + (D*) s; // ERROR - cannot convert +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass9.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass9.C new file mode 100644 index 00000000000..824ee76f0c5 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass9.C @@ -0,0 +1,32 @@ +// Build don't link: + +template <class T> +struct S1 +{ + template <class U> + struct S2 + { + S2(U); + + void g() + { + S2<U> s2u (u); + } + + U& u; + }; + + template <class U> + void f(U u) + { + S2<U> s2u(u); + s2u.g(); + } +}; + +void g() +{ + S1<int> s1; + s1.f(3.0); +} + diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify3.C b/gcc/testsuite/g++.old-deja/g++.pt/unify3.C new file mode 100644 index 00000000000..847dc0eda38 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/unify3.C @@ -0,0 +1,22 @@ +// Build don't link: + +template <class T1, class T2> +struct ComputeBinaryType +{ +}; + +template<class T1> +struct ComputeBinaryType<T1, double> { + void g(); +}; + +template<class T1> +struct ComputeBinaryType<T1&, double> { + void h(); +}; + +void f() +{ + ComputeBinaryType<double, double> cb; + cb.g(); +} |