Commit 830bfa74 by Mark Mitchell Committed by Mark Mitchell

call.c (add_template_candidate): Adjust for changes to fn_type_unification.

	* 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.

From-SVN: r19663
parent 89ad74a3
Mon May 11 07:16:30 1998 Mark Mitchell <mmitchell@usa.net> 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. * lex.c (yyprint): Remove TYPENAME_ELLIPSIS.
* parse.h: Regenerated. * parse.h: Regenerated.
* parse.c: Really regenerated. * parse.c: Really regenerated.
......
...@@ -61,9 +61,11 @@ static tree build_this PROTO((tree)); ...@@ -61,9 +61,11 @@ static tree build_this PROTO((tree));
static struct z_candidate * splice_viable PROTO((struct z_candidate *)); static struct z_candidate * splice_viable PROTO((struct z_candidate *));
static int any_viable PROTO((struct z_candidate *)); static int any_viable PROTO((struct z_candidate *));
static struct z_candidate * add_template_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 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 static struct z_candidate * add_template_conv_candidate
PROTO((struct z_candidate *, tree, tree, tree, tree)); PROTO((struct z_candidate *, tree, tree, tree, tree));
static struct z_candidate * add_builtin_candidates static struct z_candidate * add_builtin_candidates
...@@ -1865,11 +1867,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags) ...@@ -1865,11 +1867,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
static struct z_candidate* static struct z_candidate*
add_template_candidate_real (candidates, tmpl, explicit_targs, add_template_candidate_real (candidates, tmpl, explicit_targs,
arglist, return_type, flags, arglist, return_type, flags,
obj) obj, strict)
struct z_candidate *candidates; struct z_candidate *candidates;
tree tmpl, explicit_targs, arglist, return_type; tree tmpl, explicit_targs, arglist, return_type;
int flags; int flags;
tree obj; tree obj;
unification_kind_t strict;
{ {
int ntparms = DECL_NTPARMS (tmpl); int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_scratch_vec (ntparms); tree targs = make_scratch_vec (ntparms);
...@@ -1878,7 +1881,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs, ...@@ -1878,7 +1881,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
tree fn; tree fn;
i = fn_type_unification (tmpl, explicit_targs, targs, arglist, i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
return_type, 0, NULL_TREE); return_type, strict, NULL_TREE);
if (i != 0) if (i != 0)
return candidates; return candidates;
...@@ -1920,14 +1923,16 @@ add_template_candidate_real (candidates, tmpl, explicit_targs, ...@@ -1920,14 +1923,16 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
static struct z_candidate * static struct z_candidate *
add_template_candidate (candidates, tmpl, explicit_targs, add_template_candidate (candidates, tmpl, explicit_targs,
arglist, return_type, flags) arglist, return_type, flags, strict)
struct z_candidate *candidates; struct z_candidate *candidates;
tree tmpl, explicit_targs, arglist, return_type; tree tmpl, explicit_targs, arglist, return_type;
int flags; int flags;
unification_kind_t strict;
{ {
return return
add_template_candidate_real (candidates, tmpl, explicit_targs, 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) ...@@ -1938,7 +1943,7 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
{ {
return return
add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist, 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) ...@@ -2058,7 +2063,8 @@ build_user_type_conversion_1 (totype, expr, flags)
templates = scratch_tree_cons (NULL_TREE, ctor, templates); templates = scratch_tree_cons (NULL_TREE, ctor, templates);
candidates = candidates =
add_template_candidate (candidates, ctor, add_template_candidate (candidates, ctor,
NULL_TREE, args, NULL_TREE, flags); NULL_TREE, args, NULL_TREE, flags,
DEDUCE_CALL);
} }
else else
candidates = add_function_candidate (candidates, ctor, candidates = add_function_candidate (candidates, ctor,
...@@ -2107,7 +2113,8 @@ build_user_type_conversion_1 (totype, expr, flags) ...@@ -2107,7 +2113,8 @@ build_user_type_conversion_1 (totype, expr, flags)
templates = scratch_tree_cons (NULL_TREE, fn, templates); templates = scratch_tree_cons (NULL_TREE, fn, templates);
candidates = candidates =
add_template_candidate (candidates, fn, NULL_TREE, add_template_candidate (candidates, fn, NULL_TREE,
args, totype, flags); args, totype, flags,
DEDUCE_CONV);
} }
else else
candidates = add_function_candidate (candidates, fn, candidates = add_function_candidate (candidates, fn,
...@@ -2261,7 +2268,7 @@ build_new_function_call (fn, args) ...@@ -2261,7 +2268,7 @@ build_new_function_call (fn, args)
templates = scratch_tree_cons (NULL_TREE, t, templates); templates = scratch_tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate candidates = add_template_candidate
(candidates, t, explicit_targs, args, NULL_TREE, (candidates, t, explicit_targs, args, NULL_TREE,
LOOKUP_NORMAL); LOOKUP_NORMAL, DEDUCE_CALL);
} }
else if (! template_only) else if (! template_only)
candidates = add_function_candidate candidates = add_function_candidate
...@@ -2346,7 +2353,7 @@ build_object_call (obj, args) ...@@ -2346,7 +2353,7 @@ build_object_call (obj, args)
candidates candidates
= add_template_candidate (candidates, fn, NULL_TREE, = add_template_candidate (candidates, fn, NULL_TREE,
mem_args, NULL_TREE, mem_args, NULL_TREE,
LOOKUP_NORMAL); LOOKUP_NORMAL, DEDUCE_CALL);
} }
else else
candidates = add_function_candidate candidates = add_function_candidate
...@@ -2603,7 +2610,7 @@ build_new_op (code, flags, arg1, arg2, arg3) ...@@ -2603,7 +2610,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
candidates candidates
= add_template_candidate (candidates, fn, NULL_TREE, = add_template_candidate (candidates, fn, NULL_TREE,
arglist, TREE_TYPE (fnname), arglist, TREE_TYPE (fnname),
flags); flags, DEDUCE_CALL);
} }
else else
candidates = add_function_candidate (candidates, fn, arglist, flags); candidates = add_function_candidate (candidates, fn, arglist, flags);
...@@ -2639,7 +2646,7 @@ build_new_op (code, flags, arg1, arg2, arg3) ...@@ -2639,7 +2646,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
candidates candidates
= add_template_candidate (candidates, fn, NULL_TREE, = add_template_candidate (candidates, fn, NULL_TREE,
this_arglist, TREE_TYPE (fnname), this_arglist, TREE_TYPE (fnname),
flags); flags, DEDUCE_CALL);
} }
else else
candidates = add_function_candidate candidates = add_function_candidate
...@@ -3591,7 +3598,7 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -3591,7 +3598,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
candidates = candidates =
add_template_candidate (candidates, t, explicit_targs, add_template_candidate (candidates, t, explicit_targs,
this_arglist, this_arglist,
TREE_TYPE (name), flags); TREE_TYPE (name), flags, DEDUCE_CALL);
} }
else if (! template_only) else if (! template_only)
candidates = add_function_candidate (candidates, t, candidates = add_function_candidate (candidates, t,
......
...@@ -5151,7 +5151,7 @@ instantiate_type (lhstype, rhs, complain) ...@@ -5151,7 +5151,7 @@ instantiate_type (lhstype, rhs, complain)
i = type_unification i = type_unification
(DECL_INNERMOST_TEMPLATE_PARMS (elem), t, (DECL_INNERMOST_TEMPLATE_PARMS (elem), t,
TYPE_ARG_TYPES (TREE_TYPE (elem)), 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 (i == 0)
{ {
if (save_elem) if (save_elem)
......
...@@ -1683,6 +1683,16 @@ extern tree null_node; ...@@ -1683,6 +1683,16 @@ extern tree null_node;
/* in pt.c */ /* 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 tree current_template_parms;
extern HOST_WIDE_INT processing_template_decl; extern HOST_WIDE_INT processing_template_decl;
extern tree last_tree; extern tree last_tree;
...@@ -2504,8 +2514,8 @@ extern int uses_template_parms PROTO((tree)); ...@@ -2504,8 +2514,8 @@ extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template 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 void overload_template_name PROTO((tree));
extern int fn_type_unification PROTO((tree, tree, tree, tree, tree, int, tree)); 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, int, int)); extern int type_unification PROTO((tree, tree, tree, tree, tree, unification_kind_t, int));
struct tinst_level *tinst_for_decl PROTO((void)); struct tinst_level *tinst_for_decl PROTO((void));
extern void mark_decl_instantiated PROTO((tree, int)); extern void mark_decl_instantiated PROTO((tree, int));
extern int more_specialized PROTO((tree, tree, tree)); extern int more_specialized PROTO((tree, tree, tree));
......
...@@ -893,7 +893,7 @@ build_overload_identifier (name) ...@@ -893,7 +893,7 @@ build_overload_identifier (name)
{ {
tree template, parmlist, arglist, tname; tree template, parmlist, arglist, tname;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
arglist = TREE_VALUE (template); arglist = innermost_args (TREE_VALUE (template), 0);
template = TREE_PURPOSE (template); template = TREE_PURPOSE (template);
tname = DECL_NAME (template); tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
......
...@@ -70,7 +70,12 @@ static tree saved_trees; ...@@ -70,7 +70,12 @@ static tree saved_trees;
#define obstack_chunk_alloc xmalloc #define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free #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 void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree)); static int push_tinst_level PROTO((tree));
static tree classtype_mangled_name PROTO((tree)); static tree classtype_mangled_name PROTO((tree));
...@@ -81,8 +86,10 @@ static tree get_class_bindings PROTO((tree, tree, tree, 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 coerce_template_parms PROTO((tree, tree, tree, int, int, int));
static tree tsubst_enum PROTO((tree, tree, tree *)); static tree tsubst_enum PROTO((tree, tree, tree *));
static tree add_to_template_args PROTO((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, 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 tree complete_template_args PROTO((tree, tree, int));
static void note_template_header PROTO((int)); static void note_template_header PROTO((int));
static tree maybe_fold_nontype_arg PROTO((tree)); static tree maybe_fold_nontype_arg PROTO((tree));
...@@ -104,6 +111,9 @@ static tree tsubst_friend_class PROTO((tree, tree)); ...@@ -104,6 +111,9 @@ static tree tsubst_friend_class PROTO((tree, tree));
static tree get_bindings_real PROTO((tree, tree, tree, int)); static tree get_bindings_real PROTO((tree, tree, tree, int));
static int template_decl_level PROTO((tree)); static int template_decl_level PROTO((tree));
static tree maybe_get_template_decl_from_type_decl 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 /* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is using TEMPLATE_PARAMETERS as its innermost parameter list) is
...@@ -360,7 +370,7 @@ is_member_template (t) ...@@ -360,7 +370,7 @@ is_member_template (t)
} }
/* Return a new template argument vector which contains all of ARGS /* 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 innermost set of arguments the EXTRA_ARGS. If UNBOUND_ONLY, we
are only interested in unbound template arguments, not arguments from are only interested in unbound template arguments, not arguments from
enclosing templates that have been instantiated already. */ enclosing templates that have been instantiated already. */
...@@ -373,10 +383,16 @@ complete_template_args (tmpl, extra_args, unbound_only) ...@@ -373,10 +383,16 @@ complete_template_args (tmpl, extra_args, unbound_only)
/* depth is the number of levels of enclosing args we're adding. */ /* depth is the number of levels of enclosing args we're adding. */
int depth, i; int depth, i;
tree args, new_args, spec_args = NULL_TREE; 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 (tmpl) == TEMPLATE_DECL, 0);
my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 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) if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only)
{ {
/* A specialization of a member template of a template class shows up /* A specialization of a member template of a template class shows up
...@@ -405,7 +421,7 @@ complete_template_args (tmpl, extra_args, unbound_only) ...@@ -405,7 +421,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
template args. */ template args. */
depth = 0; 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) if (depth == 1)
TREE_VEC_ELT (new_args, 0) = args; TREE_VEC_ELT (new_args, 0) = args;
...@@ -427,7 +443,7 @@ complete_template_args (tmpl, extra_args, unbound_only) ...@@ -427,7 +443,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
if (depth == 0) if (depth == 0)
return extra_args; 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 /* If this isn't a member template, extra_args is for the innermost
template class, so skip over it. */ template class, so skip over it. */
...@@ -447,10 +463,14 @@ complete_template_args (tmpl, extra_args, unbound_only) ...@@ -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) if (spec_args)
TREE_VEC_ELT (new_args, depth + 1) = spec_args; TREE_VEC_ELT (new_args, depth) = spec_args;
return new_args; return new_args;
} }
...@@ -776,7 +796,7 @@ determine_specialization (template_id, decl, targs_out, ...@@ -776,7 +796,7 @@ determine_specialization (template_id, decl, targs_out,
NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE,
targs_in, targs_in,
1, 1); DEDUCE_EXACT, 1);
if (i == 0) if (i == 0)
/* Unification was successful. */ /* Unification was successful. */
...@@ -1814,8 +1834,15 @@ push_template_decl_real (decl, is_friend) ...@@ -1814,8 +1834,15 @@ push_template_decl_real (decl, is_friend)
cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t)); cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
} }
} }
/* Get the innermost set of template arguments. */ /* Get the innermost set of template arguments. We don't do this
args = innermost_args (args, 0); 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; DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl); TREE_TYPE (tmpl) = TREE_TYPE (decl);
...@@ -2904,11 +2931,36 @@ lookup_template_class (d1, arglist, in_decl, context) ...@@ -2904,11 +2931,36 @@ lookup_template_class (d1, arglist, in_decl, context)
|| (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template))) || (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template)))
== FUNCTION_DECL)) == FUNCTION_DECL))
{ {
tree arglist_for_mangling;
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
arglist = coerce_template_parms (parmlist, arglist, template, if (/* ARGLIST can be NULL_TREE if there are default arguments. */
1, 1, 0); arglist != NULL_TREE
if (arglist == error_mark_node) && 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; return error_mark_node;
if (uses_template_parms (arglist)) if (uses_template_parms (arglist))
{ {
...@@ -2937,10 +2989,15 @@ lookup_template_class (d1, arglist, in_decl, context) ...@@ -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. */ /* FIXME avoid duplication. */
mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1), mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
parmlist, parmlist,
arglist, arglist_for_mangling,
id_context); id_context);
id = get_identifier (mangled_name); id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = d1; IDENTIFIER_TEMPLATE (id) = d1;
...@@ -3875,11 +3932,46 @@ innermost_args (args, is_spec) ...@@ -3875,11 +3932,46 @@ innermost_args (args, is_spec)
tree args; tree args;
int is_spec; 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 TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
return args; 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 /* Take the tree structure T and replace template parameters used therein
with the argument vector ARGS. IN_DECL is an associated decl for with the argument vector ARGS. IN_DECL is an associated decl for
diagnostics. diagnostics.
...@@ -3907,7 +3999,9 @@ tsubst (t, args, in_decl) ...@@ -3907,7 +3999,9 @@ tsubst (t, args, in_decl)
type = TREE_TYPE (t); type = TREE_TYPE (t);
if (type == unknown_type_node) if (type == unknown_type_node)
my_friendly_abort (42); my_friendly_abort (42);
if (type && TREE_CODE (t) != FUNCTION_DECL if (type && TREE_CODE (t) != FUNCTION_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE
&& TREE_CODE (t) != TYPENAME_TYPE && TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != TEMPLATE_DECL && TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE) && TREE_CODE (t) != IDENTIFIER_NODE)
...@@ -3932,14 +4026,33 @@ tsubst (t, args, in_decl) ...@@ -3932,14 +4026,33 @@ tsubst (t, args, in_decl)
tree context; tree context;
tree r; tree r;
context = if (TYPE_CONTEXT (t) != NULL_TREE)
TYPE_CONTEXT (t) {
? tsubst (TYPE_CONTEXT (t), args, in_decl) : 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); r = lookup_template_class (t, argvec, in_decl, context);
return cp_build_type_variant (r, TYPE_READONLY (t), return cp_build_type_variant (r, TYPE_READONLY (t),
TYPE_VOLATILE (t)); TYPE_VOLATILE (t));
} }
/* else fall through */ /* else fall through */
...@@ -4208,7 +4321,7 @@ tsubst (t, args, in_decl) ...@@ -4208,7 +4321,7 @@ tsubst (t, args, in_decl)
} }
if (PRIMARY_TEMPLATE_P (t)) 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. */ /* We don't partially instantiate partial specializations. */
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
...@@ -4646,30 +4759,8 @@ tsubst (t, args, in_decl) ...@@ -4646,30 +4759,8 @@ tsubst (t, args, in_decl)
} }
/* Otherwise, a vector of template arguments. */ /* Otherwise, a vector of template arguments. */
{ return tsubst_template_arg_vector (t, 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++)
{
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;
t = make_tree_vec (len);
for (i = 0; i < len; i++)
TREE_VEC_ELT (t, i) = elts[i];
return t;
}
case POINTER_TYPE: case POINTER_TYPE:
case REFERENCE_TYPE: case REFERENCE_TYPE:
{ {
...@@ -5493,7 +5584,7 @@ int ...@@ -5493,7 +5584,7 @@ int
fn_type_unification (fn, explicit_targs, targs, args, return_type, fn_type_unification (fn, explicit_targs, targs, args, return_type,
strict, extra_fn_arg) strict, extra_fn_arg)
tree fn, explicit_targs, targs, args, return_type; tree fn, explicit_targs, targs, args, return_type;
int strict; unification_kind_t strict;
tree extra_fn_arg; tree extra_fn_arg;
{ {
int i; int i;
...@@ -5553,22 +5644,37 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, ...@@ -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 a function or method parameter of a function template), so don't zero
out targs and don't fail on an incomplete match. out targs and don't fail on an incomplete match.
If STRICT is 1, the match must be exact (for casts of overloaded The parameter STRICT is one of:
addresses, explicit instantiation, and more_specialized). */
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 int
type_unification (tparms, targs, parms, args, targs_in, type_unification (tparms, targs, parms, args, targs_in,
strict, allow_incomplete) strict, allow_incomplete)
tree tparms, targs, parms, args, targs_in; 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; tree arg;
int* explicit_mask; int* explicit_mask;
int i; 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; TREE_VEC_ELT (targs, i) = NULL_TREE;
if (targs_in != NULL_TREE) if (targs_in != NULL_TREE)
...@@ -5596,10 +5702,84 @@ type_unification (tparms, targs, parms, args, targs_in, ...@@ -5596,10 +5702,84 @@ type_unification (tparms, targs, parms, args, targs_in,
else else
explicit_mask = 0; explicit_mask = 0;
r = type_unification_real (tparms, targs, parms, args, 0, return
strict, allow_incomplete, explicit_mask); 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 /* Like type_unfication. EXPLICIT_MASK, if non-NULL, is an array of
...@@ -5610,12 +5790,15 @@ static int ...@@ -5610,12 +5790,15 @@ static int
type_unification_real (tparms, targs, parms, args, subr, type_unification_real (tparms, targs, parms, args, subr,
strict, allow_incomplete, explicit_mask) strict, allow_incomplete, explicit_mask)
tree tparms, targs, parms, args; tree tparms, targs, parms, args;
int subr, strict, allow_incomplete; int subr;
unification_kind_t strict;
int allow_incomplete;
int* explicit_mask; int* explicit_mask;
{ {
tree parm, arg; tree parm, arg;
int i; int i;
int ntparms = TREE_VEC_LENGTH (tparms); int ntparms = TREE_VEC_LENGTH (tparms);
int sub_strict;
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289); my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
my_friendly_assert (parms == NULL_TREE my_friendly_assert (parms == NULL_TREE
...@@ -5626,6 +5809,24 @@ type_unification_real (tparms, targs, parms, args, subr, ...@@ -5626,6 +5809,24 @@ type_unification_real (tparms, targs, parms, args, subr,
my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291); my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292); 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 while (parms
&& parms != void_list_node && parms != void_list_node
&& args && args
...@@ -5657,7 +5858,7 @@ type_unification_real (tparms, targs, parms, args, subr, ...@@ -5657,7 +5858,7 @@ type_unification_real (tparms, targs, parms, args, subr,
arg = NULL_TREE; arg = NULL_TREE;
} }
if (strict) if (strict == DEDUCE_EXACT)
{ {
if (comptypes (parm, type, 1)) if (comptypes (parm, type, 1))
continue; continue;
...@@ -5683,20 +5884,20 @@ type_unification_real (tparms, targs, parms, args, subr, ...@@ -5683,20 +5884,20 @@ type_unification_real (tparms, targs, parms, args, subr,
if (TREE_CODE (arg) == OVERLOAD if (TREE_CODE (arg) == OVERLOAD
&& TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL) && TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL)
{ {
int ntparms;
tree targs; tree targs;
tree arg_type;
/* Have to back unify here */ /* Have to back unify here */
arg = OVL_FUNCTION (arg); arg = OVL_FUNCTION (arg);
ntparms = DECL_NTPARMS (arg); targs = make_scratch_vec (DECL_NTPARMS (arg));
targs = make_scratch_vec (ntparms); arg_type = TREE_TYPE (arg);
maybe_adjust_types_for_deduction (strict, &parm, &arg_type);
parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE); parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE);
return return
type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg), type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
targs, targs, arg_type, parm, NULL_TREE,
TYPE_ARG_TYPES (TREE_TYPE (arg)), DEDUCE_EXACT, allow_incomplete);
parm, NULL_TREE, strict,
allow_incomplete);
} }
arg = TREE_TYPE (arg); arg = TREE_TYPE (arg);
} }
...@@ -5707,21 +5908,10 @@ type_unification_real (tparms, targs, parms, args, subr, ...@@ -5707,21 +5908,10 @@ type_unification_real (tparms, targs, parms, args, subr,
arg = ptr_type_node; arg = ptr_type_node;
} }
if (! subr && TREE_CODE (arg) == REFERENCE_TYPE) if (!subr)
arg = TREE_TYPE (arg); maybe_adjust_types_for_deduction (strict, &parm, &arg);
if (! subr && TREE_CODE (parm) != REFERENCE_TYPE) switch (unify (tparms, targs, parm, arg, sub_strict,
{
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,
explicit_mask)) explicit_mask))
{ {
case 0: case 0:
...@@ -5771,12 +5961,43 @@ template_decl_level (decl) ...@@ -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 int
unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) 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; tree tparms, targs, parm, arg;
int ntparms, strict; int strict;
int* explicit_mask; int* explicit_mask;
{ {
int idx; int idx;
...@@ -5801,11 +6022,16 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -5801,11 +6022,16 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
if (arg == parm && !uses_template_parms (parm)) if (arg == parm && !uses_template_parms (parm))
return 0; return 0;
/* We can't remove cv-quals when strict. */ /* Immediately reject some pairs that won't unify because of
if (strict && TREE_CODE (arg) == TREE_CODE (parm) cv-qualification mismatches. */
if (TREE_CODE (arg) == TREE_CODE (parm)
&& TREE_CODE_CLASS (TREE_CODE (arg)) == 't' && TREE_CODE_CLASS (TREE_CODE (arg)) == 't'
&& (TYPE_READONLY (arg) < TYPE_READONLY (parm) /* We check the cv-qualifiers when unifying with template type
|| TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm))) 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; return 1;
switch (TREE_CODE (parm)) switch (TREE_CODE (parm))
...@@ -5885,8 +6111,9 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -5885,8 +6111,9 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
/* This argument can be deduced. */ /* This argument can be deduced. */
if (unify (tparms, targs, ntparms, t, if (unify (tparms, targs, t,
TREE_VEC_ELT (argvec, i), strict, explicit_mask)) TREE_VEC_ELT (argvec, i),
UNIFY_ALLOW_NONE, explicit_mask))
return 1; return 1;
} }
} }
...@@ -5895,25 +6122,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -5895,25 +6122,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
} }
else else
{ {
if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm) /* If PARM is `const T' and ARG is only `int', we don't have
|| TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm))) 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; return 1;
#if 0 /* Consider the case where ARG is `const volatile int' and
/* Template type parameters cannot contain cv-quals; i.e. PARM is `const T'. Then, T should be `volatile int'. */
template <class T> void f (T& a, T& b) will not generate arg =
void f (const int& a, const int& b). */ cp_build_type_variant (arg,
if (TYPE_READONLY (arg) > TYPE_READONLY (parm) TYPE_READONLY (arg) > TYPE_READONLY (parm),
|| TYPE_VOLATILE (arg) > TYPE_VOLATILE (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
} }
/* Simple cases: Value already set, does match or doesn't. */ /* Simple cases: Value already set, does match or doesn't. */
...@@ -5954,20 +6176,48 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -5954,20 +6176,48 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
return 0; return 0;
case POINTER_TYPE: case POINTER_TYPE:
if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg)) {
return unify (tparms, targs, ntparms, parm, int sub_strict;
TYPE_PTRMEMFUNC_FN_TYPE (arg), strict, explicit_mask);
if (TREE_CODE (arg) != POINTER_TYPE) if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
return 1; return (unify (tparms, targs, parm,
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), TYPE_PTRMEMFUNC_FN_TYPE (arg), strict,
strict, explicit_mask); 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: case REFERENCE_TYPE:
if (TREE_CODE (arg) == REFERENCE_TYPE) if (TREE_CODE (arg) != REFERENCE_TYPE)
arg = TREE_TYPE (arg); return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict, explicit_mask); UNIFY_ALLOW_NONE, explicit_mask);
case ARRAY_TYPE: case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE) if (TREE_CODE (arg) != ARRAY_TYPE)
...@@ -5976,11 +6226,11 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -5976,11 +6226,11 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
!= (TYPE_DOMAIN (arg) == NULL_TREE)) != (TYPE_DOMAIN (arg) == NULL_TREE))
return 1; return 1;
if (TYPE_DOMAIN (parm) != NULL_TREE if (TYPE_DOMAIN (parm) != NULL_TREE
&& unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), && unify (tparms, targs, TYPE_DOMAIN (parm),
TYPE_DOMAIN (arg), strict, explicit_mask) != 0) TYPE_DOMAIN (arg), UNIFY_ALLOW_NONE, explicit_mask) != 0)
return 1; return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict, explicit_mask); UNIFY_ALLOW_NONE, explicit_mask);
case REAL_TYPE: case REAL_TYPE:
case COMPLEX_TYPE: case COMPLEX_TYPE:
...@@ -5993,16 +6243,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -5993,16 +6243,20 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
if (TREE_CODE (parm) == INTEGER_TYPE) if (TREE_CODE (parm) == INTEGER_TYPE)
{ {
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
&& unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm), && unify (tparms, targs, TYPE_MIN_VALUE (parm),
TYPE_MIN_VALUE (arg), strict, explicit_mask)) TYPE_MIN_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1; return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg) if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
&& unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm), && unify (tparms, targs, TYPE_MAX_VALUE (parm),
TYPE_MAX_VALUE (arg), strict, explicit_mask)) TYPE_MAX_VALUE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1; return 1;
} }
else if (TREE_CODE (parm) == REAL_TYPE 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; return 1;
/* As far as unification is concerned, this wins. Later checks /* As far as unification is concerned, this wins. Later checks
...@@ -6027,28 +6281,32 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -6027,28 +6281,32 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg)) if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
return 1; return 1;
for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--) 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), TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
strict, explicit_mask)) UNIFY_ALLOW_NONE, explicit_mask))
return 1; return 1;
return 0; return 0;
} }
case RECORD_TYPE: case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm)) 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); arg, strict, explicit_mask);
/* Allow trivial conversions. */ if (TREE_CODE (arg) != RECORD_TYPE)
if (TREE_CODE (arg) != RECORD_TYPE
|| TYPE_READONLY (parm) < TYPE_READONLY (arg)
|| TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
return 1; return 1;
if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm)) if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
{ {
tree t = NULL_TREE; 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); t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
else if else if
(CLASSTYPE_TEMPLATE_INFO (arg) (CLASSTYPE_TEMPLATE_INFO (arg)
...@@ -6057,40 +6315,38 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -6057,40 +6315,38 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
if (! t || t == error_mark_node) if (! t || t == error_mark_node)
return 1; return 1;
return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm), return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
CLASSTYPE_TI_ARGS (t), strict, explicit_mask); 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 1;
return 0; return 0;
case METHOD_TYPE: case METHOD_TYPE:
if (TREE_CODE (arg) != METHOD_TYPE)
return 1;
goto check_args;
case FUNCTION_TYPE: case FUNCTION_TYPE:
if (TREE_CODE (arg) != FUNCTION_TYPE) if (TREE_CODE (arg) != TREE_CODE (parm))
return 1; return 1;
check_args:
if (unify (tparms, targs, ntparms, TREE_TYPE (parm), if (unify (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), strict, explicit_mask)) TREE_TYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1; return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), 1, TYPE_ARG_TYPES (arg), 1,
strict, 0, explicit_mask); DEDUCE_EXACT, 0, explicit_mask);
case OFFSET_TYPE: case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE) if (TREE_CODE (arg) != OFFSET_TYPE)
return 1; return 1;
if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm), if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
TYPE_OFFSET_BASETYPE (arg), strict, explicit_mask)) TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE, explicit_mask))
return 1; return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
TREE_TYPE (arg), strict, explicit_mask); UNIFY_ALLOW_NONE, explicit_mask);
case CONST_DECL: case CONST_DECL:
if (arg != decl_constant_value (parm)) if (arg != decl_constant_value (parm))
return 1; return 1;
return 0; return 0;
...@@ -6138,13 +6394,13 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask) ...@@ -6138,13 +6394,13 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
integer_type_node, integer_type_node,
arg, t2)); arg, t2));
return unify (tparms, targs, ntparms, t1, t, return unify (tparms, targs, t1, t, UNIFY_ALLOW_NONE,
strict, explicit_mask); explicit_mask);
} }
if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) if (!IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc)))
/* Good, we mangaged to simplify the exression. */ /* 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); explicit_mask);
else else
/* Bad, we couldn't simplify this. Assume it doesn't /* Bad, we couldn't simplify this. Assume it doesn't
...@@ -6282,7 +6538,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype) ...@@ -6282,7 +6538,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
i = fn_type_unification (fn, explicit_args, targs, i = fn_type_unification (fn, explicit_args, targs,
decl_arg_types, decl_arg_types,
TREE_TYPE (TREE_TYPE (decl)), TREE_TYPE (TREE_TYPE (decl)),
1, DEDUCE_EXACT,
extra_fn_arg); extra_fn_arg);
if (i != 0) if (i != 0)
...@@ -6335,9 +6591,9 @@ get_class_bindings (tparms, parms, args, outer_args) ...@@ -6335,9 +6591,9 @@ get_class_bindings (tparms, parms, args, outer_args)
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 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), TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
1, 0)) UNIFY_ALLOW_NONE, 0))
{ {
case 0: case 0:
break; break;
...@@ -6628,6 +6884,75 @@ do_type_instantiation (t, storage) ...@@ -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. */ /* Produce the definition of D, a _DECL generated from a template. */
tree tree
...@@ -6637,7 +6962,7 @@ instantiate_decl (d) ...@@ -6637,7 +6962,7 @@ instantiate_decl (d)
tree ti = DECL_TEMPLATE_INFO (d); tree ti = DECL_TEMPLATE_INFO (d);
tree tmpl = TI_TEMPLATE (ti); tree tmpl = TI_TEMPLATE (ti);
tree args = TI_ARGS (ti); tree args = TI_ARGS (ti);
tree td, temp; tree td;
tree decl_pattern, code_pattern; tree decl_pattern, code_pattern;
tree save_ti; tree save_ti;
int nested = in_function_p (); int nested = in_function_p ();
...@@ -6747,38 +7072,7 @@ instantiate_decl (d) ...@@ -6747,38 +7072,7 @@ instantiate_decl (d)
lineno = DECL_SOURCE_LINE (d); lineno = DECL_SOURCE_LINE (d);
input_filename = DECL_SOURCE_FILE (d); input_filename = DECL_SOURCE_FILE (d);
/* Trick tsubst into giving us a new decl in case the template changed. */ regenerate_decl_from_template (d, td);
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;
if (TREE_CODE (d) == VAR_DECL) if (TREE_CODE (d) == VAR_DECL)
{ {
......
// 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
}
// 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);
}
// 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();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment