86th Cygnus<->FSF quick merge

From-SVN: r12177
This commit is contained in:
Mike Stump 1996-06-06 19:10:27 +00:00
parent bb91b814bd
commit a0128b67f4
11 changed files with 292 additions and 95 deletions

View File

@ -3,6 +3,36 @@ Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com>
* decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
(finish_file): Likewise.
Tue Jun 4 15:41:45 1996 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (tsubst_expr, case DECL_STMT): Don't pass
LOOKUP_ONLYCONVERTING at all for now.
* search.c (add_conversions): Put the conversion function in
TREE_VALUE, the basetype in TREE_PURPOSE.
* cvt.c (build_type_conversion): Adjust.
* cvt.c (build_expr_type_conversion): Adjust.
* call.c (user_harshness): Adjust.
Mon Jun 3 15:30:52 1996 Jason Merrill <jason@yorick.cygnus.com>
* method.c (emit_thunk): Pretend this is a FUNCTION_DECL for the
backend's benefit.
Fri May 31 14:56:13 1996 Mike Stump <mrs@cygnus.com>
* cp-tree.h (OFFSET_REF): Remove.
* tree.def (CP_OFFSET_REF): Rename to OFFSET_REF.
* expr.c (cplus_expand_expr): Cleanup callers of expand_expr.
* init.c (expand_aggr_init_1): Ditto.
(build_new): Ditto.
* typeck.c (expand_target_expr): Ditto.
Fri May 31 14:22:08 1996 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (build_modify_expr): Don't use TREE_VALUE on a
TARGET_EXPR.
Wed May 29 17:04:33 1996 Mike Stump <mrs@cygnus.com>
* cvt.c (build_up_reference): Redo how and when temporaries are

View File

@ -640,18 +640,19 @@ user_harshness (type, parmtype)
for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv))
{
struct harshness_code tmp;
tree cand = TREE_VALUE (conv);
if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
if (winner && winner == cand)
continue;
if (tmp = convert_harshness (type, TREE_PURPOSE (conv), NULL_TREE),
(tmp.code < USER_CODE) && (tmp.distance >= 0))
tmp = convert_harshness (type, TREE_TYPE (TREE_TYPE (cand)), NULL_TREE);
if ((tmp.code < USER_CODE) && (tmp.distance >= 0))
{
if (winner)
return EVIL_CODE;
else
{
winner = conv;
winner = cand;
code = tmp.code;
}
}

View File

@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */
Operand 0 is the object within which the offset is taken.
Operand 1 is the offset. The language independent OFFSET_REF
just won't work for us. */
DEFTREECODE (CP_OFFSET_REF, "cp_offset_ref", "r", 2)
DEFTREECODE (OFFSET_REF, "offset_ref", "r", 2)
/* For DELETE_EXPR, operand 0 is the store to be destroyed.
Operand 1 is the value to pass to the destroying function
@ -50,7 +50,7 @@ DEFTREECODE (MEMBER_REF, "member_ref", "r", 2)
operator converts to. Operand is expression to be converted. */
DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
/* For CPLUS_NEW_EXPR, operand 0 is function which performs initialization,
/* For NEW_EXPR, operand 0 is function which performs initialization,
operand 1 is argument list to initialization function,
and operand 2 is the slot which was allocated for this expression. */
DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)

View File

@ -318,10 +318,6 @@ enum cplus_tree_code {
};
#undef DEFTREECODE
/* Override OFFSET_REFs from the back-end, as we want our very own. */
/* Allow complex pointer to members to work correctly. */
#define OFFSET_REF CP_OFFSET_REF
enum languages { lang_c, lang_cplusplus };
/* Macros to make error reporting functions' lives easier. */

View File

@ -1509,10 +1509,12 @@ build_type_conversion (code, xtype, expr, for_sure)
/* Nope; try looking for others. */
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
tree cand = TREE_VALUE (conv);
if (winner && winner == cand)
continue;
if (can_convert (xtype, TREE_PURPOSE (conv)))
if (can_convert (xtype, TREE_TYPE (TREE_TYPE (cand))))
{
if (winner)
{
@ -1520,19 +1522,19 @@ build_type_conversion (code, xtype, expr, for_sure)
{
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype);
cp_error (" candidate conversions include `%T' and `%T'",
TREE_PURPOSE (winner), TREE_PURPOSE (conv));
cp_error (" candidate conversions include `%D' and `%D'",
winner, cand);
}
return NULL_TREE;
}
else
winner = conv;
winner = cand;
}
}
if (winner)
return build_type_conversion_1 (xtype, basetype, expr,
DECL_NAME (TREE_VALUE (winner)), for_sure);
DECL_NAME (winner), for_sure);
return NULL_TREE;
}
@ -1590,11 +1592,12 @@ build_expr_type_conversion (desires, expr, complain)
{
int win = 0;
tree candidate;
tree cand = TREE_VALUE (conv);
if (winner && TREE_VALUE (winner) == TREE_VALUE (conv))
if (winner && winner == cand)
continue;
candidate = TREE_PURPOSE (conv);
candidate = TREE_TYPE (TREE_TYPE (cand));
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
@ -1619,23 +1622,23 @@ build_expr_type_conversion (desires, expr, complain)
{
cp_error ("ambiguous default type conversion from `%T'",
basetype);
cp_error (" candidate conversions include `%T' and `%T'",
TREE_PURPOSE (winner), TREE_PURPOSE (conv));
cp_error (" candidate conversions include `%D' and `%D'",
winner, cand);
}
return error_mark_node;
}
else
winner = conv;
winner = cand;
}
}
if (winner)
{
tree type = TREE_PURPOSE (winner);
tree type = TREE_TYPE (TREE_TYPE (winner));
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
return build_type_conversion_1 (type, basetype, expr,
DECL_NAME (TREE_VALUE (winner)), 1);
DECL_NAME (winner), 1);
}
return NULL_TREE;
@ -1839,11 +1842,6 @@ build_conv (code, type, from)
int rank = ICS_STD_RANK (from);
switch (code)
{
case PROMO_CONV:
if (rank < PROMO_RANK)
rank = PROMO_RANK;
break;
case PTR_CONV:
case PMEM_CONV:
case BASE_CONV:
@ -1852,16 +1850,10 @@ build_conv (code, type, from)
rank = STD_RANK;
break;
case PBOOL_CONV:
if (rank < PBOOL_RANK)
rank = PBOOL_RANK;
break;
default:
break;
}
ICS_STD_RANK (t) = rank;
ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
return t;
}
@ -1877,8 +1869,6 @@ standard_conversion (to, from, expr)
return from;
conv = build1 (EXACT_CONV, from, expr);
if (TREE_CODE (expr) == USER_CONV)
ICS_USER_FLAG (conv) = 1;
if (fcode == FUNCTION_TYPE)
{
@ -1979,25 +1969,25 @@ standard_conversion (to, from, expr)
|| fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)))
return 0;
if (fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))
conv = build_conv (PBOOL_CONV, to, conv);
else
conv = build_conv (STD_CONV, to, conv);
conv = build_conv (STD_CONV, to, conv);
if (fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from)
&& ICS_STD_RANK (conv) < PBOOL_RANK)
ICS_STD_RANK (conv) = PBOOL_RANK;
}
else if (INTEGRAL_CODE_P (tcode) || tcode == REAL_TYPE)
{
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
return 0;
else if (to == type_promotes_to (from))
conv = build_conv (PROMO_CONV, to, conv);
else
conv = build_conv (STD_CONV, to, conv);
conv = build_conv (STD_CONV, to, conv);
/* Give this a better rank if it's a promotion. */
if (to == type_promotes_to (from)
&& ICS_STD_RANK (TREE_OPERAND (conv, 0)) <= PROMO_RANK)
ICS_STD_RANK (conv) = PROMO_RANK;
}
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from))
{
conv = build_conv (BASE_CONV, to, conv);
}
conv = build_conv (BASE_CONV, to, conv);
else
return 0;
@ -2021,25 +2011,70 @@ implicit_conversion (to, from, expr, flags)
if (! cand)
return NULL_TREE;
conv = cand->second_conv;
for (t = conv; TREE_CODE (TREE_OPERAND (t, 0)) != EXACT_MATCH; )
t = TREE_OPERAND (t, 0));
TREE_OPERAND (t, 0) = build (USER_CONV
return conv;
return cand->second_conv;
}
struct z_candidate *
add_method_candidate (candidates, method, instance, parms, flags)
add_function_candidate (candidates, fn, arglist, flags)
struct z_candidate *candidates;
tree method, instance, parms;
tree fn, args;
int flags;
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len = list_length (args);
tree convs = make_tree_vec (len);
tree parmnode = parmlist;
tree argnode = arglist;
int viable = 1;
struct z_candidate *cand;
for (i = 0; i < len; ++i)
{
tree arg = TREE_VALUE (argnode);
tree argtype = TREE_TYPE (arg);
tree t;
if (parmnode == void_list_node)
break;
else if (parmnode)
t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
else
{
t = build1 (EXACT_CONV, argtype, arg);
ICS_ELLIPSIS_FLAG (t) = 1;
}
TREE_VEC_ELT (convs, i) = t;
if (! t)
{
viable = 0;
break;
}
if (parm)
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
}
if (parmnode && parmnode != void_list_node)
viable = 0;
cand = (struct z_candidate *) oballoc (sizeof (struct z_candidate));
cand->fn = fn;
cand->convs = convs;
cand->second_conv = NULL_TREE;
cand->viable = viable;
cand->template = NULL_TREE;
cand->basetype_path = NULL_TREE;
cand->next = candidates;
return cand;
}
/* Returns the best overload candidate to perform the requested
conversion. */
struct z_candidate *
build_user_type_conversion_1 (totype, expr, flags)
tree totype, expr;
@ -2048,6 +2083,7 @@ build_user_type_conversion_1 (totype, expr, flags)
struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, t;
tree method_args;
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
@ -2059,24 +2095,35 @@ build_user_type_conversion_1 (totype, expr, flags)
for (; ctors; ctors = DECL_CHAIN (ctors))
{
candidates = add_ctor_candidate (candidates, ctors, expr, flags);
candidates->basetype_path = TYPE_BINFO (totype);
}
method_args = build_tree_list
(NULL_TREE, build_unary_op (ADDR_EXPR, expr, 0));
for (; convs; convs = TREE_CHAIN (convs))
{
tree fn = TREE_VALUE (convs);
tree ics = standard_conversion (totype, TREE_TYPE (TREE_TYPE (fn)), 0);
if (ics)
{
candidates = add_method_candidate
(candidates, fn, expr, NULL_TREE, flags);
candidates = add_function_candidate
(candidates, fn, method_args, flags);
candidates->second_ics = ics;
candidates->basetype_path = TREE_PURPOSE (convs);
}
}
if (! any_viable (candidates))
{
if (flags & LOOKUP_COMPLAIN)
cp_error ("no viable candidates");
{
if (candidates && ! candidates->next)
/* say why this one won't work or try to be loose */;
else
cp_error ("no viable candidates");
}
return 0;
}
@ -2089,9 +2136,110 @@ build_user_type_conversion_1 (totype, expr, flags)
cp_error ("ambiguous user-defined type conversion");
}
for (t = cand->second_conv; TREE_CODE (TREE_OPERAND (t, 0)) != EXACT_MATCH; )
t = TREE_OPERAND (t, 0);
TREE_OPERAND (t, 0) = build
(USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
NULL_TREE, cand->fn, cand->convs, cand->basetype_path);
ICS_USER_FLAG (cand->second_conv) = 1;
return cand;
}
tree
build_user_type_conversion (totype, expr, flags)
tree totype, expr, flags;
{
struct z_candidate *cand
= build_user_type_conversion_1 (totype, expr, flags);
return convert_like (cand->second_conv, expr);
}
void
enforce_access (basetype_path, function)
tree basetype_path, function;
{
tree access = compute_access (basetype_path, function);
if (access == access_private_node)
{
cp_error_at ("%s `%+#D' is %s", name_kind, function,
TREE_PRIVATE (function) ? "private"
: "from private base class");
error ("within this context");
}
else if (access == access_protected_node)
{
cp_error_at ("%s `%+#D' %s", name_kind, function,
TREE_PROTECTED (function) ? "is protected"
: "has protected accessibility");
error ("within this context");
}
}
tree
convert_like (convs, expr)
tree convs, expr;
{
tree previous;
if (TREE_CODE (convs) == USER_CONV)
{
tree fn = TREE_OPERAND (convs, 1);
enforce_access (TREE_OPERAND (convs, 3), fn);
return build_over_call (TREE_OPERAND (convs, 1),
TREE_OPERAND (convs, 2), expr, LOOKUP_NORMAL);
}
else if (TREE_CODE (convs) == EXACT_CONV)
return expr;
previous = convert_like (TREE_OPERAND (convs, 0), expr);
return convert (TREE_TYPE (convs), expr);
}
tree
build_over_call (fn, convs, args, flags)
tree fn, convs, args;
int flags;
{
tree converted_args;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
tree conv = convs;
tree arg = args;
if (TREE_CODE (arg) != TREE_LIST)
arg = build_tree_list (NULL_TREE, arg);
for (; arg;
parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg),
conv = TREE_CHAIN (conv))
converted_args = tree_cons
(NULL_TREE, convert_like (TREE_VALUE (conv), TREE_VALUE (arg)),
converted_args);
for (; parm; parm = TREE_CHAIN (parm))
converted_args = tree_cons
(NULL_TREE,
convert_for_ellipsis (TREE_VALUE (parm), TREE_PURPOSE (parm)),
converted_args);
converted_args = nreverse (converted_args);
return build_x_call (fn, converted_args, flags);
}
tree
build_x_call (fn, args, flags)
tree fn, args;
int flags;
{
if (DECL_FUNCTION_MEMBER_P (fn))
{
}
}
/* Compare two implicit conversion sequences according to the rules set out in
[over.ics.rank]. Return values:
@ -2139,29 +2287,6 @@ compare_ics (ics1, ics2)
/* 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. */
{
int bool1 = TREE_CODE (ics1) == BOOL_CONV;
int bool2 = TREE_CODE (ics2) == BOOL_CONV;
if (bool1)
{
tree it = TREE_TYPE (TREE_OPERAND (ics1, 0));
if (TREE_CODE (it) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_TYPE (it))
bool1 = 0;
}
if (bool2)
{
tree it = TREE_TYPE (TREE_OPERAND (ics2, 0));
if (TREE_CODE (it) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_TYPE (it))
bool2 = 0;
}
if (bool1 && ! bool2)
return 1;
if (bool2 && ! bool1)
return -1;
}
#endif
if (TREE_CODE (ics1) == QUAL_CONV)
@ -2306,12 +2431,27 @@ compare_ics (ics1, ics2)
return 0;
}
/* Compare two candidates for overloading as described in
[over.match.best]. Return values:
1: cand1 is better than cand2
-1: cand2 is better than cand1
0: cand1 and cand2 are indistinguishable */
int joust (cand1, cand2)
struct z_candidate *cand1, *cand2;
{
int winner = 0;
int i;
/* a viable function F1
is defined to be a better function than another viable function F2 if
for all arguments i, ICSi(F1) is not a worse conversion sequence than
ICSi(F2), and then */
/* for some argument j, ICSj(F1) is a better conversion sequence than
ICSj(F2) */
for (i = 0; i < TREE_VEC_LENGTH (cand1->convs); ++i)
{
int comp = compare_ics (TREE_VEC_ELT (cand1->convs, i),
@ -2325,12 +2465,36 @@ int joust (cand1, cand2)
}
}
if (winner == 0 && cand1->second_ics)
if (winner)
return winner;
/* or, if not that,
F1 is a non-template function and F2 is a template function */
if (! cand1->template && cand2->template)
return 1;
else if (cand1->template && ! cand2->template)
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
sequence from the return type of F1 to the destination type (i.e.,
the type of the entity being initialized) is a better conversion
sequence than the standard conversion sequence from the return type
of F2 to the destination type. */
if (cand1->second_ics)
winner = compare_ics (cand1->second_ics, cand2->second_ics);
return winner;
}
/* Given a list of candidates for overloading, find the best one, if any.
This algorithm has a worst case of O(2n) (winner is last), and a best
case of O(n/2) (totally ambiguous); much better than a sorting
algorithm. */
struct z_candidate *
tourney (candidates)
struct z_candidate *candidates;
@ -2338,8 +2502,8 @@ tourney (candidates)
struct z_candidate *champ = candidates, *challenger;
int fate;
/* This algorithm has a worst case of O(2n) (winner is last) , and a best
case of O(n/2) (no winner); much better than a sorting algorithm. */
/* Walk through the list once, comparing each current champ to the next
candidate, knocking out a candidate or two with each comparison. */
for (challenger = champ->next; challenger; )
{
@ -2361,6 +2525,10 @@ tourney (candidates)
}
}
/* Make sure the champ is better than all the candidates it hasn't yet
been compared to. This may do one more comparison than necessary. Oh
well. */
for (challenger = candidates; challenger != champ;
challenger = challenger->next)
{

View File

@ -165,7 +165,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = maybe_build_cleanup (convert_from_reference (init));
if (init != NULL_TREE)
expand_expr (init, 0, 0, 0);
expand_expr (init, const0_rtx, VOIDmode, 0);
}
call_target = return_target = DECL_RTL (slot);
}

View File

@ -1403,7 +1403,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
/* Unify the initialization targets. */
DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
else
DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, 0, 0);
DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, VOIDmode, 0);
expand_expr_stmt (init);
return;
@ -2965,7 +2965,7 @@ build_new (placement, decl, init, use_global_new)
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
rtxval = expand_expr (alloc_expr, NULL, VOIDmode, 0);
rtxval = expand_expr (alloc_expr, NULL_RTX, VOIDmode, 0);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();

View File

@ -1750,6 +1750,8 @@ emit_thunk (thunk_fndecl)
if (current_function_decl)
abort ();
current_function_decl = thunk_fndecl;
TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
#ifdef ASM_OUTPUT_MI_THUNK
temporary_allocation ();
assemble_start_function (thunk_fndecl, fnname);
@ -1937,6 +1939,7 @@ emit_thunk (thunk_fndecl)
permanent_allocation (1);
flag_omit_frame_pointer = save_ofp;
#endif /* ASM_OUTPUT_MI_THUNK */
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
decl_printable_name = save_decl_printable_name;
current_function_decl = 0;

View File

@ -2093,7 +2093,7 @@ tsubst_expr (t, args, nargs, in_decl)
tsubst (TREE_OPERAND (t, 2), args, nargs, in_decl));
init = tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl);
cp_finish_decl
(dcl, init, NULL_TREE, 1, init ? LOOKUP_ONLYCONVERTING : 0);
(dcl, init, NULL_TREE, 1, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
resume_momentary (i);
return dcl;
}

View File

@ -3508,8 +3508,7 @@ add_conversions (binfo)
tree tmp = TREE_VEC_ELT (method_vec, i);
if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)))
break;
conversions = tree_cons (TREE_TYPE (TREE_TYPE (tmp)), tmp,
conversions);
conversions = tree_cons (binfo, tmp, conversions);
}
}

View File

@ -5370,7 +5370,7 @@ expand_target_expr (t)
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
rtxval = expand_expr (t, NULL, VOIDmode, 0);
rtxval = expand_expr (t, NULL_RTX, VOIDmode, 0);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();
@ -5803,7 +5803,7 @@ build_modify_expr (lhs, modifycode, rhs)
expanded without a target. */
if (TREE_CODE (newrhs) == TARGET_EXPR)
newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
TREE_VALUE (newrhs));
TREE_OPERAND (newrhs, 0));
}
if (TREE_CODE (newrhs) == ERROR_MARK)