PATCH for overload resolution
Mark Mitchell
mmitchell@usa.net
Tue May 5 00:50:00 GMT 1998
Jason --
Here's a patch that consists of a substantial reworking of
compare_ics. I started out to fix a particular bug, but it looked
like the whole thing could use some work, and I suspect I fixed a few
other bugs in the process. Here's the test-case:
template <class T>
class ConstArray {
};
template <class T1, class T2>
void operator+(const ConstArray<T1>&, const ConstArray<T2>&);
template <class T1, class T2>
void operator+(const ConstArray<T1>&, T2);
template <class T1, class T2>
void operator+(T1, const ConstArray<T2>&);
const ConstArray<int> cai();
const ConstArray<double> cad();
void f()
{
cai () + cad ();
}
This used to cause a bogus error message.
--
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available
Mon May 4 09:41:00 1998 Mark Mitchell <mmitchell@usa.net>
* call.c (compare_qual): Remove.
(ICS_THIS_FLAG): Likewise.
(add_function_candidate): Handle `this' parameters in conformance
with the standard; i.e., build implicit conversion sequences for
them as if they were reference, rather than pointer, parameters.
(is_subseq): Tweak.
(compare_ics): Modify substantially to bring into conformance with
the standard.
* cp-tree.h (is_derived_from): Declare
(comp_cv_qualification): Likewise.
* search.c (is_derived_from): Define.
* typeck.c (comp_cv_qualification): Likewise.
Index: cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.67
diff -c -p -r1.67 call.c
*** call.c 1998/05/03 02:30:57 1.67
--- call.c 1998/05/04 15:56:22
*************** static tree build_field_call PROTO((tree
*** 44,50 ****
static tree find_scoped_type PROTO((tree, tree, tree));
static struct z_candidate * tourney PROTO((struct z_candidate *));
static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
- static int compare_qual PROTO((tree, tree));
static int compare_ics PROTO((tree, tree));
static tree build_over_call PROTO((struct z_candidate *, tree, int));
static tree convert_default_arg PROTO((tree, tree));
--- 44,49 ----
*************** struct z_candidate {
*** 687,693 ****
#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE)
#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
- #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
#define USER_CONV_CAND(NODE) \
--- 688,693 ----
*************** add_function_candidate (candidates, fn,
*** 1122,1138 ****
if (parmnode == void_list_node)
break;
else if (parmnode)
! t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
else
{
t = build1 (IDENTITY_CONV, argtype, arg);
ICS_ELLIPSIS_FLAG (t) = 1;
}
- if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
- && ! DECL_CONSTRUCTOR_P (fn))
- ICS_THIS_FLAG (t) = 1;
-
TREE_VEC_ELT (convs, i) = t;
if (! t)
break;
--- 1122,1156 ----
if (parmnode == void_list_node)
break;
else if (parmnode)
! {
! tree parmtype = TREE_VALUE (parmnode);
!
! if (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
! && !DECL_CONSTRUCTOR_P (fn)
! /* This last condition avoids problems with signatures. */
! && TYPE_PTR_P (parmtype))
! {
! /* [over.match.funcs]
!
! For non-static member functions, the type of the
! implicit object parameter is "reference to cv X"
! where X is the class of which the function is a
! member and cv is the cv-qualification on the member
! function declaration. */
! parmtype = build_reference_type (TREE_TYPE (parmtype));
!
! if (TYPE_PTR_P (argtype))
! argtype = build_reference_type (TREE_TYPE (argtype));
! }
!
! t = implicit_conversion (parmtype, argtype, arg, flags);
! }
else
{
t = build1 (IDENTITY_CONV, argtype, arg);
ICS_ELLIPSIS_FLAG (t) = 1;
}
TREE_VEC_ELT (convs, i) = t;
if (! t)
break;
*************** build_new_method_call (instance, name, a
*** 3624,3693 ****
flags);
}
! /* Compare two implicit conversion sequences that differ only in their
! qualification conversion. Subroutine of compare_ics. */
static int
! compare_qual (ics1, ics2)
tree ics1, ics2;
{
! tree to1 = TREE_TYPE (ics1);
! tree to2 = TREE_TYPE (ics2);
!
! if (TYPE_PTRMEMFUNC_P (to1))
! to1 = TYPE_PTRMEMFUNC_FN_TYPE (to1);
! if (TYPE_PTRMEMFUNC_P (to2))
! to2 = TYPE_PTRMEMFUNC_FN_TYPE (to2);
! to1 = TREE_TYPE (to1);
! to2 = TREE_TYPE (to2);
!
! if (TREE_CODE (to1) == OFFSET_TYPE)
! {
! to1 = TREE_TYPE (to1);
! to2 = TREE_TYPE (to2);
! }
!
! if (TYPE_READONLY (to1) >= TYPE_READONLY (to2)
! && TYPE_VOLATILE (to1) > TYPE_VOLATILE (to2))
! return -1;
! else if (TYPE_READONLY (to1) > TYPE_READONLY (to2)
! && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
! return -1;
! else if (TYPE_READONLY (to1) <= TYPE_READONLY (to2)
! && TYPE_VOLATILE (to1) < TYPE_VOLATILE (to2))
! return 1;
! else if (TYPE_READONLY (to1) < TYPE_READONLY (to2)
! && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
! return 1;
! return 0;
! }
!
! /* Determine whether standard conversion sequence ICS1 is a proper
! subsequence of ICS2. We assume that a conversion of the same code
! between the same types indicates a subsequence. */
! static int
! is_subseq (ics1, ics2)
! tree ics1, ics2;
! {
! /* Do not consider lvalue transformations here. */
! if (TREE_CODE (ics2) == RVALUE_CONV
! || TREE_CODE (ics2) == LVALUE_CONV)
! return 0;
- for (;; ics2 = TREE_OPERAND (ics2, 0))
- {
if (TREE_CODE (ics2) == TREE_CODE (ics1)
&& comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1)
&& comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)),
TREE_TYPE (TREE_OPERAND (ics1, 0)), 1))
return 1;
-
- if (TREE_CODE (ics2) == USER_CONV
- || TREE_CODE (ics2) == AMBIG_CONV
- || TREE_CODE (ics2) == IDENTITY_CONV)
- return 0;
}
}
--- 3647,3689 ----
flags);
}
! /* Returns non-zero iff standard conversion sequence ICS1 is a proper
! subsequence of ICS2. */
static int
! is_subseq (ics1, ics2)
tree ics1, ics2;
{
! /* We can assume that a conversion of the same code
! between the same types indicates a subsequence since we only get
! here if the types we are converting from are the same. */
!
! while (TREE_CODE (ics1) == RVALUE_CONV
! || TREE_CODE (ics1) == LVALUE_CONV)
! ics1 = TREE_OPERAND (ics1, 0);
!
! while (1)
! {
! while (TREE_CODE (ics2) == RVALUE_CONV
! || TREE_CODE (ics2) == LVALUE_CONV)
! ics2 = TREE_OPERAND (ics2, 0);
! if (TREE_CODE (ics2) == USER_CONV
! || TREE_CODE (ics2) == AMBIG_CONV
! || TREE_CODE (ics2) == IDENTITY_CONV)
! /* At this point, ICS1 cannot be a proper subsequence of
! ICS2. We can get a USER_CONV when we are comparing the
! second standard conversion sequence of two user conversion
! sequences. */
! return 0;
! ics2 = TREE_OPERAND (ics2, 0);
if (TREE_CODE (ics2) == TREE_CODE (ics1)
&& comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1)
&& comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)),
TREE_TYPE (TREE_OPERAND (ics1, 0)), 1))
return 1;
}
}
*************** static int
*** 3702,3749 ****
compare_ics (ics1, ics2)
tree ics1, ics2;
{
! tree main1, main2;
!
! if (TREE_CODE (ics1) == QUAL_CONV)
! main1 = TREE_OPERAND (ics1, 0);
! else
! main1 = ics1;
!
! if (TREE_CODE (ics2) == QUAL_CONV)
! main2 = TREE_OPERAND (ics2, 0);
! else
! main2 = ics2;
!
! /* Conversions for `this' are PTR_CONVs, but we compare them as though
! they were REF_BINDs. */
! if (ICS_THIS_FLAG (ics1))
! {
! tree t = main1;
! if (TREE_CODE (t) == PTR_CONV)
! t = TREE_OPERAND (t, 0);
! t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
! t = build_conv (REF_BIND, TREE_TYPE (ics1), t);
! ICS_STD_RANK (t) = ICS_STD_RANK (main1);
! main1 = ics1 = t;
! }
! if (ICS_THIS_FLAG (ics2))
! {
! tree t = main2;
! if (TREE_CODE (t) == PTR_CONV)
! t = TREE_OPERAND (t, 0);
! t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
! t = build_conv (REF_BIND, TREE_TYPE (ics2), t);
! ICS_STD_RANK (t) = ICS_STD_RANK (main2);
! main2 = ics2 = t;
! }
!
! if (ICS_RANK (ics1) > ICS_RANK (ics2))
! return -1;
! else if (ICS_RANK (ics1) < ICS_RANK (ics2))
return 1;
! if (ICS_RANK (ics1) == BAD_RANK)
{
if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
|| ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
return -1;
--- 3698,3783 ----
compare_ics (ics1, ics2)
tree ics1, ics2;
{
! tree from_type1 = NULL_TREE;
! tree from_type2;
! tree orig_to_type1;
! tree orig_to_type2;
! tree to_type1;
! tree to_type2;
! int ref_binding_1;
! int ref_binding_2;
!
! /* [over.ics.rank]
!
! When a parameter of reference type binds directly
! (_dcl.init.ref_) to an argument expression, the implicit
! conversion sequence is the identity conversion, unless the
! argument expression has a type that is a derived class of the
! parameter type, in which case the implicit conversion sequence
! is a derived-to-base Conversion.
!
! If the parameter binds directly to the result of applying a
! conversion function to the argument expression, the implicit
! conversion sequence is a user-defined conversion sequence
! (_over.ics.user_), with the second standard conversion sequence
! either an identity conversion or, if the conversion function
! returns an entity of a type that is a derived class of the
! parameter type, a derived-to-base Conversion.
!
! When a parameter of reference type is not bound directly to an
! argument expression, the conversion sequence is the one required
! to convert the argument expression to the underlying type of the
! reference according to _over.best.ics_. Conceptually, this
! conversion sequence corresponds to copy-initializing a temporary
! of the underlying type with the argument expression. Any
! difference in top-level cv-qualification is subsumed by the
! initialization itself and does not constitute a conversion. */
!
! if (TREE_CODE (ics1) == REF_BIND)
! {
! ref_binding_1 = 1;
! orig_to_type1 = TREE_TYPE (TREE_TYPE (ics1));
! ics1 = TREE_OPERAND (ics1, 0);
! if (TREE_CODE (ics1) == IDENTITY_CONV
! && is_derived_from (TREE_TYPE (ics1), orig_to_type1))
! ics1 = build_conv (BASE_CONV, orig_to_type1, ics1);
! }
! else
! ref_binding_1 = 0;
!
! if (TREE_CODE (ics2) == REF_BIND)
! {
! ref_binding_2 = 1;
! orig_to_type2 = TREE_TYPE (TREE_TYPE (ics2));
! ics2 = TREE_OPERAND (ics2, 0);
! if (TREE_CODE (ics2) == IDENTITY_CONV
! && is_derived_from (TREE_TYPE (ics2), orig_to_type2))
! ics2 = build_conv (BASE_CONV, orig_to_type2, ics2);
! }
! else
! ref_binding_2 = 0;
!
! /* [over.ics.rank]
!
! When comparing the basic forms of implicit conversion sequences (as
! defined in _over.best.ics_)
!
! --a standard conversion sequence (_over.ics.scs_) is a better
! conversion sequence than a user-defined conversion sequence
! or an ellipsis conversion sequence, and
!
! --a user-defined conversion sequence (_over.ics.user_) is a
! better conversion sequence than an ellipsis conversion sequence
! (_over.ics.ellipsis_). */
! if (ICS_RANK (ics1) < ICS_RANK (ics2))
return 1;
+ else if (ICS_RANK (ics2) < ICS_RANK (ics1))
+ return -1;
! if (ICS_BAD_FLAG (ics1))
{
+ /* Both ICS are bad. We try to make a decision based on what
+ would have happenned if they'd been good. */
if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
|| ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
return -1;
*************** compare_ics (ics1, ics2)
*** 3751,3768 ****
|| ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
return 1;
! /* else fall through */
}
! /* User-defined conversion sequence U1 is a better conversion sequence
! than another user-defined conversion sequence U2 if they contain the
! same user-defined conversion operator or constructor and if the sec-
! ond standard conversion sequence of U1 is better than the second
! standard conversion sequence of U2. */
if (ICS_USER_FLAG (ics1))
{
tree t1, t2;
for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0))
if (TREE_CODE (t1) == AMBIG_CONV)
--- 3785,3810 ----
|| ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
return 1;
! /* We couldn't make up our minds; try to figure it out below. */
}
! if (ICS_ELLIPSIS_FLAG (ics1))
! /* Both conversions are ellipsis conversions. */
! return 0;
if (ICS_USER_FLAG (ics1))
{
+ /* [over.ics.rank]
+
+ User-defined conversion sequence U1 is a better conversion
+ sequence than another user-defined conversion sequence U2 if
+ they contain the same user-defined conversion function or
+ constructor and if the second standard conversion sequence
+ of U1 is better than the second standard conversion sequence
+ of U2. */
+
tree t1, t2;
+ int result;
for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0))
if (TREE_CODE (t1) == AMBIG_CONV)
*************** compare_ics (ics1, ics2)
*** 3773,3947 ****
if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
return 0;
- else if (ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
- return -1;
- else if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
- return 1;
! /* else fall through */
}
! #if 0 /* Handled by ranking */
! /* A conversion that is not a conversion of a pointer, or pointer to
! member, to bool is better than another conversion that is such a
! conversion. */
! #endif
! if (TREE_CODE (main1) != TREE_CODE (main2))
{
! /* ...if S1 is a proper subsequence of S2 */
! if (is_subseq (main1, main2))
return 1;
! if (is_subseq (main2, main1))
return -1;
- return 0;
}
! if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV
! || TREE_CODE (main1) == REF_BIND || TREE_CODE (main1) == BASE_CONV)
! {
! tree to1 = TREE_TYPE (main1);
! tree from1 = TREE_TYPE (TREE_OPERAND (main1, 0));
! tree to2 = TREE_TYPE (main2);
! tree from2 = TREE_TYPE (TREE_OPERAND (main2, 0));
! int distf, distt;
! /* Standard conversion sequence S1 is a better conversion sequence than
! standard conversion sequence S2 if...
! S1 and S2 differ only in their qualification conversion and they
! yield types identical except for cv-qualifiers and S2 adds all the
! qualifiers that S1 adds (and in the same places) and S2 adds yet
! more cv-qualifiers than S1, or the similar case with reference
! binding15). */
! if (TREE_CODE (main1) == REF_BIND)
! {
! if (TYPE_MAIN_VARIANT (TREE_TYPE (to1))
! == TYPE_MAIN_VARIANT (TREE_TYPE (to2)))
! return compare_qual (ics1, ics2);
! }
! else if (TREE_CODE (main1) != BASE_CONV && from1 == from2 && to1 == to2)
! return compare_qual (ics1, ics2);
!
! if (TYPE_PTRMEMFUNC_P (to1))
! {
! to1 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to1)));
! from1 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from1)));
! }
! else if (TREE_CODE (main1) != BASE_CONV)
! {
! to1 = TREE_TYPE (to1);
! if (TREE_CODE (main1) != REF_BIND)
! from1 = TREE_TYPE (from1);
! if (TREE_CODE (to1) == OFFSET_TYPE)
! {
! to1 = TYPE_OFFSET_BASETYPE (to1);
! from1 = TYPE_OFFSET_BASETYPE (from1);
! }
! }
! if (TYPE_PTRMEMFUNC_P (to2))
{
! to2 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2)));
! from2 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from2)));
}
! else if (TREE_CODE (main1) != BASE_CONV)
{
! to2 = TREE_TYPE (to2);
! if (TREE_CODE (main1) != REF_BIND)
! from2 = TREE_TYPE (from2);
!
! if (TREE_CODE (to2) == OFFSET_TYPE)
{
! to2 = TYPE_OFFSET_BASETYPE (to2);
! from2 = TYPE_OFFSET_BASETYPE (from2);
}
}
!
! if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2)))
! return 0;
!
! /* The sense of pmem conversions is reversed from that of the other
! conversions. */
! if (TREE_CODE (main1) == PMEM_CONV)
{
! tree t = from1; from1 = from2; from2 = t;
! t = to1; to1 = to2; to2 = t;
! }
! distf = get_base_distance (from1, from2, 0, 0);
! if (distf == -1)
! {
! distf = -get_base_distance (from2, from1, 0, 0);
! if (distf == 1)
! return 0;
}
!
! /* If class B is derived directly or indirectly from class A,
! conver- sion of B* to A* is better than conversion of B* to
! void*, and conversion of A* to void* is better than
! conversion of B* to void*. */
!
! if (TREE_CODE (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE)
{
! if (distf > 0)
return 1;
! else if (distf < 0)
return -1;
}
! else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1)
! && get_base_distance (to1, from1, 0, 0) != -1)
! return 1;
! else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2)
! && get_base_distance (to2, from2, 0, 0) != -1)
! return -1;
!
! if (! (IS_AGGR_TYPE (to1) && IS_AGGR_TYPE (to2)))
! return 0;
! /* If class B is derived directly or indirectly from class A and class
! C is derived directly or indirectly from B */
! distt = get_base_distance (to1, to2, 0, 0);
! if (distt == -1)
! {
! distt = -get_base_distance (to2, to1, 0, 0);
! if (distt == 1)
! return 0;
! }
!
! /* --conversion of C* to B* is better than conversion of C* to A*, */
! if (distf == 0)
! {
! if (distt > 0)
! return -1;
! else if (distt < 0)
! return 1;
! }
! /* --conversion of B* to A* is better than conversion of C* to A*, */
! else if (distt == 0)
{
! if (distf > 0)
return 1;
! else if (distf < 0)
return -1;
}
}
- else if (TREE_CODE (TREE_TYPE (main1)) == POINTER_TYPE
- || TYPE_PTRMEMFUNC_P (TREE_TYPE (main1)))
- {
- if (TREE_TYPE (main1) == TREE_TYPE (main2))
- return compare_qual (ics1, ics2);
! #if 0 /* This is now handled by making identity better than anything else. */
! /* existing practice, not WP-endorsed: const char * -> const char *
! is better than char * -> const char *. (jason 6/29/96) */
! if (TREE_TYPE (ics1) == TREE_TYPE (ics2))
! return -compare_qual (main1, main2);
! #endif
! }
return 0;
}
--- 3815,4041 ----
if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
return 0;
! /* We can just fall through here, after setting up
! FROM_TYPE1 and FROM_TYPE2. */
! from_type1 = TREE_TYPE (t1);
! from_type2 = TREE_TYPE (t2);
}
! /* We're dealing with two standard conversion sequences.
!
! [over.ics.rank]
! Standard conversion sequence S1 is a better conversion sequence than
! standard conversion sequence S2 if
!
! --S1 is a proper subsequence of S2 (comparing the conversion
! sequences in the canonical form defined by _over.ics.scs_,
! excluding any Lvalue Transformation; the identity conversion
! sequence is considered to be a subsequence of any non-identity
! conversion sequence */
!
! if (from_type1 == NULL_TREE)
! {
! from_type1 = ics1;
! while (TREE_CODE (from_type1) != IDENTITY_CONV)
! from_type1 = TREE_OPERAND (from_type1, 0);
! from_type1 = TREE_TYPE (from_type1);
!
! from_type2 = ics2;
! while (TREE_CODE (from_type2) != IDENTITY_CONV)
! from_type2 = TREE_OPERAND (from_type2, 0);
! from_type2 = TREE_TYPE (from_type2);
! }
!
! if (comptypes (from_type1, from_type2, 1))
{
! if (is_subseq (ics1, ics2))
return 1;
! if (is_subseq (ics2, ics1))
return -1;
}
+ else
+ /* One sequence cannot be a subsequence of the other; they don't
+ start with the same type. This can happen when comparing the
+ second standard conversion sequence in two user-defined
+ conversion sequences. */
+ ;
! /* [over.ics.rank]
! Or, if not that,
! --the rank of S1 is better than the rank of S2 (by the rules
! defined below):
! Standard conversion sequences are ordered by their ranks: an Exact
! Match is a better conversion than a Promotion, which is a better
! conversion than a Conversion.
!
! Two conversion sequences with the same rank are indistinguishable
! unless one of the following rules applies:
!
! --A conversion that is not a conversion of a pointer, or pointer
! to member, to bool is better than another conversion that is such
! a conversion.
!
! The ICS_STD_RANK automatically handles the pointer-to-bool rule,
! so that we do not have to check it explicitly. */
! if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
! return 1;
! else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1))
! return -1;
!
! to_type1 = TREE_TYPE (ics1);
! to_type2 = TREE_TYPE (ics2);
! /* The rules for pointers to members A::* are just like the rules
! for pointers A*. */
! if (TYPE_PTRMEM_P (from_type1)
! && TYPE_PTRMEM_P (from_type2)
! && TYPE_PTRMEM_P (to_type1)
! && TYPE_PTRMEM_P (to_type2))
! {
! from_type1 = build_pointer_type (TYPE_OFFSET_BASETYPE (from_type1));
! from_type2 = build_pointer_type (TYPE_OFFSET_BASETYPE (from_type2));
! to_type1 = build_pointer_type (TYPE_OFFSET_BASETYPE (to_type1));
! to_type2 = build_pointer_type (TYPE_OFFSET_BASETYPE (to_type2));
! }
! else if (TYPE_PTRMEMFUNC_P (from_type1)
! && TYPE_PTRMEMFUNC_P (from_type2)
! && TYPE_PTRMEMFUNC_P (to_type1)
! && TYPE_PTRMEMFUNC_P (to_type2))
! {
! from_type1 = TYPE_PTRMEMFUNC_FN_TYPE (from_type1);
! from_type2 = TYPE_PTRMEMFUNC_FN_TYPE (from_type2);
! to_type1 = TYPE_PTRMEMFUNC_FN_TYPE (to_type1);
! to_type2 = TYPE_PTRMEMFUNC_FN_TYPE (to_type2);
! }
!
! if (TYPE_PTR_P (from_type1)
! && TYPE_PTR_P (from_type2)
! && TYPE_PTR_P (to_type1)
! && TYPE_PTR_P (to_type2))
! {
! /* [over.ics.rank]
!
! --If class B is derived directly or indirectly from class A,
! conversion of B* to A* is better than conversion of B* to
! void*, and conversion of A* to void* is better than
! conversion of B* to void*. */
! if (TREE_CODE (TREE_TYPE (to_type1)) == VOID_TYPE
! && TREE_CODE (TREE_TYPE (to_type1)) == VOID_TYPE)
{
! if (is_derived_from (TREE_TYPE (from_type1),
! TREE_TYPE (from_type2)))
! return -1;
! else if (is_derived_from (TREE_TYPE (from_type2),
! TREE_TYPE (from_type1)))
! return 1;
}
! else if (TREE_CODE (TREE_TYPE (to_type1)) == VOID_TYPE
! || TREE_CODE (TREE_TYPE (to_type2)) == VOID_TYPE)
{
! if (comptypes (from_type1, from_type2, 1))
{
! if (TREE_CODE (TREE_TYPE (to_type2)) == VOID_TYPE)
! {
! if (is_derived_from (TREE_TYPE (from_type1),
! TREE_TYPE (to_type1)))
! return 1;
! }
! /* We know that TO_TYPE1 is `void*' here. */
! else if (is_derived_from (TREE_TYPE (from_type2),
! TREE_TYPE (to_type2)))
! return -1;
}
}
! else
{
! /* [over.ics.rank]
! --If class B is derived directly or indirectly from class A
! and class C is derived directly or indirectly from B,
!
! --conversion of C* to B* is better than conversion of C* to
! A*,
!
! --conversion of B* to A* is better than conversion of C* to
! A* */
! if (comptypes (from_type1, from_type2, 1))
! {
! if (is_derived_from (TREE_TYPE (to_type1),
! TREE_TYPE (to_type2)))
! return 1;
! else if (is_derived_from (TREE_TYPE (to_type2),
! TREE_TYPE (to_type1)))
! return -1;
! }
! else if (comptypes (to_type1, to_type2, 1))
! {
! if (is_derived_from (TREE_TYPE (from_type2),
! TREE_TYPE (from_type1)))
! return 1;
! else if (is_derived_from (TREE_TYPE (from_type1),
! TREE_TYPE (from_type2)))
! return -1;
! }
}
! }
! else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
! && comptypes (from_type1, from_type2, 1))
! {
! /* [over.ics.rank]
!
! --binding of an expression of type C to a reference of type
! B& is better than binding an expression of type C to a
! reference of type A&
!
! --conversion of C to B is better than conversion of C to A, */
! if (is_derived_from (from_type1, to_type1)
! && is_derived_from (from_type1, to_type2))
{
! if (is_derived_from (to_type1, to_type2))
return 1;
! else if (is_derived_from (to_type2, to_type1))
return -1;
}
! }
! else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
! && comptypes (to_type1, to_type2, 1))
! {
! /* [over.ics.rank]
! --binding of an expression of type B to a reference of type
! A& is better than binding an expression of type C to a
! reference of type A&,
! --onversion of B to A is better than conversion of C to A */
! if (is_derived_from (from_type1, to_type1)
! && is_derived_from (from_type2, to_type1))
{
! if (is_derived_from (from_type2, from_type1))
return 1;
! else if (is_derived_from (from_type1, from_type2))
return -1;
}
}
! /* [over.ics.rank]
!
! --S1 and S2 are reference bindings (_dcl.init.ref_), and the
! types to which the references refer are the same type except
! for top-level cv-qualifiers, and the type to which the
! reference initialized by S2 refers is more cv-qualified than
! the type to which the reference initialized by S1 refers */
!
! if (ref_binding_1 && ref_binding_2
! && comptypes (TYPE_MAIN_VARIANT (to_type1),
! TYPE_MAIN_VARIANT (to_type2), 1))
! return comp_cv_qualification (orig_to_type2, orig_to_type1);
+ /* Neither conversion sequence is better than the other. */
return 0;
}
Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.58
diff -c -p -r1.58 cp-tree.h
*** cp-tree.h 1998/04/26 16:29:58 1.58
--- cp-tree.h 1998/05/04 15:56:47
*************** extern void pop_memoized_context PROTO(
*** 2516,2521 ****
--- 2533,2539 ----
extern tree get_vbase PROTO((tree, tree));
extern tree get_binfo PROTO((tree, tree, int));
extern int get_base_distance PROTO((tree, tree, int, tree *));
+ extern int is_derived_from PROTO((tree, tree));
extern tree compute_access PROTO((tree, tree));
extern tree lookup_field PROTO((tree, tree, int, int));
extern tree lookup_nested_field PROTO((tree, int));
*************** extern int comptypes PROTO((tree, tre
*** 2690,2695 ****
--- 2719,2725 ----
extern int comp_target_types PROTO((tree, tree, int));
extern int compparms PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int));
+ extern int comp_cv_qualification PROTO((tree, tree));
extern int self_promoting_args_p PROTO((tree));
extern tree unsigned_type PROTO((tree));
extern tree signed_type PROTO((tree));
Index: cp/search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.22
diff -c -p -r1.22 search.c
*** search.c 1998/04/17 08:05:24 1.22
--- search.c 1998/05/04 15:58:58
*************** get_base_distance (parent, binfo, protec
*** 790,795 ****
--- 790,810 ----
return rval;
}
+ /* Returns non-zero iff DERIVED is derived from BASE. The inputs may
+ be any _TYPE nodes. */
+
+ int
+ is_derived_from (derived, base)
+ tree derived;
+ tree base;
+ {
+ if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
+ || !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
+ return 0;
+
+ return get_base_distance (derived, base, /*protect=*/0, /*path_ptr=*/0);
+ }
+
/* Search for a member with name NAME in a multiple inheritance lattice
specified by TYPE. If it does not exist, return NULL_TREE.
If the member is ambiguously referenced, return `error_mark_node'.
Index: cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.61
diff -c -p -r1.61 typeck.c
*** typeck.c 1998/04/26 16:30:11 1.61
--- typeck.c 1998/05/04 15:59:21
*************** comp_target_types (ttl, ttr, nptrs)
*** 1019,1024 ****
--- 1019,1047 ----
return 0;
}
+ /* Returns 1 if TYPE1 is more cv-qualified than TYPE2, -1 if TYPE2 is
+ more cv-qualified that TYPE1, and 0 otherwise. */
+
+ int
+ comp_cv_qualification (type1, type2)
+ tree type1;
+ tree type2;
+ {
+ if (TYPE_READONLY (type1) == TYPE_READONLY (type2)
+ && TYPE_VOLATILE (type1) == TYPE_VOLATILE (type2))
+ return 0;
+
+ if (TYPE_READONLY (type1) >= TYPE_READONLY (type2)
+ && TYPE_VOLATILE (type1) >= TYPE_VOLATILE (type2))
+ return 1;
+
+ if (TYPE_READONLY (type2) >= TYPE_READONLY (type1)
+ && TYPE_VOLATILE (type2) >= TYPE_VOLATILE (type1))
+ return -1;
+
+ return 0;
+ }
+
/* If two types share a common base type, return that basetype.
If there is not a unique most-derived base type, this function
returns ERROR_MARK_NODE. */
Index: testsuite/g++.old-deja/g++.other/overload2.C
===================================================================
RCS file: overload2.C
diff -N overload2.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- overload2.C Mon May 4 09:48:42 1998
***************
*** 0 ****
--- 1,22 ----
+ // Build don't link:
+
+ template <class T>
+ class ConstArray {
+ };
+
+ template <class T1, class T2>
+ void operator+(const ConstArray<T1>&, const ConstArray<T2>&);
+
+ template <class T1, class T2>
+ void operator+(const ConstArray<T1>&, T2);
+
+ template <class T1, class T2>
+ void operator+(T1, const ConstArray<T2>&);
+
+ const ConstArray<int> cai();
+ const ConstArray<double> cad();
+
+ void f()
+ {
+ cai () + cad ();
+ }
More information about the Gcc-bugs
mailing list