diff options
author | Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu> | 1998-07-11 23:06:46 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 1998-07-11 23:06:46 -0400 |
commit | 744fac594b8f707fc4bbb7acbdcf4b8753d4cd71 (patch) | |
tree | 3c114b63cc3899e04a8e8ac4bd43415fb4085f14 /gcc | |
parent | eda600e865cff603d9398c48df114693da913458 (diff) | |
download | gcc-744fac594b8f707fc4bbb7acbdcf4b8753d4cd71.zip gcc-744fac594b8f707fc4bbb7acbdcf4b8753d4cd71.tar.gz gcc-744fac594b8f707fc4bbb7acbdcf4b8753d4cd71.tar.bz2 |
typeck.c (comptypes, [...]): Add parameter comparison.
* typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter
comparison.
* pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a
template template parameter, record its use.
(for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse
its template arguments if exists.
* pt.c (coerce_template_template_parms): New function equivalent
to coerce_template_parms when IS_TMPL_PARM is true.
(coerce_template_parms): Use it. Remove the IS_TMPL_PARM parameter,
all callers changed.
(coerce_template_parms): Access ARGLIST properly when creating a
new vector. Only accept implicit TYPE_DECL as valid argument for
a template template parameter when it is a base class of
current_class_type. Don't display error message when COMPLAIN is
false.
From-SVN: r21073
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/cp/method.c | 2 | ||||
-rw-r--r-- | gcc/cp/pt.c | 191 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 3 |
4 files changed, 152 insertions, 67 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d24b105..19121c4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,6 +1,27 @@ +1998-07-12 Kriang Lerdsuwanakij <lerdsuwa@scf-fs.usc.edu> + + * typeck.c (comptypes, case TEMPLATE_TEMPLATE_PARM): Add parameter + comparison. + + * pt.c (for_each_template_parm, case TEMPLATE_DECL): If it is a + template template parameter, record its use. + (for_each_template_parm, case TEMPLATE_TEMPLATE_PARM): Traverse + its template arguments if exists. + + * pt.c (coerce_template_template_parms): New function equivalent + to coerce_template_parms when IS_TMPL_PARM is true. + (coerce_template_parms): Use it. Remove the IS_TMPL_PARM parameter, + all callers changed. + + (coerce_template_parms): Access ARGLIST properly when creating a + new vector. Only accept implicit TYPE_DECL as valid argument for + a template template parameter when it is a base class of + current_class_type. Don't display error message when COMPLAIN is + false. + 1998-07-12 Klaus Kaempf (kkaempf@progis.de) - * repo.c (get_base_filename): Use file_name_nondirectory (). + * repo.c (get_base_filename): Use file_name_nondirectory. (open_repo_file): Ditto. * cp-tree.h (file_name_nondirectory): Add prototype. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 23f52c2..ebd6715 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -298,7 +298,7 @@ dicat (lo, hi) OB_PUTC ('0' + ulo); } -__inline void +static __inline void flush_repeats (nrepeats, type) int nrepeats; tree type; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 42caf46..36d0c0d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -84,7 +84,7 @@ static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree)); static tree tsubst_expr_values PROTO((tree, tree)); static int list_eq PROTO((tree, tree)); 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)); 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*, @@ -2347,6 +2347,82 @@ convert_nontype_argument (type, expr) return error_mark_node; } +/* Return 1 if PARM_PARMS and ARG_PARMS matches using rule for + template template parameters. Both PARM_PARMS and ARG_PARMS are + vectors of TREE_LIST nodes containing TYPE_DECL, TEMPLATE_DECL + or PARM_DECL. + + ARG_PARMS may contain more parameters than PARM_PARMS. If this is + the case, then extra parameters must have default arguments. + + Consider the example: + template <class T, class Allocator = allocator> class vector; + template<template <class U> class TT> class C; + + C<vector> is a valid instantiation. PARM_PARMS for the above code + contains a TYPE_DECL (for U), ARG_PARMS contains two TYPE_DECLs (for + T and Allocator) and OUTER_ARGS contains the argument that is used to + substitute the TT parameter. */ + +static int +coerce_template_template_parms (parm_parms, arg_parms, in_decl, outer_args) + tree parm_parms, arg_parms, in_decl, outer_args; +{ + int nparms, nargs, i; + tree parm, arg; + + my_friendly_assert (TREE_CODE (parm_parms) == TREE_VEC, 0); + my_friendly_assert (TREE_CODE (arg_parms) == TREE_VEC, 0); + + nparms = TREE_VEC_LENGTH (parm_parms); + nargs = TREE_VEC_LENGTH (arg_parms); + + /* The rule here is opposite of coerce_template_parms. */ + if (nargs < nparms + || (nargs > nparms + && TREE_PURPOSE (TREE_VEC_ELT (arg_parms, nparms)) == NULL_TREE)) + return 0; + + for (i = 0; i < nparms; ++i) + { + parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i)); + arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i)); + + if (arg == NULL_TREE || arg == error_mark_node + || parm == NULL_TREE || parm == error_mark_node) + return 0; + + if (TREE_CODE (arg) != TREE_CODE (parm)) + return 0; + + switch (TREE_CODE (parm)) + { + case TYPE_DECL: + break; + + case TEMPLATE_DECL: + /* We encounter instantiations of templates like + template <template <template <class> class> class TT> + class C; */ + sorry ("nested template template parameter"); + return 0; + + case PARM_DECL: + /* The tsubst call is used to handle cases such as + template <class T, template <T> class TT> class D; + i.e. the parameter list of TT depends on earlier parameters. */ + if (!comptypes (tsubst (TREE_TYPE (parm), outer_args, in_decl), + TREE_TYPE (arg), 1)) + return 0; + break; + + default: + my_friendly_abort (0); + } + } + return 1; +} + /* Convert all template arguments to their appropriate types, and return a vector containing the resulting values. If any error occurs, return error_mark_node, and, if COMPLAIN is non-zero, issue an error message. @@ -2356,22 +2432,16 @@ convert_nontype_argument (type, expr) If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be provided in ARGLIST, or else trailing parameters must have default values. If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument - deduction for any unspecified trailing arguments. + deduction for any unspecified trailing arguments. */ - If IS_TMPL_PARM is non-zero, we will coercing parameters of template - template arguments. In this case, ARGLIST is a chain of TREE_LIST - nodes containing TYPE_DECL, TEMPLATE_DECL or PARM_DECL. */ - static tree coerce_template_parms (parms, arglist, in_decl, complain, - require_all_arguments, - is_tmpl_parm) + require_all_arguments) tree parms, arglist; tree in_decl; int complain; int require_all_arguments; - int is_tmpl_parm; { int nparms, nargs, i, lost = 0; tree vec = NULL_TREE; @@ -2414,7 +2484,7 @@ coerce_template_parms (parms, arglist, in_decl, tree arg; tree parm = TREE_VEC_ELT (parms, i); - if (arglist) + if (arglist && TREE_CODE (arglist) == TREE_LIST) { arg = arglist; arglist = TREE_CHAIN (arglist); @@ -2424,7 +2494,7 @@ coerce_template_parms (parms, arglist, in_decl, else arg = TREE_VALUE (arg); } - else if (is_tmpl_parm && i < nargs) + else if (i < nargs) { arg = TREE_VEC_ELT (arglist, i); if (arg == error_mark_node) @@ -2450,16 +2520,6 @@ coerce_template_parms (parms, arglist, in_decl, tree val = 0; int is_type, requires_type, is_tmpl_type, requires_tmpl_type; - if (is_tmpl_parm && i < nargs) - { - /* In case we are checking arguments inside a template template - parameter, ARG that does not come from default argument is - also a TREE_LIST node. Note that ARG can also be a TREE_LIST - in other cases such as overloaded functions. */ - if (arg != NULL_TREE && arg != error_mark_node) - arg = TREE_VALUE (arg); - } - if (arg == NULL_TREE) /* We're out of arguments. */ { @@ -2492,7 +2552,11 @@ coerce_template_parms (parms, arglist, in_decl, || requires_tmpl_type; /* Check if it is a class template. If REQUIRES_TMPL_TYPE is true, - we also accept implicitly created TYPE_DECL as a valid argument. */ + we also accept implicitly created TYPE_DECL as a valid argument. + This is necessary to handle the case where we pass a template name + to a template template parameter in a scope where we've derived from + in instantiation of that template, so the template name refers to that + instantiation. We really ought to handle this better. */ is_tmpl_type = (TREE_CODE (arg) == TEMPLATE_DECL && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL) || (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM @@ -2501,16 +2565,16 @@ coerce_template_parms (parms, arglist, in_decl, && CLASSTYPE_TEMPLATE_INFO (arg) && TREE_CODE (TYPE_NAME (arg)) == TYPE_DECL && DECL_ARTIFICIAL (TYPE_NAME (arg)) - && requires_tmpl_type); + && requires_tmpl_type + && current_class_type + /* FIXME what about nested types? */ + && get_binfo (arg, current_class_type, 0)); if (is_tmpl_type && TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) arg = TYPE_STUB_DECL (arg); else if (is_tmpl_type && TREE_CODE (arg) == RECORD_TYPE) arg = CLASSTYPE_TI_TEMPLATE (arg); - if (is_tmpl_parm && i < nargs) - is_type = TREE_CODE (arg) == TYPE_DECL || is_tmpl_type; - else - is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type; + is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || is_tmpl_type; if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM) @@ -2544,7 +2608,7 @@ coerce_template_parms (parms, arglist, in_decl, } if (is_tmpl_type ^ requires_tmpl_type) { - if (in_decl) + if (in_decl && complain) { cp_error ("type/value mismatch at argument %d in template parameter list for `%D'", i + 1, in_decl); @@ -2557,16 +2621,6 @@ coerce_template_parms (parms, arglist, in_decl, TREE_VEC_ELT (vec, i) = error_mark_node; continue; } - if (is_tmpl_parm) - { - if (requires_tmpl_type) - { - cp_error ("nested template template parameter not implemented"); - lost++; - TREE_VEC_ELT (vec, i) = error_mark_node; - } - continue; - } if (is_type) { @@ -2575,23 +2629,28 @@ coerce_template_parms (parms, arglist, in_decl, tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm); tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg); - /* 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_template_parms (parmparm, argparm, + in_decl, vec)) + { + val = arg; - val = coerce_template_parms (argparm, parmparm, in_decl, 1, 1, 1); - if (val != error_mark_node) - val = arg; - - /* TEMPLATE_TEMPLATE_PARM node is preferred over - TEMPLATE_DECL. */ - if (val != error_mark_node - && DECL_TEMPLATE_TEMPLATE_PARM_P (val)) - val = TREE_TYPE (val); + /* TEMPLATE_TEMPLATE_PARM node is preferred over + TEMPLATE_DECL. */ + if (val != error_mark_node + && DECL_TEMPLATE_TEMPLATE_PARM_P (val)) + val = TREE_TYPE (val); + } + else + { + if (in_decl && complain) + { + cp_error ("type/value mismatch at argument %d in template parameter list for `%D'", + i + 1, in_decl); + cp_error (" expected a template of type `%D', got `%D'", parm, arg); + } + + val = error_mark_node; + } } else { @@ -3013,7 +3072,7 @@ lookup_template_class (d1, arglist, in_decl, context) CLASSTYPE_GOT_SEMICOLON (parm) = 1; parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); - arglist2 = coerce_template_parms (parmlist, arglist, template, 1, 1, 0); + arglist2 = coerce_template_parms (parmlist, arglist, template, 1, 1); if (arglist2 == error_mark_node) return error_mark_node; @@ -3049,13 +3108,13 @@ lookup_template_class (d1, arglist, in_decl, context) TREE_VEC_ELT (new_args, i) = coerce_template_parms (TREE_VALUE (t), TREE_VEC_ELT (arglist, i), - template, 1, 1, 0); + template, 1, 1); arglist = new_args; } else arglist = coerce_template_parms (parmlist, innermost_args (arglist, 0), - template, 1, 1, 0); + template, 1, 1); if (arglist == error_mark_node) return error_mark_node; if (uses_template_parms (arglist)) @@ -3268,10 +3327,8 @@ for_each_template_parm (t, fn, data) case TEMPLATE_DECL: /* A template template parameter is encountered */ if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)) - /* We are parsing a template declaration */ - return 1; - /* We are instantiating templates with template template - parameter */ + return for_each_template_parm (TREE_TYPE (t), fn, data); + /* Already substituted template template parameter */ return 0; case CONST_DECL: @@ -3301,8 +3358,12 @@ for_each_template_parm (t, fn, data) return for_each_template_parm (TREE_OPERAND (t, 0), fn, data); /* template parm nodes */ - case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: + /* Record template parameters such as `T' inside `TT<T>'. */ + if (CLASSTYPE_TEMPLATE_INFO (t) + && for_each_template_parm (CLASSTYPE_TI_ARGS (t), fn, data)) + return 1; + case TEMPLATE_TYPE_PARM: case TEMPLATE_PARM_INDEX: if (fn) return (*fn)(t, data); @@ -5844,7 +5905,7 @@ type_unification (tparms, targs, parms, args, explicit_targs, { tree arg_vec; arg_vec = coerce_template_parms (tparms, explicit_targs, NULL_TREE, 0, - 0, 0); + 0); if (arg_vec == error_mark_node) return 1; @@ -6260,10 +6321,10 @@ unify (tparms, targs, parm, arg, strict, explicit_mask) 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> + template <class T, class Allocator = allocator> class vector. */ - if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1, 0) + if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 1, 1) == error_mark_node) return 1; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5176c56..0708692 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -804,6 +804,9 @@ comptypes (type1, type2, strict) if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)) return 0; + if (! comp_template_parms (DECL_TEMPLATE_PARMS (TYPE_NAME (t1)), + DECL_TEMPLATE_PARMS (TYPE_NAME (t2)))) + return 0; if (! CLASSTYPE_TEMPLATE_INFO (t1) && ! CLASSTYPE_TEMPLATE_INFO (t2)) return 1; /* Don't check inheritance. */ |