From: Nathan Sidwell Date: Mon, 22 Jan 2001 13:51:43 +0000 (+0000) Subject: cp-tree.h (unification_kind_t): Add DEDUCE_ORDER. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=62e4a758537dd6c82a0a2ce1b0cd75842e41441c;p=gcc.git cp-tree.h (unification_kind_t): Add DEDUCE_ORDER. cp: * cp-tree.h (unification_kind_t): Add DEDUCE_ORDER. (more_specialized): Add deduction parameter. * call.c (joust): Adjust more_specialized call. * pt.c (UNIFY_ALLOW_OUTER_MORE_CV_QUAL, UNIFY_ALLOW_OUTER_LESS_CV_QUAL): New unify flags. (get_bindings_order): Remove. (get_bindings_real): Add DEDUCE parameter. (maybe_adjust_types_for_deduction): Return extra unify flags. Do REFERENCE_TYPE jig for DEDUCE_ORDER. (type_unification_real): Deal with DEDUCE_ORDER. Use result of maybe_adjust_types_for_deduction. (more_specialized): Add DEDUCE parameter. Call get_bindings_real directly. (try_one_overload): Use result of maybe_adjust_types_for_deduction. (check_cv_quals_for_unify): Use new unify qualifier flags. (unify): Clear new unify qualifier flags. (get_bindings_real): Add DEDUCE parameter. (get_bindings): Adjust call to get_bindings_real. (get_bindings_overload): Likewise. (most_specialized_instantiation): Adjust call to more_specialized. testsuite: * g++.old-deja/g++.martin/sts_partial.C: Remove XFAIL. * g++.old-deja/g++.pt/spec35.C: New test. * g++.old-deja/g++.pt/spec36.C: New test. From-SVN: r39182 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 79274281bed..3374dd2e268 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2001-01-22 Nathan Sidwell + + * cp-tree.h (unification_kind_t): Add DEDUCE_ORDER. + (more_specialized): Add deduction parameter. + * call.c (joust): Adjust more_specialized call. + * pt.c (UNIFY_ALLOW_OUTER_MORE_CV_QUAL, + UNIFY_ALLOW_OUTER_LESS_CV_QUAL): New unify flags. + (get_bindings_order): Remove. + (get_bindings_real): Add DEDUCE parameter. + (maybe_adjust_types_for_deduction): Return extra unify flags. Do + REFERENCE_TYPE jig for DEDUCE_ORDER. + (type_unification_real): Deal with DEDUCE_ORDER. Use result of + maybe_adjust_types_for_deduction. + (more_specialized): Add DEDUCE parameter. Call get_bindings_real + directly. + (try_one_overload): Use result of maybe_adjust_types_for_deduction. + (check_cv_quals_for_unify): Use new unify qualifier flags. + (unify): Clear new unify qualifier flags. + (get_bindings_real): Add DEDUCE parameter. + (get_bindings): Adjust call to get_bindings_real. + (get_bindings_overload): Likewise. + (most_specialized_instantiation): Adjust call to + more_specialized. + 2001-01-19 Jason Merrill * decl2.c (flag_vtable_thunks): Also depend on ENABLE_NEW_GXX_ABI. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e3613ee7265..fa5a50803bf 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5196,6 +5196,7 @@ joust (cand1, cand2, warn) else if (cand1->template && cand2->template) winner = more_specialized (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template), + DEDUCE_ORDER, /* Never do unification on the 'this' parameter. */ TREE_VEC_LENGTH (cand1->convs) - DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1df938b814d..8122d566697 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3209,14 +3209,15 @@ extern int function_depth; /* in pt.c */ -/* These values are used for the `STRICT' parameter to type_unfication and +/* These values are used for the `STRICT' parameter to type_unification 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 + DEDUCE_EXACT, + DEDUCE_ORDER } unification_kind_t; /* Macros for operating on a template instantation level node, represented @@ -4143,7 +4144,7 @@ extern tree instantiate_template PARAMS ((tree, tree)); extern int fn_type_unification PARAMS ((tree, tree, tree, tree, tree, unification_kind_t, int)); extern tree tinst_for_decl PARAMS ((void)); extern void mark_decl_instantiated PARAMS ((tree, int)); -extern int more_specialized PARAMS ((tree, tree, int)); +extern int more_specialized PARAMS ((tree, tree, int, int)); extern void mark_class_instantiated PARAMS ((tree, int)); extern void do_decl_instantiation PARAMS ((tree, tree, tree)); extern void do_type_instantiation PARAMS ((tree, tree, int)); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cf3b52d33e2..184edf846f9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -87,6 +87,8 @@ static htab_t local_specializations; #define UNIFY_ALLOW_DERIVED 4 #define UNIFY_ALLOW_INTEGER 8 #define UNIFY_ALLOW_OUTER_LEVEL 16 +#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32 +#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64 #define GTB_VIA_VIRTUAL 1 /* The base class we are examining is virtual, or a base class of a virtual @@ -111,7 +113,7 @@ static tree coerce_template_parms PARAMS ((tree, tree, tree, int, int)); static void tsubst_enum PARAMS ((tree, tree, tree)); static tree add_to_template_args PARAMS ((tree, tree)); static tree add_outermost_template_args PARAMS ((tree, tree)); -static void maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*, +static int maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*, tree*)); static int type_unification_real PARAMS ((tree, tree, tree, tree, int, unification_kind_t, int, int)); @@ -121,7 +123,6 @@ static tree convert_nontype_argument PARAMS ((tree, tree)); static tree convert_template_argument PARAMS ((tree, tree, tree, int, int , tree)); static tree get_bindings_overload PARAMS ((tree, tree, tree)); -static tree get_bindings_order PARAMS ((tree, tree, int)); static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*)); static tree build_template_parm_index PARAMS ((int, int, int, tree, tree)); static int inline_needs_template_parms PARAMS ((tree)); @@ -136,7 +137,7 @@ static tree build_template_decl PARAMS ((tree, tree)); static int mark_template_parm PARAMS ((tree, void *)); static tree tsubst_friend_function PARAMS ((tree, tree)); static tree tsubst_friend_class PARAMS ((tree, tree)); -static tree get_bindings_real PARAMS ((tree, tree, tree, int, int)); +static tree get_bindings_real PARAMS ((tree, tree, tree, int, int, int)); static int template_decl_level PARAMS ((tree)); static tree maybe_get_template_decl_from_type_decl PARAMS ((tree)); static int check_cv_quals_for_unify PARAMS ((int, tree, tree)); @@ -7681,13 +7682,15 @@ instantiate_template (tmpl, targ_ptr) [temp.deduct.conv]. DEDUCE_EXACT: + We are deducing arguments when doing an explicit instantiation + as in [temp.explicit], when determining an explicit specialization + as in [temp.expl.spec], or when taking the address of a function + template, as in [temp.deduct.funcaddr]. + + DEDUCE_ORDER: 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 determining an explicit specialization as in - [temp.expl.spec], or when taking the address of a function - template, as in [temp.deduct.funcaddr]. + templates, as in [temp.func.order] and [temp.class.order]. LEN is the number of parms to consider before returning success, or -1 for all. This is used in partial ordering to avoid comparing parms for @@ -7793,12 +7796,14 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, the argument passed to the call, or the type of the value initialized with the result of the conversion function. */ -static void +static int maybe_adjust_types_for_deduction (strict, parm, arg) unification_kind_t strict; tree* parm; tree* arg; { + int result = 0; + switch (strict) { case DEDUCE_CALL: @@ -7817,8 +7822,43 @@ maybe_adjust_types_for_deduction (strict, parm, arg) case DEDUCE_EXACT: /* There is nothing to do in this case. */ - return; + return 0; + case DEDUCE_ORDER: + /* DR 214. [temp.func.order] is underspecified, and leads to no + ordering between things like `T *' and `T const &' for `U *'. + The former has T=U and the latter T=U*. The former looks more + specialized and John Spicer considers it well-formed (the EDG + compiler accepts it). + + John also confirms that deduction should proceed as in a function + call. Which implies the usual ARG and PARM bashing as DEDUCE_CALL. + However, in ordering, ARG can have REFERENCE_TYPE, but no argument + to an actual call can have such a type. + + When deducing against a REFERENCE_TYPE, we can either not change + PARM's type, or we can change ARG's type too. The latter, though + seemingly more safe, turns out to give the following quirk. Consider + deducing a call to a `const int *' with the following template + function parameters + #1; T const *const & ; T = int + #2; T *const & ; T = const int + #3; T * ; T = const int + It looks like #1 is the more specialized. Taken pairwise, #1 is + more specialized than #2 and #2 is more specialized than #3, yet + there is no ordering between #1 and #3. + + So, if ARG is a reference, we look though it when PARM is + not a refence. When both are references we don't change either. */ + if (TREE_CODE (*arg) == REFERENCE_TYPE) + { + if (TREE_CODE (*parm) == REFERENCE_TYPE) + return 0; + *arg = TREE_TYPE (*arg); + result |= UNIFY_ALLOW_OUTER_LESS_CV_QUAL; + goto skip_arg; + } + break; default: my_friendly_abort (0); } @@ -7849,6 +7889,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg) *arg = TYPE_MAIN_VARIANT (*arg); } + skip_arg:; /* [temp.deduct.call] If P is a cv-qualified type, the top level cv-qualifiers @@ -7857,7 +7898,11 @@ maybe_adjust_types_for_deduction (strict, parm, arg) type deduction. */ *parm = TYPE_MAIN_VARIANT (*parm); if (TREE_CODE (*parm) == REFERENCE_TYPE) - *parm = TREE_TYPE (*parm); + { + *parm = TREE_TYPE (*parm); + result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL; + } + return result; } /* Most parms like fn_type_unification. @@ -7902,6 +7947,10 @@ type_unification_real (tparms, targs, parms, args, subr, case DEDUCE_EXACT: sub_strict = UNIFY_ALLOW_NONE; break; + + case DEDUCE_ORDER: + sub_strict = UNIFY_ALLOW_NONE; + break; default: my_friendly_abort (0); @@ -7943,7 +7992,7 @@ type_unification_real (tparms, targs, parms, args, subr, arg = NULL_TREE; } - if (strict == DEDUCE_EXACT) + if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER) { if (same_type_p (parm, type)) continue; @@ -7976,12 +8025,16 @@ type_unification_real (tparms, targs, parms, args, subr, } arg = TREE_TYPE (arg); } + + { + int arg_strict = sub_strict; + + if (!subr) + arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg); - if (!subr) - maybe_adjust_types_for_deduction (strict, &parm, &arg); - - if (unify (tparms, targs, parm, arg, sub_strict)) - return 1; + if (unify (tparms, targs, parm, arg, arg_strict)) + return 1; + } /* Are we done with the interesting parms? */ if (--len == 0) @@ -8129,7 +8182,7 @@ try_one_overload (tparms, orig_targs, targs, parm, arg, strict, if (uses_template_parms (arg)) return 1; - maybe_adjust_types_for_deduction (strict, &parm, &arg); + sub_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg); /* We don't copy orig_targs for this because if we have already deduced some template args from previous args, unify would complain when we @@ -8413,11 +8466,11 @@ check_cv_quals_for_unify (strict, arg, parm) tree arg; tree parm; { - if (!(strict & UNIFY_ALLOW_MORE_CV_QUAL) + if (!(strict & (UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_OUTER_MORE_CV_QUAL)) && !at_least_as_qualified_p (arg, parm)) return 0; - if (!(strict & UNIFY_ALLOW_LESS_CV_QUAL) + if (!(strict & (UNIFY_ALLOW_LESS_CV_QUAL | UNIFY_ALLOW_OUTER_LESS_CV_QUAL)) && !at_least_as_qualified_p (parm, arg)) return 0; @@ -8448,7 +8501,13 @@ check_cv_quals_for_unify (strict, arg, parm) have const qualified pointers leading up to the inner type which requires additional CV quals, except at the outer level, where const is not required [conv.qual]. It would be normal to set this flag in - addition to setting UNIFY_ALLOW_MORE_CV_QUAL. */ + addition to setting UNIFY_ALLOW_MORE_CV_QUAL. + UNIFY_ALLOW_OUTER_MORE_CV_QUAL: + This is the outermost level of a deduction, and PARM can be more CV + qualified at this point. + UNIFY_ALLOW_OUTER_LESS_CV_QUAL: + This is the outermost level of a deduction, and PARM can be less CV + qualified at this point. */ static int unify (tparms, targs, parm, arg, strict) @@ -8498,6 +8557,8 @@ unify (tparms, targs, parm, arg, strict) strict &= ~UNIFY_ALLOW_MORE_CV_QUAL; strict &= ~UNIFY_ALLOW_OUTER_LEVEL; strict &= ~UNIFY_ALLOW_DERIVED; + strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL; + strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL; switch (TREE_CODE (parm)) { @@ -8963,6 +9024,8 @@ mark_decl_instantiated (result, extern_p) /* Given two function templates PAT1 and PAT2, return: + DEDUCE should be DEDUCE_EXACT or DEDUCE_ORDER. + 1 if PAT1 is more specialized than PAT2 as described in [temp.func.order]. -1 if PAT2 is more specialized than PAT1. 0 if neither is more specialized. @@ -8970,18 +9033,21 @@ mark_decl_instantiated (result, extern_p) LEN is passed through to fn_type_unification. */ int -more_specialized (pat1, pat2, len) +more_specialized (pat1, pat2, deduce, len) tree pat1, pat2; + int deduce; int len; { tree targs; int winner = 0; - targs = get_bindings_order (pat1, DECL_TEMPLATE_RESULT (pat2), len); + targs = get_bindings_real (pat1, DECL_TEMPLATE_RESULT (pat2), + NULL_TREE, 0, deduce, len); if (targs) --winner; - targs = get_bindings_order (pat2, DECL_TEMPLATE_RESULT (pat1), len); + targs = get_bindings_real (pat2, DECL_TEMPLATE_RESULT (pat1), + NULL_TREE, 0, deduce, len); if (targs) ++winner; @@ -9018,12 +9084,12 @@ more_specialized_class (pat1, pat2) DECL from the function template FN, with the explicit template arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must also match. Return NULL_TREE if no satisfactory arguments could be - found. LEN is passed through to fn_type_unification. */ + found. DEDUCE and LEN are passed through to fn_type_unification. */ static tree -get_bindings_real (fn, decl, explicit_args, check_rettype, len) +get_bindings_real (fn, decl, explicit_args, check_rettype, deduce, len) tree fn, decl, explicit_args; - int check_rettype, len; + int check_rettype, deduce, len; { int ntparms = DECL_NTPARMS (fn); tree targs = make_tree_vec (ntparms); @@ -9069,7 +9135,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype, len) decl_arg_types, (check_rettype || DECL_CONV_FN_P (fn) ? TREE_TYPE (decl_type) : NULL_TREE), - DEDUCE_EXACT, len); + deduce, len); if (i != 0) return NULL_TREE; @@ -9083,7 +9149,7 @@ tree get_bindings (fn, decl, explicit_args) tree fn, decl, explicit_args; { - return get_bindings_real (fn, decl, explicit_args, 1, -1); + return get_bindings_real (fn, decl, explicit_args, 1, DEDUCE_EXACT, -1); } /* But for resolve_overloaded_unification, we only care about the parameter @@ -9093,17 +9159,7 @@ static tree get_bindings_overload (fn, decl, explicit_args) tree fn, decl, explicit_args; { - return get_bindings_real (fn, decl, explicit_args, 0, -1); -} - -/* And for more_specialized, we want to be able to stop partway. */ - -static tree -get_bindings_order (fn, decl, len) - tree fn, decl; - int len; -{ - return get_bindings_real (fn, decl, NULL_TREE, 0, len); + return get_bindings_real (fn, decl, explicit_args, 0, DEDUCE_EXACT, -1); } /* Return the innermost template arguments that, when applied to a @@ -9162,7 +9218,8 @@ most_specialized_instantiation (instantiations) champ = instantiations; for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn)) { - fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1); + fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), + DEDUCE_EXACT, -1); if (fate == 1) ; else @@ -9179,7 +9236,8 @@ most_specialized_instantiation (instantiations) for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn)) { - fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1); + fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), + DEDUCE_EXACT, -1); if (fate != 1) return error_mark_node; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d43e8915b09..09f2e134866 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2001-01-22 Nathan Sidwell + + * g++.old-deja/g++.martin/sts_partial.C: Remove XFAIL. + * g++.old-deja/g++.pt/spec35.C: New test. + * g++.old-deja/g++.pt/spec36.C: New test. + 2001-01-20 Jakub Jelinek * gcc.c-torture/compile/20010118-1.c: New test. diff --git a/gcc/testsuite/g++.old-deja/g++.martin/sts_partial.C b/gcc/testsuite/g++.old-deja/g++.martin/sts_partial.C index c2dc9411b54..382214c3c76 100644 --- a/gcc/testsuite/g++.old-deja/g++.martin/sts_partial.C +++ b/gcc/testsuite/g++.old-deja/g++.martin/sts_partial.C @@ -1,4 +1,3 @@ -// excess errors test - XFAIL // ecgs-bugs 1999-02-22 14:26 Stefan Schwarzer // sts@ica1.uni-stuttgart.de // partial ordering problem in egcs <= 1.1.1 diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec35.C b/gcc/testsuite/g++.old-deja/g++.pt/spec35.C new file mode 100644 index 00000000000..e768c9104b3 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec35.C @@ -0,0 +1,31 @@ +// Build don't link: +// +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 18 Jan 2001 + +// Bug 1617. We didn't resolve partial ordering properly. The std is rather +// vague about it anyway, DR 214 talks about this. + +extern "C" int puts (char const *); + +template int Foo (T); // ERROR - candidate +template int Foo (T &); // ERROR - candidate + +template int Qux (T); // ERROR - candidate +template int Qux (T const &); // ERROR - candidate + +template int Bar (T const *const &); // ERROR - candidate +template int Bar (T *const &); // ERROR - candidate +template int Bar (T *); // ERROR - candidate + +template int Baz (T *const &); // ERROR - candidate +template int Baz (T *); // ERROR - candidate + +int Baz (int const *ptr, int *ptr2) +{ + Baz (ptr2); // ERROR - ambiguous + Bar (ptr2); // ERROR - ambiguous + Foo (ptr2); // ERROR - ambiguous + Qux (ptr2); // ERROR - ambiguous + return 0; +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec36.C b/gcc/testsuite/g++.old-deja/g++.pt/spec36.C new file mode 100644 index 00000000000..7581f85e510 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec36.C @@ -0,0 +1,46 @@ +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 18 Jan 2001 + +// Bug 1617. We didn't resolve partial ordering properly. The std is rather +// vague about it anyway, DR 214 talks about this. + +extern "C" int puts (char const *); + +template int Foo (T *) {puts (__PRETTY_FUNCTION__); return 1;} +template int Foo (T &) {puts (__PRETTY_FUNCTION__); return 2;} +template int Foo (T const &) {puts (__PRETTY_FUNCTION__); return 3;} + +template int Bar (T const *const &) {puts (__PRETTY_FUNCTION__); return 4;} +template int Bar (T *const &) {puts (__PRETTY_FUNCTION__); return 5;} +template int Bar (T *) {puts (__PRETTY_FUNCTION__); return 6;} + +template int Quux (T *const &) {puts (__PRETTY_FUNCTION__); return 7;} +template int Quux (T const &) {puts (__PRETTY_FUNCTION__); return 8;} + + +int Baz (int const *ptr, int *ptr2) +{ + if (Foo (ptr) != 1) + return 1; + if (Foo (ptr2) != 1) + return 2; + if (Foo (*ptr) != 3) + return 3; + if (Foo (*ptr2) != 2) + return 4; + + if (Bar (ptr) != 4) + return 5; + + if (Quux (ptr) != 7) + return 5; + if (Quux (ptr2) != 7) + return 6; + + return 0; +} + +int main () +{ + return Baz (0, 0); +}