call.c (build_conv): Typo in comment.

cp:
	* call.c (build_conv): Typo in comment.
	(add_builtin_candidate): Add more explanation.
	Remove extra test for ENUMERAL_TYPE in {PRE,POST}INCREMENT_EXPR.
	Allow ENUMERAL_TYPEs for relops and eqops. Add both candidates
	when we have enumeral types.
	(add_builtin_candidates): Add more explanation. Add ENUMERAL_TYPE
	candidates for relops and eqops.
	(joust): Simplify control flow. Allow a non-template user
	function to hide a builtin.
testsuite:
	* g++.old-deja/g++.pt/overload14.C: New test.

From-SVN: r39197
This commit is contained in:
Nathan Sidwell 2001-01-23 10:36:26 +00:00 committed by Nathan Sidwell
parent 20b11783a3
commit 4cff6abe40
4 changed files with 109 additions and 30 deletions

View File

@ -1,3 +1,15 @@
2001-01-23 Nathan Sidwell <nathan@codesourcery.com>
* call.c (build_conv): Typo in comment.
(add_builtin_candidate): Add more explanation.
Remove extra test for ENUMERAL_TYPE in {PRE,POST}INCREMENT_EXPR.
Allow ENUMERAL_TYPEs for relops and eqops. Add both candidates
when we have enumeral types.
(add_builtin_candidates): Add more explanation. Add ENUMERAL_TYPE
candidates for relops and eqops.
(joust): Simplify control flow. Allow a non-template user
function to hide a builtin.
2001-01-22 Nathan Sidwell <nathan@codesourcery.com>
* cp-tree.h (unification_kind_t): Add DEDUCE_ORDER.

View File

@ -608,7 +608,7 @@ build_conv (code, type, from)
tree t;
int rank = ICS_STD_RANK (from);
/* We can't use buidl1 here because CODE could be USER_CONV, which
/* We can't use buildl1 here because CODE could be USER_CONV, which
takes two arguments. In that case, the caller is responsible for
filling in the second argument. */
t = make_node (code);
@ -1563,7 +1563,12 @@ promoted_arithmetic_type_p (type)
/* Create any builtin operator overload candidates for the operator in
question given the converted operand types TYPE1 and TYPE2. The other
args are passed through from add_builtin_candidates to
build_builtin_candidate. */
build_builtin_candidate.
TYPE1 and TYPE2 may not be permissible, and we must filter them.
If CODE is requires candidates operands of the same type of the kind
of which TYPE1 and TYPE2 are, we add both candidates
CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */
static struct z_candidate *
add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
@ -1611,8 +1616,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
return candidates;
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE)
|| TYPE_PTROB_P (type1))
if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
{
type1 = build_reference_type (type1);
break;
@ -1712,8 +1716,8 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
candidate operator functions of the form112)
ptrdiff_t operator-(T, T);
16For every pointer type T, there exist candidate operator functions of
the form
16For every enumeral or pointer type T, there exist candidate operator
functions of the form
bool operator<(T, T);
bool operator>(T, T);
bool operator<=(T, T);
@ -1757,15 +1761,19 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
type1 = type2;
break;
}
/* FALLTHROUGH */
case LT_EXPR:
case GT_EXPR:
case LE_EXPR:
case GE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
if ((ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
|| (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)))
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
if (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
break;
if (TREE_CODE (type1) == ENUMERAL_TYPE && TREE_CODE (type2) == ENUMERAL_TYPE)
break;
if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1]))
{
type2 = type1;
@ -1940,15 +1948,16 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
my_friendly_abort (367);
}
/* If we're dealing with two pointer types, we need candidates
for both of them. */
/* If we're dealing with two pointer types or two enumeral types,
we need candidates for both of them. */
if (type2 && !same_type_p (type1, type2)
&& TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE
|| (TREE_CODE (type1) == POINTER_TYPE
&& TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
|| TYPE_PTRMEMFUNC_P (type1)
|| IS_AGGR_TYPE (type1)))
|| IS_AGGR_TYPE (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
candidates = build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
@ -1977,7 +1986,12 @@ type_decays_to (type)
2) pointer-pair taking candidates. These are generated for each type
one of the input types converts to.
3) arithmetic candidates. According to the standard, we should generate
all of these, but I'm trying not to... */
all of these, but I'm trying not to...
Here we generate a superset of the possible candidates for this particular
case. That is a subset of the full set the standard defines, plus some
other cases which the standard disallows. add_builtin_candidate will
filter out the illegal set. */
static struct z_candidate *
add_builtin_candidates (candidates, code, code2, fnname, args, flags)
@ -1987,6 +2001,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
int flags;
{
int ref1, i;
int enum_p = 0;
tree type, argtypes[3];
/* TYPES[i] is the set of possible builtin-operator parameter types
we will consider for the Ith argument. These are represented as
@ -2038,6 +2053,16 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
case COMPONENT_REF:
return candidates;
case COND_EXPR:
case EQ_EXPR:
case NE_EXPR:
case LT_EXPR:
case LE_EXPR:
case GT_EXPR:
case GE_EXPR:
enum_p = 1;
/* FALLTHROUGH */
default:
ref1 = 0;
}
@ -2086,8 +2111,8 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
if (INTEGRAL_TYPE_P (type))
type = type_promotes_to (type);
}
@ -2105,8 +2130,8 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
if (INTEGRAL_TYPE_P (type))
type = type_promotes_to (type);
}
@ -5186,21 +5211,34 @@ joust (cand1, cand2, warn)
if (winner)
return winner;
/* or, if not that,
F1 is a non-template function and F2 is a template function */
/* or, if not that, a non-template function is better than a
template function. */
if (! cand1->template && cand2->template)
return 1;
else if (cand1->template && ! cand2->template)
return -1;
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));
{
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));
if (winner)
return winner;
}
/* or, if not that, a non-template user function is better than a
builtin. */
if (TREE_CODE (cand1->fn) != IDENTIFIER_NODE
&& TREE_CODE (cand2->fn) == IDENTIFIER_NODE)
return 1;
else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE
&& TREE_CODE (cand2->fn) != IDENTIFIER_NODE)
return -1;
/* or, if not that,
the context is an initialization by user-defined conversion (see
_dcl.init_ and _over.match.user_) and the standard conversion
@ -5209,11 +5247,15 @@ joust (cand1, cand2, warn)
sequence than the standard conversion sequence from the return type
of F2 to the destination type. */
if (! winner && cand1->second_conv)
winner = compare_ics (cand1->second_conv, cand2->second_conv);
if (cand1->second_conv)
{
winner = compare_ics (cand1->second_conv, cand2->second_conv);
if (winner)
return winner;
}
/* If the built-in candidates are the same, arbitrarily pick one. */
if (! winner && cand1->fn == cand2->fn
if (cand1->fn == cand2->fn
&& TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
{
for (i = 0; i < len; ++i)
@ -5253,7 +5295,7 @@ tweak:
/* Extension: If the worst conversion for one candidate is worse than the
worst conversion for the other, take the first. */
if (! winner && ! pedantic)
if (!pedantic)
{
int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;
@ -5271,7 +5313,8 @@ tweak:
return -1;
}
return winner;
my_friendly_assert (!winner, 20010121);
return 0;
}
/* Given a list of candidates for overloading, find the best one, if any.

View File

@ -1,3 +1,7 @@
2001-01-23 Nathan Sidwell <nathan@codesourcery.com>
* g++.old-deja/g++.pt/overload14.C: New test.
2001-01-22 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* gcc.c-torture/execute/20010122-1.c: New test, exercise

View File

@ -0,0 +1,20 @@
// Build don't link:
//
// Copyright (C) 2000 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 18 Jan 2001 <nathan@codesourcery.com>
// Bug 1639. We failed to have builtin relop candidates with enumeral type.
template <typename T1, typename T2> void operator == (T1, T2);
enum E {e1};
void operator != (E, E);
bool Foo (E e)
{
return e == e1;
}
bool Baz (E e)
{
return e != e1; // ERROR - void not ignored.
}