pt.c (tsubst): Decrease the template-level of TEMPLATE_TEMPLATE_PARMS.
* pt.c (tsubst): Decrease the template-level of TEMPLATE_TEMPLATE_PARMS. Likewise for the DECL_INITIAL of a TEMPLATE_PARM_INDEX. (template_decl_level): New function. (unify): Make sure to record unifications for template parameters, even when the parameters exactly match the arguments. Combine duplicated code for TEMPLATE_TEMPLATE_PARMs and TEMPLATE_TYPE_PARMS. Don't try to unify template parameters that aren't from the level we're currently working on. From-SVN: r19378
This commit is contained in:
parent
693e265fc0
commit
db2767b644
@ -4,6 +4,16 @@ Wed Apr 22 13:24:48 1998 Mark Mitchell <mmitchell@usa.net>
|
||||
the DECL_RESULTs of a member TEMPLATE_DECL, not just the
|
||||
TEMPLATE_DECL.
|
||||
|
||||
* pt.c (tsubst): Decrease the template-level of
|
||||
TEMPLATE_TEMPLATE_PARMS. Likewise for the DECL_INITIAL of a
|
||||
TEMPLATE_PARM_INDEX.
|
||||
(template_decl_level): New function.
|
||||
(unify): Make sure to record unifications for template
|
||||
parameters, even when the parameters exactly match the arguments.
|
||||
Combine duplicated code for TEMPLATE_TEMPLATE_PARMs and
|
||||
TEMPLATE_TYPE_PARMS. Don't try to unify template parameters that
|
||||
aren't from the level we're currently working on.
|
||||
|
||||
Tue Apr 21 22:00:04 1998 Mark Mitchell <mmitchell@usa.net>
|
||||
|
||||
* errfn.c (cp_thing): Use xrealloc, not xmalloc, to copy memory.
|
||||
|
223
gcc/cp/pt.c
223
gcc/cp/pt.c
@ -3944,17 +3944,15 @@ tsubst (t, args, in_decl)
|
||||
tree parms;
|
||||
tree* new_parms;
|
||||
tree spec;
|
||||
int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
|
||||
|
||||
if (TREE_CODE (decl) == TYPE_DECL
|
||||
&& TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
|
||||
/* There is no tsubst'ing to be done in a template template
|
||||
parameter. */
|
||||
return t;
|
||||
|
||||
/* We might already have an instance of this template. */
|
||||
spec = retrieve_specialization (t, args);
|
||||
if (spec != NULL_TREE)
|
||||
return spec;
|
||||
if (!is_template_template_parm)
|
||||
{
|
||||
/* We might already have an instance of this template. */
|
||||
spec = retrieve_specialization (t, args);
|
||||
if (spec != NULL_TREE)
|
||||
return spec;
|
||||
}
|
||||
|
||||
/* Make a new template decl. It will be similar to the
|
||||
original, but will record the current template arguments.
|
||||
@ -3966,6 +3964,15 @@ tsubst (t, args, in_decl)
|
||||
my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
|
||||
DECL_CHAIN (tmpl) = NULL_TREE;
|
||||
TREE_CHAIN (tmpl) = NULL_TREE;
|
||||
|
||||
if (is_template_template_parm)
|
||||
{
|
||||
tree new_decl = tsubst (decl, args, in_decl);
|
||||
DECL_RESULT (tmpl) = new_decl;
|
||||
TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
DECL_CONTEXT (tmpl) = tsubst (DECL_CONTEXT (t),
|
||||
args, in_decl);
|
||||
DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t),
|
||||
@ -4311,7 +4318,11 @@ tsubst (t, args, in_decl)
|
||||
{
|
||||
tree r = copy_node (t);
|
||||
TREE_TYPE (r) = type;
|
||||
DECL_INITIAL (r) = TREE_TYPE (r);
|
||||
if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX)
|
||||
DECL_INITIAL (r) = TREE_TYPE (r);
|
||||
else
|
||||
DECL_INITIAL (r) = tsubst (DECL_INITIAL (r), args, in_decl);
|
||||
|
||||
DECL_CONTEXT (r) = NULL_TREE;
|
||||
#ifdef PROMOTE_PROTOTYPES
|
||||
if ((TREE_CODE (type) == INTEGER_TYPE
|
||||
@ -5565,6 +5576,27 @@ type_unification_real (tparms, targs, parms, args, subr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the level of DECL, which declares a template parameter. */
|
||||
|
||||
static int
|
||||
template_decl_level (decl)
|
||||
tree decl;
|
||||
{
|
||||
switch (TREE_CODE (decl))
|
||||
{
|
||||
case TYPE_DECL:
|
||||
case TEMPLATE_DECL:
|
||||
return TEMPLATE_TYPE_LEVEL (TREE_TYPE (decl));
|
||||
|
||||
case PARM_DECL:
|
||||
return TEMPLATE_PARM_LEVEL (DECL_INITIAL (decl));
|
||||
|
||||
default:
|
||||
my_friendly_abort (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tail recursion is your friend. */
|
||||
|
||||
static int
|
||||
@ -5575,6 +5607,7 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
|
||||
{
|
||||
int idx;
|
||||
tree targ;
|
||||
tree tparm;
|
||||
|
||||
/* I don't think this will do the right thing with respect to types.
|
||||
But the only case I've seen it in so far has been array bounds, where
|
||||
@ -5587,7 +5620,11 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
|
||||
return 1;
|
||||
if (arg == unknown_type_node)
|
||||
return 1;
|
||||
if (arg == parm)
|
||||
/* If PARM uses template parameters, then we can't bail out here,
|
||||
even in ARG == PARM, since we won't record unifications for the
|
||||
template parameters. We might need them if we're trying to
|
||||
figure out which of two things is more specialized. */
|
||||
if (arg == parm && !uses_template_parms (parm))
|
||||
return 0;
|
||||
|
||||
/* We can't remove cv-quals when strict. */
|
||||
@ -5606,53 +5643,24 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
|
||||
return 0;
|
||||
|
||||
case TEMPLATE_TYPE_PARM:
|
||||
idx = TEMPLATE_TYPE_IDX (parm);
|
||||
targ = TREE_VEC_ELT (targs, idx);
|
||||
/* Check for mixed types and values. */
|
||||
if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
|
||||
return 1;
|
||||
|
||||
if (!strict && targ != NULL_TREE
|
||||
&& explicit_mask && explicit_mask[idx])
|
||||
/* An explicit template argument. Don't even try to match
|
||||
here; the overload resolution code will manage check to
|
||||
see whether the call is legal. */
|
||||
return 0;
|
||||
|
||||
if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
|
||||
|| TYPE_VOLATILE (arg) < TYPE_VOLATILE (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
|
||||
/* Simple cases: Value already set, does match or doesn't. */
|
||||
if (targ != NULL_TREE
|
||||
&& (comptypes (targ, arg, 1)
|
||||
|| (explicit_mask && explicit_mask[idx])))
|
||||
return 0;
|
||||
else if (targ)
|
||||
return 1;
|
||||
TREE_VEC_ELT (targs, idx) = arg;
|
||||
return 0;
|
||||
|
||||
case TEMPLATE_TEMPLATE_PARM:
|
||||
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
|
||||
|
||||
if (TEMPLATE_TYPE_LEVEL (parm)
|
||||
!= template_decl_level (tparm))
|
||||
/* The PARM is not one we're trying to unify. Just check
|
||||
to see if it matches ARG. */
|
||||
return (TREE_CODE (arg) == TREE_CODE (parm)
|
||||
&& comptypes (parm, arg, 1) == 0) ? 0 : 1;
|
||||
idx = TEMPLATE_TYPE_IDX (parm);
|
||||
targ = TREE_VEC_ELT (targs, idx);
|
||||
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
|
||||
|
||||
/* Check for mixed types and values. */
|
||||
if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TEMPLATE_DECL)
|
||||
if ((TREE_CODE (parm) == TEMPLATE_TYPE_PARM
|
||||
&& TREE_CODE (tparm) != TYPE_DECL)
|
||||
|| (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
|
||||
&& TREE_CODE (tparm) != TEMPLATE_DECL))
|
||||
return 1;
|
||||
|
||||
if (!strict && targ != NULL_TREE
|
||||
@ -5662,51 +5670,76 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
|
||||
see whether the call is legal. */
|
||||
return 0;
|
||||
|
||||
if (CLASSTYPE_TEMPLATE_INFO (parm))
|
||||
if (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM)
|
||||
{
|
||||
/* We arrive here when PARM does not involve template
|
||||
specialization. */
|
||||
if (CLASSTYPE_TEMPLATE_INFO (parm))
|
||||
{
|
||||
/* We arrive here when PARM does not involve template
|
||||
specialization. */
|
||||
|
||||
/* ARG must be constructed from a template class. */
|
||||
if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
|
||||
return 1;
|
||||
/* ARG must be constructed from a template class. */
|
||||
if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg))
|
||||
return 1;
|
||||
|
||||
{
|
||||
tree parmtmpl = CLASSTYPE_TI_TEMPLATE (parm);
|
||||
tree parmvec = CLASSTYPE_TI_ARGS (parm);
|
||||
tree argvec = CLASSTYPE_TI_ARGS (arg);
|
||||
tree argtmplvec
|
||||
= DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
|
||||
int i;
|
||||
{
|
||||
tree parmtmpl = CLASSTYPE_TI_TEMPLATE (parm);
|
||||
tree parmvec = CLASSTYPE_TI_ARGS (parm);
|
||||
tree argvec = CLASSTYPE_TI_ARGS (arg);
|
||||
tree argtmplvec
|
||||
= DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (arg));
|
||||
int i;
|
||||
|
||||
/* The parameter and argument roles have to be switched here
|
||||
in order to handle default arguments properly. For example,
|
||||
template<template <class> class TT> void f(TT<int>)
|
||||
should be able to accept vector<int> which comes from
|
||||
template <class T, class Allcator = allocator>
|
||||
/* The parameter and argument roles have to be switched here
|
||||
in order to handle default arguments properly. For example,
|
||||
template<template <class> class TT> void f(TT<int>)
|
||||
should be able to accept vector<int> which comes from
|
||||
template <class T, class Allcator = allocator>
|
||||
class vector. */
|
||||
|
||||
if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1, 0)
|
||||
== error_mark_node)
|
||||
return 1;
|
||||
|
||||
/* Deduce arguments T, i from TT<T> or TT<i>. */
|
||||
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
|
||||
{
|
||||
tree t = TREE_VEC_ELT (parmvec, i);
|
||||
if (TREE_CODE (t) != TEMPLATE_TYPE_PARM
|
||||
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
|
||||
&& TREE_CODE (t) != TEMPLATE_PARM_INDEX)
|
||||
continue;
|
||||
|
||||
/* This argument can be deduced. */
|
||||
|
||||
if (unify (tparms, targs, ntparms, t,
|
||||
TREE_VEC_ELT (argvec, i), strict, explicit_mask))
|
||||
if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1, 0)
|
||||
== error_mark_node)
|
||||
return 1;
|
||||
|
||||
/* Deduce arguments T, i from TT<T> or TT<i>. */
|
||||
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
|
||||
{
|
||||
tree t = TREE_VEC_ELT (parmvec, i);
|
||||
if (TREE_CODE (t) != TEMPLATE_TYPE_PARM
|
||||
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
|
||||
&& TREE_CODE (t) != TEMPLATE_PARM_INDEX)
|
||||
continue;
|
||||
|
||||
/* This argument can be deduced. */
|
||||
|
||||
if (unify (tparms, targs, ntparms, t,
|
||||
TREE_VEC_ELT (argvec, i), strict, explicit_mask))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
arg = CLASSTYPE_TI_TEMPLATE (arg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
|
||||
|| TYPE_VOLATILE (arg) < TYPE_VOLATILE (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);
|
||||
}
|
||||
arg = CLASSTYPE_TI_TEMPLATE (arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Simple cases: Value already set, does match or doesn't. */
|
||||
@ -5720,8 +5753,18 @@ unify (tparms, targs, ntparms, parm, arg, strict, explicit_mask)
|
||||
return 0;
|
||||
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
|
||||
|
||||
if (TEMPLATE_PARM_LEVEL (parm)
|
||||
!= template_decl_level (tparm))
|
||||
/* The PARM is not one we're trying to unify. Just check
|
||||
to see if it matches ARG. */
|
||||
return (TREE_CODE (arg) == TREE_CODE (parm)
|
||||
&& cp_tree_equal (parm, arg) == 0) ? 0 : 1;
|
||||
|
||||
idx = TEMPLATE_PARM_IDX (parm);
|
||||
targ = TREE_VEC_ELT (targs, idx);
|
||||
|
||||
if (targ)
|
||||
{
|
||||
int i = cp_tree_equal (targ, arg);
|
||||
|
Loading…
Reference in New Issue
Block a user