diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 20725d820ae..949da95b65b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -4,6 +4,16 @@ Wed Apr 22 13:24:48 1998 Mark Mitchell 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 * errfn.c (cp_thing): Use xrealloc, not xmalloc, to copy memory. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8de724a9026..b6e695d6420 100644 --- a/gcc/cp/pt.c +++ b/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 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