This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH]: Bug 1617
Mark Mitchell wrote:
> `T*' is more specialized that `T const &'? I see, because a `T
> const&' is pretty much like a `T'? Is that the thinking.
Yup. During deduction a template type T will become say, `int', not
`int const &'. That's not taken into account with when ordering.
> ! fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), 99999);
>
> What's with the 99999? Surely we need some name for this magic value?
> What does 99999 signify?
Okay -- I'd overloaded the meaning of `len' - bad. I've added a
parameter to explicitly say what to do. It also removes get_bindings_order, as
that kind of wasn't doing anything anymore.
> So, let's rework the comment to explain what process you're talking
> about.
Ok, no ARG or PARM abuse going on now :)
> Once we resolve the 99999 thing, the patch is OK.
I've installed the attached patch which has those amendments.
built & tested on i686-pc-linux-gnu.
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-01-22 Nathan Sidwell <nathan@codesourcery.com>
* 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.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/call.c,v
retrieving revision 1.249
diff -c -3 -p -r1.249 call.c
*** call.c 2001/01/17 05:59:51 1.249
--- call.c 2001/01/22 13:15:53
*************** joust (cand1, cand2, warn)
*** 5196,5201 ****
--- 5196,5202 ----
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));
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.564
diff -c -3 -p -r1.564 cp-tree.h
*** cp-tree.h 2001/01/19 09:24:11 1.564
--- cp-tree.h 2001/01/22 13:15:59
*************** extern int function_depth;
*** 3209,3222 ****
/* in pt.c */
! /* These values are used for the `STRICT' parameter to type_unfication 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
} unification_kind_t;
/* Macros for operating on a template instantation level node, represented
--- 3209,3223 ----
/* in pt.c */
! /* 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_ORDER
} unification_kind_t;
/* Macros for operating on a template instantation level node, represented
*************** extern tree instantiate_template PARAMS
*** 4143,4149 ****
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 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));
--- 4144,4150 ----
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, 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));
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.508
diff -c -3 -p -r1.508 pt.c
*** pt.c 2001/01/19 09:24:14 1.508
--- pt.c 2001/01/22 13:16:06
*************** static htab_t local_specializations;
*** 87,92 ****
--- 87,94 ----
#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
*************** static tree coerce_template_parms PARAMS
*** 111,117 ****
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*,
tree*));
static int type_unification_real PARAMS ((tree, tree, tree, tree,
int, unification_kind_t, int, int));
--- 113,119 ----
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 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));
*************** static tree convert_nontype_argument PAR
*** 121,127 ****
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));
--- 123,128 ----
*************** static tree build_template_decl PARAMS (
*** 136,142 ****
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 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));
--- 137,143 ----
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, 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));
*************** instantiate_template (tmpl, targ_ptr)
*** 7681,7693 ****
[temp.deduct.conv].
DEDUCE_EXACT:
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].
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
--- 7682,7696 ----
[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].
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
*************** fn_type_unification (fn, explicit_targs,
*** 7793,7804 ****
the argument passed to the call, or the type of the value
initialized with the result of the conversion function. */
! static void
maybe_adjust_types_for_deduction (strict, parm, arg)
unification_kind_t strict;
tree* parm;
tree* arg;
{
switch (strict)
{
case DEDUCE_CALL:
--- 7796,7809 ----
the argument passed to the call, or the type of the value
initialized with the result of the conversion function. */
! 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:
*************** maybe_adjust_types_for_deduction (strict
*** 7817,7824 ****
case DEDUCE_EXACT:
/* There is nothing to do in this case. */
! return;
default:
my_friendly_abort (0);
}
--- 7822,7864 ----
case DEDUCE_EXACT:
/* There is nothing to do in this case. */
! 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);
}
*************** maybe_adjust_types_for_deduction (strict
*** 7849,7854 ****
--- 7889,7895 ----
*arg = TYPE_MAIN_VARIANT (*arg);
}
+ skip_arg:;
/* [temp.deduct.call]
If P is a cv-qualified type, the top level cv-qualifiers
*************** maybe_adjust_types_for_deduction (strict
*** 7857,7863 ****
type deduction. */
*parm = TYPE_MAIN_VARIANT (*parm);
if (TREE_CODE (*parm) == REFERENCE_TYPE)
! *parm = TREE_TYPE (*parm);
}
/* Most parms like fn_type_unification.
--- 7898,7908 ----
type deduction. */
*parm = TYPE_MAIN_VARIANT (*parm);
if (TREE_CODE (*parm) == REFERENCE_TYPE)
! {
! *parm = TREE_TYPE (*parm);
! result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
! }
! return result;
}
/* Most parms like fn_type_unification.
*************** type_unification_real (tparms, targs, pa
*** 7902,7907 ****
--- 7947,7956 ----
case DEDUCE_EXACT:
sub_strict = UNIFY_ALLOW_NONE;
break;
+
+ case DEDUCE_ORDER:
+ sub_strict = UNIFY_ALLOW_NONE;
+ break;
default:
my_friendly_abort (0);
*************** type_unification_real (tparms, targs, pa
*** 7943,7949 ****
arg = NULL_TREE;
}
! if (strict == DEDUCE_EXACT)
{
if (same_type_p (parm, type))
continue;
--- 7992,7998 ----
arg = NULL_TREE;
}
! if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER)
{
if (same_type_p (parm, type))
continue;
*************** type_unification_real (tparms, targs, pa
*** 7976,7987 ****
}
arg = TREE_TYPE (arg);
}
!
! if (!subr)
! maybe_adjust_types_for_deduction (strict, &parm, &arg);
! if (unify (tparms, targs, parm, arg, sub_strict))
! return 1;
/* Are we done with the interesting parms? */
if (--len == 0)
--- 8025,8040 ----
}
arg = TREE_TYPE (arg);
}
!
! {
! int arg_strict = sub_strict;
!
! if (!subr)
! arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
! if (unify (tparms, targs, parm, arg, arg_strict))
! return 1;
! }
/* Are we done with the interesting parms? */
if (--len == 0)
*************** try_one_overload (tparms, orig_targs, ta
*** 8129,8135 ****
if (uses_template_parms (arg))
return 1;
! 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
--- 8182,8188 ----
if (uses_template_parms (arg))
return 1;
! 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
*************** check_cv_quals_for_unify (strict, arg, p
*** 8413,8423 ****
tree arg;
tree parm;
{
! if (!(strict & UNIFY_ALLOW_MORE_CV_QUAL)
&& !at_least_as_qualified_p (arg, parm))
return 0;
! if (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
&& !at_least_as_qualified_p (parm, arg))
return 0;
--- 8466,8476 ----
tree arg;
tree parm;
{
! 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 | UNIFY_ALLOW_OUTER_LESS_CV_QUAL))
&& !at_least_as_qualified_p (parm, arg))
return 0;
*************** check_cv_quals_for_unify (strict, arg, p
*** 8448,8454 ****
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. */
static int
unify (tparms, targs, parm, arg, strict)
--- 8501,8513 ----
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.
! 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)
*************** unify (tparms, targs, parm, arg, strict)
*** 8498,8503 ****
--- 8557,8564 ----
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))
{
*************** mark_decl_instantiated (result, extern_p
*** 8963,8968 ****
--- 9024,9031 ----
/* 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.
*************** mark_decl_instantiated (result, extern_p
*** 8970,8987 ****
LEN is passed through to fn_type_unification. */
int
! more_specialized (pat1, pat2, len)
tree pat1, pat2;
int len;
{
tree targs;
int winner = 0;
! targs = get_bindings_order (pat1, DECL_TEMPLATE_RESULT (pat2), len);
if (targs)
--winner;
! targs = get_bindings_order (pat2, DECL_TEMPLATE_RESULT (pat1), len);
if (targs)
++winner;
--- 9033,9053 ----
LEN is passed through to fn_type_unification. */
int
! more_specialized (pat1, pat2, deduce, len)
tree pat1, pat2;
+ int deduce;
int len;
{
tree targs;
int winner = 0;
! targs = get_bindings_real (pat1, DECL_TEMPLATE_RESULT (pat2),
! NULL_TREE, 0, deduce, len);
if (targs)
--winner;
! targs = get_bindings_real (pat2, DECL_TEMPLATE_RESULT (pat1),
! NULL_TREE, 0, deduce, len);
if (targs)
++winner;
*************** more_specialized_class (pat1, pat2)
*** 9018,9029 ****
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. */
static tree
! get_bindings_real (fn, decl, explicit_args, check_rettype, len)
tree fn, decl, explicit_args;
! int check_rettype, len;
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
--- 9084,9095 ----
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. DEDUCE and LEN are passed through to fn_type_unification. */
static tree
! get_bindings_real (fn, decl, explicit_args, check_rettype, deduce, len)
tree fn, decl, explicit_args;
! int check_rettype, deduce, len;
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
*************** get_bindings_real (fn, decl, explicit_ar
*** 9069,9075 ****
decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
! DEDUCE_EXACT, len);
if (i != 0)
return NULL_TREE;
--- 9135,9141 ----
decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
! deduce, len);
if (i != 0)
return NULL_TREE;
*************** tree
*** 9083,9089 ****
get_bindings (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
! return get_bindings_real (fn, decl, explicit_args, 1, -1);
}
/* But for resolve_overloaded_unification, we only care about the parameter
--- 9149,9155 ----
get_bindings (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
! return get_bindings_real (fn, decl, explicit_args, 1, DEDUCE_EXACT, -1);
}
/* But for resolve_overloaded_unification, we only care about the parameter
*************** get_bindings (fn, decl, explicit_args)
*** 9092,9109 ****
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 the innermost template arguments that, when applied to a
--- 9158,9165 ----
static tree
get_bindings_overload (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
! return get_bindings_real (fn, decl, explicit_args, 0, DEDUCE_EXACT, -1);
}
/* Return the innermost template arguments that, when applied to a
*************** most_specialized_instantiation (instanti
*** 9162,9168 ****
champ = instantiations;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
! fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1);
if (fate == 1)
;
else
--- 9218,9225 ----
champ = instantiations;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
! fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
! DEDUCE_EXACT, -1);
if (fate == 1)
;
else
*************** most_specialized_instantiation (instanti
*** 9179,9185 ****
for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{
! fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1);
if (fate != 1)
return error_mark_node;
}
--- 9236,9243 ----
for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{
! fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
! DEDUCE_EXACT, -1);
if (fate != 1)
return error_mark_node;
}