diff options
author | Mark Mitchell <mmitchell@usa.net> | 1998-04-22 21:02:01 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-04-22 21:02:01 +0000 |
commit | db2767b644667cdb0beefc7c98c643e605512405 (patch) | |
tree | 9f38d9c184acc8ee76a7f015f6616c5329af210d /gcc | |
parent | 693e265fc07aa9119906a3ed03318599ae6b5bc5 (diff) | |
download | gcc-db2767b644667cdb0beefc7c98c643e605512405.zip gcc-db2767b644667cdb0beefc7c98c643e605512405.tar.gz gcc-db2767b644667cdb0beefc7c98c643e605512405.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/pt.c | 221 |
2 files changed, 142 insertions, 89 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 20725d8..949da95 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8de724a..b6e695d 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 <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. */ - - /* ARG must be constructed from a template class. */ - if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg)) - return 1; + if (CLASSTYPE_TEMPLATE_INFO (parm)) + { + /* We arrive here when PARM does not involve template + specialization. */ - { - 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; + /* ARG must be constructed from a template class. */ + if (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg)) + return 1; - /* 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> + { + 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> class vector. */ - if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1, 0) - == error_mark_node) - return 1; + 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; + /* 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. */ + /* This argument can be deduced. */ - if (unify (tparms, targs, ntparms, t, - TREE_VEC_ELT (argvec, i), strict, explicit_mask)) - return 1; + 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); |