cp-tree.def: Add WRAPPER.
* cp-tree.def: Add WRAPPER. USER_CONV now only has two ops. * cp-tree.h: Add WRAPPER support. * call.c (add_candidate): Split out from add_*_candidate fns. (build_over_call): Take the candidate instead of function and args. Enforce access control here. Emit overload warnings here. (add_warning): New fn. (joust): Add WARN parm. If not set, call add_warning instead of printing a warning. Reenable some warnings. (tourney): Pass it. (convert_like): Adjust. (build_new_op): Adjust. (build_new_function_call): Adjust. (build_user_type_conversion_1): Adjust. (USER_CONV_FN): Adjust. * tree.c (build_expr_wrapper, build_expr_ptr_wrapper, build_int_wrapper): New fns. From-SVN: r19393
This commit is contained in:
parent
624411284f
commit
5ffe581dd3
|
@ -1,3 +1,22 @@
|
|||
Thu Apr 23 21:19:06 1998 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* cp-tree.def: Add WRAPPER. USER_CONV now only has two ops.
|
||||
* cp-tree.h: Add WRAPPER support.
|
||||
* call.c (add_candidate): Split out from add_*_candidate fns.
|
||||
(build_over_call): Take the candidate instead of function and args.
|
||||
Enforce access control here. Emit overload warnings here.
|
||||
(add_warning): New fn.
|
||||
(joust): Add WARN parm. If not set, call add_warning instead of
|
||||
printing a warning. Reenable some warnings.
|
||||
(tourney): Pass it.
|
||||
(convert_like): Adjust.
|
||||
(build_new_op): Adjust.
|
||||
(build_new_function_call): Adjust.
|
||||
(build_user_type_conversion_1): Adjust.
|
||||
(USER_CONV_FN): Adjust.
|
||||
* tree.c (build_expr_wrapper, build_expr_ptr_wrapper,
|
||||
build_int_wrapper): New fns.
|
||||
|
||||
Thu Apr 23 18:27:53 1998 Mark P. Mitchell <mmitchell@usa.net>
|
||||
|
||||
* pt.c (unify): Fix typo in previous change.
|
||||
|
|
166
gcc/cp/call.c
166
gcc/cp/call.c
|
@ -43,10 +43,10 @@ static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
|
|||
static tree build_field_call PROTO((tree, tree, tree, tree));
|
||||
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 *));
|
||||
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((tree, tree, tree, int));
|
||||
static tree build_over_call PROTO((struct z_candidate *, tree, int));
|
||||
static tree convert_default_arg PROTO((tree, tree));
|
||||
static tree convert_like PROTO((tree, tree));
|
||||
static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
|
||||
|
@ -664,6 +664,7 @@ struct z_candidate {
|
|||
int viable;
|
||||
tree basetype_path;
|
||||
tree template;
|
||||
tree warnings;
|
||||
struct z_candidate *next;
|
||||
};
|
||||
|
||||
|
@ -689,7 +690,9 @@ struct z_candidate {
|
|||
#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
|
||||
#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
|
||||
|
||||
#define USER_CONV_FN(NODE) TREE_OPERAND (NODE, 1)
|
||||
#define USER_CONV_CAND(NODE) \
|
||||
((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
|
||||
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
|
||||
|
||||
int
|
||||
null_ptr_cst_p (t)
|
||||
|
@ -1049,6 +1052,30 @@ implicit_conversion (to, from, expr, flags)
|
|||
return conv;
|
||||
}
|
||||
|
||||
/* Add a new entry to the list of candidates. Used by the add_*_candidate
|
||||
functions. */
|
||||
|
||||
static struct z_candidate *
|
||||
add_candidate (candidates, fn, convs, viable)
|
||||
struct z_candidate *candidates;
|
||||
tree fn, convs;
|
||||
int viable;
|
||||
{
|
||||
struct z_candidate *cand
|
||||
= (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
|
||||
|
||||
cand->fn = fn;
|
||||
cand->convs = convs;
|
||||
cand->second_conv = NULL_TREE;
|
||||
cand->viable = viable;
|
||||
cand->basetype_path = NULL_TREE;
|
||||
cand->template = NULL_TREE;
|
||||
cand->warnings = NULL_TREE;
|
||||
cand->next = candidates;
|
||||
|
||||
return cand;
|
||||
}
|
||||
|
||||
/* Create an overload candidate for the function or method FN called with
|
||||
the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on
|
||||
to implicit_conversion. */
|
||||
|
@ -1130,17 +1157,7 @@ add_function_candidate (candidates, fn, arglist, flags)
|
|||
break;
|
||||
}
|
||||
|
||||
cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
|
||||
|
||||
cand->fn = fn;
|
||||
cand->convs = convs;
|
||||
cand->second_conv = NULL_TREE;
|
||||
cand->viable = viable;
|
||||
cand->basetype_path = NULL_TREE;
|
||||
cand->template = NULL_TREE;
|
||||
cand->next = candidates;
|
||||
|
||||
return cand;
|
||||
return add_candidate (candidates, fn, convs, viable);
|
||||
}
|
||||
|
||||
/* Create an overload candidate for the conversion function FN which will
|
||||
|
@ -1207,17 +1224,7 @@ add_conv_candidate (candidates, fn, obj, arglist)
|
|||
break;
|
||||
}
|
||||
|
||||
cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
|
||||
|
||||
cand->fn = fn;
|
||||
cand->convs = convs;
|
||||
cand->second_conv = NULL_TREE;
|
||||
cand->viable = viable;
|
||||
cand->basetype_path = NULL_TREE;
|
||||
cand->template = NULL_TREE;
|
||||
cand->next = candidates;
|
||||
|
||||
return cand;
|
||||
return add_candidate (candidates, fn, convs, viable);
|
||||
}
|
||||
|
||||
static struct z_candidate *
|
||||
|
@ -1267,17 +1274,7 @@ build_builtin_candidate (candidates, fnname, type1, type2,
|
|||
viable = 0;
|
||||
}
|
||||
|
||||
cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
|
||||
|
||||
cand->fn = fnname;
|
||||
cand->convs = convs;
|
||||
cand->second_conv = NULL_TREE;
|
||||
cand->viable = viable;
|
||||
cand->basetype_path = NULL_TREE;
|
||||
cand->template = NULL_TREE;
|
||||
cand->next = candidates;
|
||||
|
||||
return cand;
|
||||
return add_candidate (candidates, fnname, convs, viable);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -2173,7 +2170,7 @@ build_user_type_conversion_1 (totype, expr, flags)
|
|||
(USER_CONV,
|
||||
(DECL_CONSTRUCTOR_P (cand->fn)
|
||||
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
|
||||
expr, cand->fn, cand->convs, cand->basetype_path);
|
||||
expr, build_expr_ptr_wrapper (cand));
|
||||
ICS_USER_FLAG (cand->second_conv) = 1;
|
||||
if (cand->viable == -1)
|
||||
ICS_BAD_FLAG (cand->second_conv) = 1;
|
||||
|
@ -2287,7 +2284,7 @@ build_new_function_call (fn, args)
|
|||
&& ! DECL_INITIAL (cand->fn))
|
||||
add_maybe_template (cand->fn, templates);
|
||||
|
||||
return build_over_call (cand->fn, cand->convs, args, LOOKUP_NORMAL);
|
||||
return build_over_call (cand, args, LOOKUP_NORMAL);
|
||||
}
|
||||
|
||||
return build_function_call (fn, args);
|
||||
|
@ -2390,7 +2387,7 @@ build_object_call (obj, args)
|
|||
}
|
||||
|
||||
if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
|
||||
return build_over_call (cand->fn, cand->convs, mem_args, LOOKUP_NORMAL);
|
||||
return build_over_call (cand, mem_args, LOOKUP_NORMAL);
|
||||
|
||||
obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
|
||||
|
||||
|
@ -2719,9 +2716,6 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
|||
: candidates->fn);
|
||||
}
|
||||
|
||||
if (DECL_FUNCTION_MEMBER_P (cand->fn))
|
||||
enforce_access (cand->basetype_path, cand->fn);
|
||||
|
||||
/* Pedantically, normal function declarations are never considered
|
||||
to refer to template instantiations, so we only do this with
|
||||
-fguiding-decls. */
|
||||
|
@ -2731,7 +2725,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
|||
add_maybe_template (cand->fn, templates);
|
||||
|
||||
return build_over_call
|
||||
(cand->fn, cand->convs,
|
||||
(cand,
|
||||
TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
|
||||
? mem_arglist : arglist,
|
||||
LOOKUP_NORMAL);
|
||||
|
@ -3045,9 +3039,10 @@ convert_like (convs, expr)
|
|||
{
|
||||
case USER_CONV:
|
||||
{
|
||||
tree fn = TREE_OPERAND (convs, 1);
|
||||
struct z_candidate *cand
|
||||
= WRAPPER_PTR (TREE_OPERAND (convs, 1));
|
||||
tree fn = cand->fn;
|
||||
tree args;
|
||||
enforce_access (TREE_OPERAND (convs, 3), fn);
|
||||
|
||||
if (DECL_CONSTRUCTOR_P (fn))
|
||||
{
|
||||
|
@ -3061,9 +3056,7 @@ convert_like (convs, expr)
|
|||
}
|
||||
else
|
||||
args = build_this (expr);
|
||||
expr = build_over_call
|
||||
(TREE_OPERAND (convs, 1), TREE_OPERAND (convs, 2),
|
||||
args, LOOKUP_NORMAL);
|
||||
expr = build_over_call (cand, args, LOOKUP_NORMAL);
|
||||
|
||||
/* If this is a constructor or a function returning an aggr type,
|
||||
we need to build up a TARGET_EXPR. */
|
||||
|
@ -3147,16 +3140,27 @@ convert_default_arg (type, arg)
|
|||
}
|
||||
|
||||
static tree
|
||||
build_over_call (fn, convs, args, flags)
|
||||
tree fn, convs, args;
|
||||
build_over_call (cand, args, flags)
|
||||
struct z_candidate *cand;
|
||||
tree args;
|
||||
int flags;
|
||||
{
|
||||
tree fn = cand->fn;
|
||||
tree convs = cand->convs;
|
||||
tree converted_args = NULL_TREE;
|
||||
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
|
||||
tree conv, arg, val;
|
||||
int i = 0;
|
||||
int is_method = 0;
|
||||
|
||||
/* Give any warnings we noticed during overload resolution. */
|
||||
if (cand->warnings)
|
||||
for (val = cand->warnings; val; val = TREE_CHAIN (val))
|
||||
joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
|
||||
|
||||
if (DECL_FUNCTION_MEMBER_P (fn))
|
||||
enforce_access (cand->basetype_path, fn);
|
||||
|
||||
if (args && TREE_CODE (args) != TREE_LIST)
|
||||
args = build_scratch_list (NULL_TREE, args);
|
||||
arg = args;
|
||||
|
@ -3588,7 +3592,6 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
enforce_access (cand->basetype_path, cand->fn);
|
||||
if (DECL_ABSTRACT_VIRTUAL_P (cand->fn)
|
||||
&& instance == current_class_ref
|
||||
&& DECL_CONSTRUCTOR_P (current_function_decl)
|
||||
|
@ -3613,7 +3616,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
|||
add_maybe_template (cand->fn, templates);
|
||||
|
||||
return build_over_call
|
||||
(cand->fn, cand->convs,
|
||||
(cand,
|
||||
TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
|
||||
flags);
|
||||
}
|
||||
|
@ -3939,7 +3942,6 @@ compare_ics (ics1, ics2)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* The source type for this standard conversion sequence. */
|
||||
|
||||
static tree
|
||||
|
@ -3955,7 +3957,19 @@ source_type (t)
|
|||
}
|
||||
my_friendly_abort (1823);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Note a warning about preferring WINNER to LOSER. We do this by storing
|
||||
a pointer to LOSER and re-running joust to produce the warning if WINNER
|
||||
is actually used. */
|
||||
|
||||
static void
|
||||
add_warning (winner, loser)
|
||||
struct z_candidate *winner, *loser;
|
||||
{
|
||||
winner->warnings = expr_tree_cons (NULL_PTR,
|
||||
build_expr_ptr_wrapper (loser),
|
||||
winner->warnings);
|
||||
}
|
||||
|
||||
/* Compare two candidates for overloading as described in
|
||||
[over.match.best]. Return values:
|
||||
|
@ -3965,8 +3979,9 @@ source_type (t)
|
|||
0: cand1 and cand2 are indistinguishable */
|
||||
|
||||
static int
|
||||
joust (cand1, cand2)
|
||||
joust (cand1, cand2, warn)
|
||||
struct z_candidate *cand1, *cand2;
|
||||
int warn;
|
||||
{
|
||||
int winner = 0;
|
||||
int i, off1 = 0, off2 = 0, len;
|
||||
|
@ -4014,7 +4029,6 @@ joust (cand1, cand2)
|
|||
|
||||
if (comp != 0)
|
||||
{
|
||||
#if 0 /* move this warning to tourney. */
|
||||
if (warn_sign_promo
|
||||
&& ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK
|
||||
&& TREE_CODE (t1) == STD_CONV
|
||||
|
@ -4029,16 +4043,23 @@ joust (cand1, cand2)
|
|||
{
|
||||
tree type = TREE_TYPE (TREE_OPERAND (t1, 0));
|
||||
tree type1, type2;
|
||||
struct z_candidate *w, *l;
|
||||
if (comp > 0)
|
||||
type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2);
|
||||
type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2),
|
||||
w = cand1, l = cand2;
|
||||
else
|
||||
type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1);
|
||||
type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1),
|
||||
w = cand2, l = cand1;
|
||||
|
||||
cp_warning ("passing `%T' chooses `%T' over `%T'",
|
||||
type, type1, type2);
|
||||
cp_warning (" in call to `%D'", DECL_NAME (cand1->fn));
|
||||
if (warn)
|
||||
{
|
||||
cp_warning ("passing `%T' chooses `%T' over `%T'",
|
||||
type, type1, type2);
|
||||
cp_warning (" in call to `%D'", w->fn);
|
||||
}
|
||||
else
|
||||
add_warning (w, l);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (winner && comp != winner)
|
||||
{
|
||||
|
@ -4049,7 +4070,6 @@ joust (cand1, cand2)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0 /* move this warning to tourney. */
|
||||
/* warn about confusing overload resolution */
|
||||
if (winner && cand1->second_conv
|
||||
&& ! DECL_CONSTRUCTOR_P (cand1->fn)
|
||||
|
@ -4063,14 +4083,18 @@ joust (cand1, cand2)
|
|||
w = cand1, l = cand2;
|
||||
else
|
||||
w = cand2, l = cand1;
|
||||
cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
|
||||
cp_warning (" for conversion from `%T' to `%T'",
|
||||
TREE_TYPE (source_type (TREE_VEC_ELT (w->convs, 0))),
|
||||
TREE_TYPE (w->second_conv));
|
||||
cp_warning (" because conversion sequence for `this' argument is better");
|
||||
if (warn)
|
||||
{
|
||||
cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
|
||||
cp_warning (" for conversion from `%T' to `%T'",
|
||||
TREE_TYPE (source_type (TREE_VEC_ELT (w->convs, 0))),
|
||||
TREE_TYPE (w->second_conv));
|
||||
cp_warning (" because conversion sequence for `this' argument is better");
|
||||
}
|
||||
else
|
||||
add_warning (w, l);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (winner)
|
||||
return winner;
|
||||
|
@ -4171,7 +4195,7 @@ tourney (candidates)
|
|||
|
||||
for (challenger = champ->next; challenger; )
|
||||
{
|
||||
fate = joust (champ, challenger);
|
||||
fate = joust (champ, challenger, 0);
|
||||
if (fate == 1)
|
||||
challenger = challenger->next;
|
||||
else
|
||||
|
@ -4196,7 +4220,7 @@ tourney (candidates)
|
|||
for (challenger = candidates; challenger != champ;
|
||||
challenger = challenger->next)
|
||||
{
|
||||
fate = joust (champ, challenger);
|
||||
fate = joust (champ, challenger, 0);
|
||||
if (fate != 1)
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -173,6 +173,10 @@ DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
|
|||
/* XXX: could recycle some of the common fields */
|
||||
DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
|
||||
|
||||
/* A generic wrapper for something not tree that we want to include in
|
||||
tree structure. */
|
||||
DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
|
||||
|
||||
/* A whole bunch of tree codes for the initial, superficial parsing of
|
||||
templates. */
|
||||
DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 2)
|
||||
|
@ -208,6 +212,10 @@ DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
|
|||
DEFTREECODE (TRY_BLOCK, "try_stmt", 'e', 2)
|
||||
DEFTREECODE (HANDLER, "catch_stmt", 'e', 2)
|
||||
|
||||
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
|
||||
|
||||
/* And some codes for expressing conversions for overload resolution. */
|
||||
|
||||
DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1)
|
||||
DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1)
|
||||
DEFTREECODE (QUAL_CONV, "qual_conv", 'e', 1)
|
||||
|
@ -216,12 +224,10 @@ DEFTREECODE (PTR_CONV, "ptr_conv", 'e', 1)
|
|||
DEFTREECODE (PMEM_CONV, "pmem_conv", 'e', 1)
|
||||
DEFTREECODE (BASE_CONV, "base_conv", 'e', 1)
|
||||
DEFTREECODE (REF_BIND, "ref_bind", 'e', 1)
|
||||
DEFTREECODE (USER_CONV, "user_conv", 'e', 4)
|
||||
DEFTREECODE (USER_CONV, "user_conv", 'e', 2)
|
||||
DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1)
|
||||
DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1)
|
||||
|
||||
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
mode:c
|
||||
|
|
|
@ -73,6 +73,18 @@ struct tree_binding
|
|||
tree value;
|
||||
};
|
||||
|
||||
#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr)
|
||||
#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i)
|
||||
|
||||
struct tree_wrapper
|
||||
{
|
||||
char common[sizeof (struct tree_common)];
|
||||
union {
|
||||
void *ptr;
|
||||
int i;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* To identify to the debug emitters if it should pay attention to the
|
||||
flag `-Wtemplate-debugging'. */
|
||||
#define HAVE_TEMPLATES 1
|
||||
|
@ -2624,6 +2636,9 @@ extern tree hack_decl_function_context PROTO((tree));
|
|||
extern tree lvalue_type PROTO((tree));
|
||||
extern tree error_type PROTO((tree));
|
||||
extern tree make_temp_vec PROTO((int));
|
||||
extern tree build_ptr_wrapper PROTO((void *));
|
||||
extern tree build_expr_ptr_wrapper PROTO((void *));
|
||||
extern tree build_int_wrapper PROTO((int));
|
||||
extern int varargs_function_p PROTO((tree));
|
||||
extern int really_overloaded_fn PROTO((tree));
|
||||
extern int cp_tree_equal PROTO((tree, tree));
|
||||
|
|
|
@ -5594,7 +5594,7 @@ template_decl_level (decl)
|
|||
|
||||
default:
|
||||
my_friendly_abort (0);
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2141,6 +2141,41 @@ make_temp_vec (len)
|
|||
return node;
|
||||
}
|
||||
|
||||
/* Build a wrapper around some pointer PTR so we can use it as a tree. */
|
||||
|
||||
tree
|
||||
build_ptr_wrapper (ptr)
|
||||
void *ptr;
|
||||
{
|
||||
tree t = make_node (WRAPPER);
|
||||
WRAPPER_PTR (t) = ptr;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Same, but on the expression_obstack. */
|
||||
|
||||
tree
|
||||
build_expr_ptr_wrapper (ptr)
|
||||
void *ptr;
|
||||
{
|
||||
tree t;
|
||||
push_expression_obstack ();
|
||||
t = build_ptr_wrapper (ptr);
|
||||
pop_obstacks ();
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Build a wrapper around some integer I so we can use it as a tree. */
|
||||
|
||||
tree
|
||||
build_int_wrapper (i)
|
||||
int i;
|
||||
{
|
||||
tree t = make_node (WRAPPER);
|
||||
WRAPPER_INT (t) = i;
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
push_expression_obstack ()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue