From 5ffe581dd305bd58d49d53fc2d3776d89e56a541 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 23 Apr 1998 22:26:41 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 19 ++++++ gcc/cp/call.c | 166 ++++++++++++++++++++++++++------------------- gcc/cp/cp-tree.def | 12 +++- gcc/cp/cp-tree.h | 15 ++++ gcc/cp/pt.c | 2 +- gcc/cp/tree.c | 35 ++++++++++ 6 files changed, 174 insertions(+), 75 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5f2a5d41e9b..eb764e85be1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +Thu Apr 23 21:19:06 1998 Jason Merrill + + * 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 * pt.c (unify): Fix typo in previous change. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 46a5be00ef3..5fd81f511bd 100644 --- a/gcc/cp/call.c +++ b/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; } diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 5ee7500bfb5..0a42d74a67b 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8b943c43a21..3247196fcc2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d88f9fe3a3e..5284e7654ea 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5594,7 +5594,7 @@ template_decl_level (decl) default: my_friendly_abort (0); - break; + return 0; } } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index de3906c5802..3b4ca22efc9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 () {