Commit ceab47eb by Mark Mitchell Committed by Mark Mitchell

call.c (compare_qual): Remove.

	* call.c (compare_qual): Remove.
	(is_subseq): Tweak.
	(is_properly_derived_from): New function.
	(maybe_handle_ref_bind): Likewise.
	(maybe_handle_implicit_object): Likewise.
	(compare_ics): Modify substantially to bring into conformance with
	the standard.
	* cp-tree.h (TYPE_PTRMEMFUNC_OBJECT_TYPE): New macro.
	(comp_cv_qualification): Declare.
	(comp_cv_qual_signature): Likewise.
	* typeck.c (comp_cv_qualification): Likewise.
	(comp_cv_qual_signature): Likewise.

From-SVN: r19880
parent 06033860
Tue May 19 14:50:27 1998 Mark Mitchell <mmitchell@usa.net>
* call.c (compare_qual): Remove.
(is_subseq): Tweak.
(is_properly_derived_from): New function.
(maybe_handle_ref_bind): Likewise.
(maybe_handle_implicit_object): Likewise.
(compare_ics): Modify substantially to bring into conformance with
the standard.
* cp-tree.h (TYPE_PTRMEMFUNC_OBJECT_TYPE): New macro.
(comp_cv_qualification): Declare.
(comp_cv_qual_signature): Likewise.
* typeck.c (comp_cv_qualification): Likewise.
(comp_cv_qual_signature): Likewise.
Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> Tue May 19 10:05:02 1998 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in (parse.o): Depend on toplev.h. * Makefile.in (parse.o): Depend on toplev.h.
......
...@@ -45,7 +45,6 @@ static tree build_field_call PROTO((tree, tree, tree, tree)); ...@@ -45,7 +45,6 @@ static tree build_field_call PROTO((tree, tree, tree, tree));
static tree find_scoped_type PROTO((tree, tree, tree)); static tree find_scoped_type PROTO((tree, tree, tree));
static struct z_candidate * tourney PROTO((struct z_candidate *)); static struct z_candidate * tourney PROTO((struct z_candidate *));
static int joust PROTO((struct z_candidate *, struct z_candidate *, int)); 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 int compare_ics PROTO((tree, tree));
static tree build_over_call PROTO((struct z_candidate *, tree, int)); static tree build_over_call PROTO((struct z_candidate *, tree, int));
static tree convert_default_arg PROTO((tree, tree)); static tree convert_default_arg PROTO((tree, tree));
...@@ -89,6 +88,9 @@ static tree strip_top_quals PROTO((tree)); ...@@ -89,6 +88,9 @@ static tree strip_top_quals PROTO((tree));
static tree non_reference PROTO((tree)); static tree non_reference PROTO((tree));
static tree build_conv PROTO((enum tree_code, tree, tree)); static tree build_conv PROTO((enum tree_code, tree, tree));
static int is_subseq PROTO((tree, tree)); static int is_subseq PROTO((tree, tree));
static int is_properly_derived_from PROTO((tree, tree));
static int maybe_handle_ref_bind PROTO((tree*, tree*));
static void maybe_handle_implicit_object PROTO((tree*));
tree tree
build_vfield_ref (datum, type) build_vfield_ref (datum, type)
...@@ -3658,119 +3660,191 @@ build_new_method_call (instance, name, args, basetype_path, flags) ...@@ -3658,119 +3660,191 @@ build_new_method_call (instance, name, args, basetype_path, flags)
flags); flags);
} }
/* Compare two implicit conversion sequences that differ only in their /* Returns non-zero iff standard conversion sequence ICS1 is a proper
qualification conversion. Subroutine of compare_ics. */ subsequence of ICS2. */
static int static int
compare_qual (ics1, ics2) is_subseq (ics1, ics2)
tree ics1, ics2; tree ics1, ics2;
{ {
tree to1 = TREE_TYPE (ics1); /* We can assume that a conversion of the same code
tree to2 = TREE_TYPE (ics2); between the same types indicates a subsequence since we only get
here if the types we are converting from are the same. */
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); while (TREE_CODE (ics1) == RVALUE_CONV
to2 = TREE_TYPE (to2); || TREE_CODE (ics1) == LVALUE_CONV)
ics1 = TREE_OPERAND (ics1, 0);
if (TREE_CODE (to1) == OFFSET_TYPE) while (1)
{ {
to1 = TREE_TYPE (to1); while (TREE_CODE (ics2) == RVALUE_CONV
to2 = TREE_TYPE (to2); || TREE_CODE (ics2) == LVALUE_CONV)
} ics2 = TREE_OPERAND (ics2, 0);
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 if (TREE_CODE (ics2) == USER_CONV
subsequence of ICS2. We assume that a conversion of the same code || TREE_CODE (ics2) == AMBIG_CONV
between the same types indicates a subsequence. */ || 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;
static int ics2 = TREE_OPERAND (ics2, 0);
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) if (TREE_CODE (ics2) == TREE_CODE (ics1)
&& comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1) && comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1)
&& comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)), && comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)),
TREE_TYPE (TREE_OPERAND (ics1, 0)), 1)) TREE_TYPE (TREE_OPERAND (ics1, 0)), 1))
return 1; return 1;
if (TREE_CODE (ics2) == USER_CONV
|| TREE_CODE (ics2) == AMBIG_CONV
|| TREE_CODE (ics2) == IDENTITY_CONV)
return 0;
} }
} }
/* Compare two implicit conversion sequences according to the rules set out in /* Returns non-zero iff DERIVED is derived from BASE. The inputs may
[over.ics.rank]. Return values: be any _TYPE nodes. */
1: ics1 is better than ics2
-1: ics2 is better than ics1
0: ics1 and ics2 are indistinguishable */
static int static int
compare_ics (ics1, ics2) is_properly_derived_from (derived, base)
tree ics1, ics2; tree derived;
tree base;
{ {
tree main1, main2; if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
|| !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
return 0;
if (TREE_CODE (ics1) == QUAL_CONV) /* We only allow proper derivation here. The DERIVED_FROM_P macro
main1 = TREE_OPERAND (ics1, 0); considers every class derived from itself. */
else return (!comptypes (TYPE_MAIN_VARIANT (derived),
main1 = ics1; TYPE_MAIN_VARIANT (base), 1)
&& DERIVED_FROM_P (base, derived));
}
if (TREE_CODE (ics2) == QUAL_CONV) /* We build the ICS for an implicit object parameter as a pointer
main2 = TREE_OPERAND (ics2, 0); conversion sequence. However, such a sequence should be compared
else as if it were a reference conversion sequence. If ICS is the
main2 = ics2; implicit conversion sequence for an implicit object parameter,
modify it accordingly. */
/* Conversions for `this' are PTR_CONVs, but we compare them as though static void
they were REF_BINDs. */ maybe_handle_implicit_object (ics)
if (ICS_THIS_FLAG (ics1)) tree* ics;
{
if (ICS_THIS_FLAG (*ics))
{ {
tree t = main1; /* [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. */
tree t = *ics;
if (TREE_CODE (t) == PTR_CONV) if (TREE_CODE (t) == PTR_CONV)
t = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 0);
t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE); t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
t = build_conv (REF_BIND, TREE_TYPE (ics1), t); t = build_conv (REF_BIND, TREE_TYPE (*ics), t);
ICS_STD_RANK (t) = ICS_STD_RANK (main1); ICS_STD_RANK (t) = ICS_STD_RANK (*ics);
main1 = ics1 = t; *ics = t;
} }
if (ICS_THIS_FLAG (ics2)) }
/* If ICS is a REF_BIND, modify it appropriately, set ORIG_TO_TYPE
to the type the reference originally referred to, and return 1.
Otherwise, return 0. */
static int
maybe_handle_ref_bind (ics, reference_type)
tree* ics;
tree* reference_type;
{
if (TREE_CODE (*ics) == REF_BIND)
{ {
tree t = main2; /* [over.ics.rank]
if (TREE_CODE (t) == PTR_CONV)
t = TREE_OPERAND (t, 0); When a parameter of reference type binds directly
t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE); (_dcl.init.ref_) to an argument expression, the implicit
t = build_conv (REF_BIND, TREE_TYPE (ics2), t); conversion sequence is the identity conversion, unless the
ICS_STD_RANK (t) = ICS_STD_RANK (main2); argument expression has a type that is a derived class of the
main2 = ics2 = t; 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. */
*reference_type = TREE_TYPE (TREE_TYPE (*ics));
*ics = TREE_OPERAND (*ics, 0);
if (TREE_CODE (*ics) == IDENTITY_CONV
&& is_properly_derived_from (TREE_TYPE (*ics), *reference_type))
*ics = build_conv (BASE_CONV, *reference_type, *ics);
return 1;
} }
return 0;
}
/* Compare two implicit conversion sequences according to the rules set out in
[over.ics.rank]. Return values:
1: ics1 is better than ics2
-1: ics2 is better than ics1
0: ics1 and ics2 are indistinguishable */
static int
compare_ics (ics1, ics2)
tree ics1, ics2;
{
tree from_type1;
tree from_type2;
tree to_type1;
tree to_type2;
tree deref_from_type1 = NULL_TREE;
tree deref_from_type2;
tree deref_to_type1;
tree deref_to_type2;
/* REF_BINDING is non-zero if the result of the conversion sequence
is a reference type. In that case REFERENCE_TYPE is the
reference type. */
int ref_binding1;
int ref_binding2;
tree reference_type1;
tree reference_type2;
/* Handle implicit object parameters. */
maybe_handle_implicit_object (&ics1);
maybe_handle_implicit_object (&ics2);
/* Handle reference parameters. */
ref_binding1 = maybe_handle_ref_bind (&ics1, &reference_type1);
ref_binding2 = maybe_handle_ref_bind (&ics2, &reference_type2);
/* [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)) if (ICS_RANK (ics1) > ICS_RANK (ics2))
return -1; return -1;
else if (ICS_RANK (ics1) < ICS_RANK (ics2)) else if (ICS_RANK (ics1) < ICS_RANK (ics2))
...@@ -3778,6 +3852,8 @@ compare_ics (ics1, ics2) ...@@ -3778,6 +3852,8 @@ compare_ics (ics1, ics2)
if (ICS_RANK (ics1) == BAD_RANK) if (ICS_RANK (ics1) == BAD_RANK)
{ {
/* 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) if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
|| ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2)) || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
return -1; return -1;
...@@ -3785,9 +3861,13 @@ compare_ics (ics1, ics2) ...@@ -3785,9 +3861,13 @@ compare_ics (ics1, ics2)
|| ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2)) || ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
return 1; return 1;
/* else fall through */ /* 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;
/* User-defined conversion sequence U1 is a better conversion sequence /* User-defined conversion sequence U1 is a better conversion sequence
than another user-defined conversion sequence U2 if they contain the than another user-defined conversion sequence U2 if they contain the
same user-defined conversion operator or constructor and if the sec- same user-defined conversion operator or constructor and if the sec-
...@@ -3807,175 +3887,251 @@ compare_ics (ics1, ics2) ...@@ -3807,175 +3887,251 @@ compare_ics (ics1, ics2)
if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
return 0; 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 */ /* We can just fall through here, after setting up
FROM_TYPE1 and FROM_TYPE2. */
from_type1 = TREE_TYPE (t1);
from_type2 = TREE_TYPE (t2);
} }
else
{
/* We're dealing with two standard conversion sequences.
#if 0 /* Handled by ranking */ [over.ics.rank]
/* 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 Standard conversion sequence S1 is a better conversion
conversion. */ sequence than standard conversion sequence S2 if
#endif
--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 */
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 (TREE_CODE (main1) != TREE_CODE (main2)) if (comptypes (from_type1, from_type2, 1))
{ {
/* ...if S1 is a proper subsequence of S2 */ if (is_subseq (ics1, ics2))
if (is_subseq (main1, main2))
return 1; return 1;
if (is_subseq (main2, main1)) if (is_subseq (ics2, ics1))
return -1; return -1;
return 0;
} }
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. */
;
if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV /* [over.ics.rank]
|| 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) Or, if not that,
{
to1 = TYPE_OFFSET_BASETYPE (to1);
from1 = TYPE_OFFSET_BASETYPE (from1);
}
}
if (TYPE_PTRMEMFUNC_P (to2)) --the rank of S1 is better than the rank of S2 (by the rules
{ defined below):
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) Standard conversion sequences are ordered by their ranks: an Exact
{ Match is a better conversion than a Promotion, which is a better
to2 = TYPE_OFFSET_BASETYPE (to2); conversion than a Conversion.
from2 = TYPE_OFFSET_BASETYPE (from2);
}
}
if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2))) Two conversion sequences with the same rank are indistinguishable
return 0; unless one of the following rules applies:
/* The sense of pmem conversions is reversed from that of the other --A conversion that is not a conversion of a pointer, or pointer
conversions. */ to member, to bool is better than another conversion that is such
if (TREE_CODE (main1) == PMEM_CONV) a conversion.
{
tree t = from1; from1 = from2; from2 = t;
t = to1; to1 = to2; to2 = t;
}
distf = get_base_distance (from1, from2, 0, 0); The ICS_STD_RANK automatically handles the pointer-to-bool rule,
if (distf == -1) so that we do not have to check it explicitly. */
{ if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
distf = -get_base_distance (from2, from1, 0, 0); return 1;
if (distf == 1) else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1))
return 0; return -1;
}
to_type1 = TREE_TYPE (ics1);
to_type2 = TREE_TYPE (ics2);
/* If class B is derived directly or indirectly from class A, if (TYPE_PTR_P (from_type1)
conver- sion of B* to A* is better than conversion of B* to && TYPE_PTR_P (from_type2)
void*, and conversion of A* to void* is better than && TYPE_PTR_P (to_type1)
conversion of B* to void*. */ && TYPE_PTR_P (to_type2))
{
deref_from_type1 = TREE_TYPE (from_type1);
deref_from_type2 = TREE_TYPE (from_type2);
deref_to_type1 = TREE_TYPE (to_type1);
deref_to_type2 = TREE_TYPE (to_type2);
}
/* The rules for pointers to members A::* are just like the rules
for pointers A*, except opposite: if B is derived from A then
A::* converts to B::*, not vice versa. For that reason, we
switch the from_ and to_ variables here. */
else if (TYPE_PTRMEM_P (from_type1)
&& TYPE_PTRMEM_P (from_type2)
&& TYPE_PTRMEM_P (to_type1)
&& TYPE_PTRMEM_P (to_type2))
{
deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
}
else if (TYPE_PTRMEMFUNC_P (from_type1)
&& TYPE_PTRMEMFUNC_P (from_type2)
&& TYPE_PTRMEMFUNC_P (to_type1)
&& TYPE_PTRMEMFUNC_P (to_type2))
{
deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
}
if (TREE_CODE (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE) if (deref_from_type1 != NULL_TREE
&& IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1))
&& IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2)))
{
/* This was one of the pointer or pointer-like conversions.
[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 (deref_to_type1) == VOID_TYPE
&& TREE_CODE (deref_to_type2) == VOID_TYPE)
{ {
if (distf > 0) if (is_properly_derived_from (deref_from_type1,
return 1; deref_from_type2))
else if (distf < 0)
return -1; return -1;
else if (is_properly_derived_from (deref_from_type2,
deref_from_type1))
return 1;
} }
else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1) else if (TREE_CODE (deref_to_type1) == VOID_TYPE
&& DERIVED_FROM_P (to1, from1)) || TREE_CODE (deref_to_type2) == VOID_TYPE)
return 1;
else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2)
&& DERIVED_FROM_P (to2, from2))
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 (comptypes (deref_from_type1, deref_from_type2, 1))
if (distt == 1) {
return 0; if (TREE_CODE (deref_to_type2) == VOID_TYPE)
{
if (is_properly_derived_from (deref_from_type1,
deref_to_type1))
return 1;
}
/* We know that DEREF_TO_TYPE1 is `void' here. */
else if (is_properly_derived_from (deref_from_type1,
deref_to_type2))
return -1;
}
} }
else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1))
/* --conversion of C* to B* is better than conversion of C* to A*, */ && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2)))
if (distf == 0)
{ {
if (distt > 0) /* [over.ics.rank]
return -1;
else if (distt < 0) --If class B is derived directly or indirectly from class A
return 1; 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 (deref_from_type1, deref_from_type2, 1))
{
if (is_properly_derived_from (deref_to_type1,
deref_to_type2))
return 1;
else if (is_properly_derived_from (deref_to_type2,
deref_to_type1))
return -1;
}
else if (comptypes (deref_to_type1, deref_to_type2, 1))
{
if (is_properly_derived_from (deref_from_type2,
deref_from_type1))
return 1;
else if (is_properly_derived_from (deref_from_type1,
deref_from_type2))
return -1;
}
} }
/* --conversion of B* to A* is better than conversion of C* to A*, */ }
else if (distt == 0) 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_properly_derived_from (from_type1, to_type1)
&& is_properly_derived_from (from_type1, to_type2))
{ {
if (distf > 0) if (is_properly_derived_from (to_type1, to_type2))
return 1; return 1;
else if (distf < 0) else if (is_properly_derived_from (to_type2, to_type1))
return -1; return -1;
} }
} }
else if (TREE_CODE (TREE_TYPE (main1)) == POINTER_TYPE else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (main1))) && comptypes (to_type1, to_type2, 1))
{ {
if (TREE_TYPE (main1) == TREE_TYPE (main2)) /* [over.ics.rank]
return compare_qual (ics1, ics2);
--binding of an expression of type B to a reference of type
#if 0 /* This is now handled by making identity better than anything else. */ A& is better than binding an expression of type C to a
/* existing practice, not WP-endorsed: const char * -> const char * reference of type A&,
is better than char * -> const char *. (jason 6/29/96) */
if (TREE_TYPE (ics1) == TREE_TYPE (ics2)) --onversion of B to A is better than conversion of C to A */
return -compare_qual (main1, main2); if (is_properly_derived_from (from_type1, to_type1)
#endif && is_properly_derived_from (from_type2, to_type1))
{
if (is_properly_derived_from (from_type2, from_type1))
return 1;
else if (is_properly_derived_from (from_type1, from_type2))
return -1;
}
} }
/* [over.ics.rank]
--S1 and S2 differ only in their qualification conversion and yield
similar types T1 and T2 (_conv.qual_), respectively, and the cv-
qualification signature of type T1 is a proper subset of the cv-
qualification signature of type T2 */
if (TREE_CODE (ics1) == QUAL_CONV
&& TREE_CODE (ics2) == QUAL_CONV
&& comptypes (from_type1, from_type2, 1))
return comp_cv_qual_signature (to_type1, to_type2);
/* [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_binding1 && ref_binding2
&& comptypes (TYPE_MAIN_VARIANT (to_type1),
TYPE_MAIN_VARIANT (to_type2), 1))
return comp_cv_qualification (reference_type2, reference_type1);
/* Neither conversion sequence is better than the other. */
return 0; return 0;
} }
......
...@@ -1362,6 +1362,11 @@ extern int flag_new_for_scope; ...@@ -1362,6 +1362,11 @@ extern int flag_new_for_scope;
pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true, pointer to member function. TYPE_PTRMEMFUNC_P _must_ be true,
before using this macro. */ before using this macro. */
#define TYPE_PTRMEMFUNC_FN_TYPE(NODE) (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE))))))) #define TYPE_PTRMEMFUNC_FN_TYPE(NODE) (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (NODE)))))))
/* Returns `A' for a type like `int (A::*)(double)' */
#define TYPE_PTRMEMFUNC_OBJECT_TYPE(NODE) \
TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (NODE)))
/* These are use to manipulate the canonical RECORD_TYPE from the /* These are use to manipulate the canonical RECORD_TYPE from the
hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */ hashed POINTER_TYPE, and can only be used on the POINTER_TYPE. */
#define TYPE_GET_PTRMEMFUNC_TYPE(NODE) ((tree)TYPE_LANG_SPECIFIC(NODE)) #define TYPE_GET_PTRMEMFUNC_TYPE(NODE) ((tree)TYPE_LANG_SPECIFIC(NODE))
...@@ -2770,6 +2775,8 @@ extern int comptypes PROTO((tree, tree, int)); ...@@ -2770,6 +2775,8 @@ extern int comptypes PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int)); extern int comp_target_types PROTO((tree, tree, int));
extern int compparms PROTO((tree, tree, int)); extern int compparms PROTO((tree, tree, int));
extern int comp_target_types PROTO((tree, tree, int)); extern int comp_target_types PROTO((tree, tree, int));
extern int comp_cv_qualification PROTO((tree, tree));
extern int comp_cv_qual_signature PROTO((tree, tree));
extern int self_promoting_args_p PROTO((tree)); extern int self_promoting_args_p PROTO((tree));
extern tree unsigned_type PROTO((tree)); extern tree unsigned_type PROTO((tree));
extern tree signed_type PROTO((tree)); extern tree signed_type PROTO((tree));
......
...@@ -1048,6 +1048,46 @@ comp_target_types (ttl, ttr, nptrs) ...@@ -1048,6 +1048,46 @@ comp_target_types (ttl, ttr, nptrs)
return 0; 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;
}
/* Returns 1 if the cv-qualification signature of TYPE1 is a proper
subset of the cv-qualification signature of TYPE2, and the types
are similar. Returns -1 if the other way 'round, and 0 otherwise. */
int
comp_cv_qual_signature (type1, type2)
tree type1;
tree type2;
{
if (comp_ptr_ttypes_real (type2, type1, -1))
return 1;
else if (comp_ptr_ttypes_real (type1, type2, -1))
return -1;
else
return 0;
}
/* If two types share a common base type, return that basetype. /* If two types share a common base type, return that basetype.
If there is not a unique most-derived base type, this function If there is not a unique most-derived base type, this function
returns ERROR_MARK_NODE. */ returns ERROR_MARK_NODE. */
...@@ -7409,14 +7449,21 @@ c_expand_start_case (exp) ...@@ -7409,14 +7449,21 @@ c_expand_start_case (exp)
return exp; return exp;
} }
/* CONSTP remembers whether or not all the intervening pointers in the `to' /* Returns non-zero if the pointer-type FROM can be converted to the
type have been const. */ pointer-type TO via a qualification conversion. If CONSTP is -1,
then we return non-zero if the pointers are similar, and the
cv-qualification signature of FROM is a proper subset of that of TO.
If CONSTP is positive, then all outer pointers have been
const-qualified. */
static int static int
comp_ptr_ttypes_real (to, from, constp) comp_ptr_ttypes_real (to, from, constp)
tree to, from; tree to, from;
int constp; int constp;
{ {
int to_more_cv_qualified = 0;
for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
{ {
if (TREE_CODE (to) != TREE_CODE (from)) if (TREE_CODE (to) != TREE_CODE (from))
...@@ -7431,19 +7478,32 @@ comp_ptr_ttypes_real (to, from, constp) ...@@ -7431,19 +7478,32 @@ comp_ptr_ttypes_real (to, from, constp)
so the usual checks are not appropriate. */ so the usual checks are not appropriate. */
if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{ {
if (TYPE_READONLY (from) > TYPE_READONLY (to) switch (comp_cv_qualification (from, to))
|| TYPE_VOLATILE (from) > TYPE_VOLATILE (to)) {
return 0; case 1:
/* FROM is more cv-qualified than TO. */
return 0;
if (! constp case -1:
&& (TYPE_READONLY (to) > TYPE_READONLY (from) /* TO is more cv-qualified than FROM. */
|| TYPE_VOLATILE (to) > TYPE_READONLY (from))) if (constp == 0)
return 0; return 0;
constp &= TYPE_READONLY (to); else
++to_more_cv_qualified;
break;
default:
break;
}
if (constp > 0)
constp &= TYPE_READONLY (to);
} }
if (TREE_CODE (to) != POINTER_TYPE) if (TREE_CODE (to) != POINTER_TYPE)
return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1); return
comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1)
&& (constp >= 0 || to_more_cv_qualified);
} }
} }
......
// Build don't run:
void f(const int *);
void f(int *) {}
void f2(const volatile int *);
void f2(volatile int *) {}
int i;
int main()
{
f(&i);
f2(&i);
}
// Build don't run:
void f(int* const volatile * const * const*);
void f(int* const * const * const*) {}
int main()
{
int*** ip;
f(&ip);
}
// Build don't run:
struct S {};
struct T : public S {};
struct U : public T {};
void f(int T::*) {}
void f(int U::*);
void g(void (T::*)(int)) {}
void g(void (U::*)(int));
int main()
{
int S::*ip;
void (S::*fp)(int);
f(ip);
g(fp);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment