diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-08-08 22:54:56 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 1996-08-08 22:54:56 +0000 |
commit | ec10e4ad2a7d64dba71cec2a34bb79f839ee01ec (patch) | |
tree | 52ddcb80dfa8e9c159b836a1a31024a019afd0e4 /gcc/cp | |
parent | c18a09dbd1806eb14bbb8a56c3fa13c4f1b42f70 (diff) | |
download | gcc-ec10e4ad2a7d64dba71cec2a34bb79f839ee01ec.tar.gz |
87th Cygnus<->FSF quick merge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@12606 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 165 | ||||
-rw-r--r-- | gcc/cp/call.c | 2671 | ||||
-rw-r--r-- | gcc/cp/class.c | 8 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 15 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2465 | ||||
-rw-r--r-- | gcc/cp/decl.c | 39 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 16 | ||||
-rw-r--r-- | gcc/cp/error.c | 15 | ||||
-rw-r--r-- | gcc/cp/except.c | 5 | ||||
-rw-r--r-- | gcc/cp/gxx.gperf | 1 | ||||
-rw-r--r-- | gcc/cp/hash.h | 240 | ||||
-rw-r--r-- | gcc/cp/init.c | 14 | ||||
-rw-r--r-- | gcc/cp/lex.c | 5 | ||||
-rw-r--r-- | gcc/cp/lex.h | 1 | ||||
-rw-r--r-- | gcc/cp/method.c | 12 | ||||
-rw-r--r-- | gcc/cp/pt.c | 17 | ||||
-rw-r--r-- | gcc/cp/search.c | 10 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 73 |
18 files changed, 3152 insertions, 2620 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 089537308e7..f65965add97 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -3,8 +3,173 @@ Thu Aug 8 17:48:16 1996 Michael Meissner <meissner@tiktok.cygnus.com> * decl2.c (import_export_vtable): Delete code that disabled vtable heuristic on systems with ASM_OUTPUT_EXTERNAL. +Wed Aug 7 12:44:11 1996 Jason Merrill <jason@yorick.cygnus.com> + + * typeck.c (build_x_function_call): Handle static call context + better. + + * decl.c (finish_function): Set the DECL_CONTEXT of the result to + the function, not its outer block. + + * call.c (build_field_call): Pass fields on to build_opfncall + regardless of TYPE_OVERLOADS_CALL_EXPR. + (build_method_call): Pass on to build_new_method_call sooner. + + * typeck.c (build_ptrmemfunc): Just return what instantiate_type + gives us. + * class.c (instantiate_type): Don't put a POINTER_TYPE to + METHOD_TYPE on an expression. Also make a copy of rhs instead of + modifying it. + +Tue Aug 6 12:58:46 1996 Jason Merrill <jason@yorick.cygnus.com> + + * call.c (compare_ics): Handle qual_conv after lvalue_conv. + (add_builtin_candidate): Don't take enums for ++. + (build_new_method_call): Handle non-aggregates and field calls. + Move new overloading code from... + * cvt.c: Here. + + * decl.c (grokparms): Don't check default args in templates. + +Mon Aug 5 17:17:06 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (build_new_op): Fix args to build_unary_op. + (add_builtin_candidates): Don't call type_promotes_to on float. + + * decl.c (grokparms): Check the type of the default arg. + + * cvt.c (build_new_op): Pass non-overloaded cases on rather than + returning NULL_TREE. + + * typeck.c (build_x_binary_op): Avoid doing extra work. + (build_x_unary_op): Ditto. + (build_x_conditional_expr): Ditto. + * cvt.c (build_over_call): Return. + (add_builtin_candidate): Fix MEMBER_REF. + (build_new_op): Ditto. + +Mon Aug 5 17:07:47 1996 Mike Stump <mrs@cygnus.com> + + * method.c (build_overload_name): Put bug fix into code but leave + disabled for now so we can be bug compatible with older releases + that do repeats incorrectly. In the future, we can enable it. + +Mon Aug 5 13:46:28 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (convert_like): Don't call build_cplus_new twice. + + * call.c, cp-tree.h, cvt.c, decl2.c, init.c, method.c, pt.c, typeck.c: + Control new overloading code with -fansi-overloading. + +Sun Aug 4 15:29:11 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (build_over_call): Call build_cplus_new. + * call.c (build_method_call): Ditto. + * typeck.c (build_function_call_real): Ditto. + (build_conditional_expr): If both operands are TARGET_EXPRs, wrap + the COND_EXPR in a TARGET_EXPR so they use the same slot. + + * cvt.c (build_up_reference): Propagate INDIRECT_BIND to + recursive calls. + * typeck.c (complete_type): Propagate + TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}. + +Sat Aug 3 14:05:07 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (joust): More ?: kludging. Sigh. + (build_over_call): Don't try to synthesize global fns. + + * search.c (lookup_conversions): Use binfo marking. + +Sat Aug 3 12:33:42 1996 Bob Manson <manson@charmed.cygnus.com> + + * search.c (build_mi_matrix): Use the correct value of cid + when determining the new mi_size. + +Sat Aug 3 01:27:41 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (add_builtin_candidates): Do consider type conversion ops + for the first parms of += et al. + (strip_top_quals): New fn. + (reference_binding): Use it instead of TYPE_MAIN_VARIANT. + (implicit_conversion): Ditto. + (add_builtin_candidates): Be careful about arrays. + (build_new_method_call): Handle vtable optimization. + +Fri Aug 2 01:26:59 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cp-tree.h (LOOKUP_NO_TEMP_BIND): New flag. + * cvt.c (reference_binding): Use it. + (implicit_conversion): Use it. + (add_builtin_candidate, COND_EXPR): Use it. + + * cvt.c (build_new_function_call): Check for error args. + + * typeck.c (comptypes): Just check DERIVED_FROM_P, not UNIQUELY. + + * gxx.gperf: Add __null. + * hash.h: Regenerate. + * lex.h: Add RID_NULL. + * lex.c (init_lex): Create null_pointer_node here, stick it in + RID_NULL. + * decl.c (init_decl_processing): Still set its type here. + * cvt.c (cp_convert_to_pointer): Don't produce null_pointer_node. + (convert_to_pointer_force): Ditto. + (null_ptr_cst_p): Check for null_pointer_node; only accept (void*)0 + if (! pedantic). + * call.c (convert_harshness): Use null_ptr_cst_p. + * typeck.c (convert_for_assignment): Ditto. Don't produce + null_pointer_node. + + * error.c (args_as_string): Handle lists of actual args, too. + * cvt.c (null_ptr_cst): Support (void*)0 for now. + (build_user_type_conversion_1): Improve diagnostics. + (build_new_function_call): Likewise. + (build_object_call): Likewise. + (build_new_method_call): Likewise. Move call before def diagnostic... + (build_over_call): Here. + + * cvt.c (build_new_method_call): Don't complain about no match if + LOOKUP_SPECULATIVELY. + (build_over_call): Fix 'this' for virtual fn. + (build_new_method_call): Add diagnostic. + +Thu Aug 1 16:45:09 1996 Jason Merrill <jason@yorick.cygnus.com> + + * cvt.c (add_function_candidate): Expect 'this' and 'in_chrg' for + constructors to be passed in. + (build_over_call): Likewise. + (build_user_type_conversion_1): Pass them in. + (convert_like): Likewise. + (build_object_call): Handle overloaded conversions. + (build_over_call): Pass the right args to build_vfn_ref. + (standard_conversion): Fix pmf convs. + (joust): Handle comparing statics and non-statics. + (build_new_method_call): New fn. + * call.c (build_method_call): Call it if NEW_OVER. + +Thu Aug 1 16:06:14 1996 Mike Stump <mrs@cygnus.com> + + * lex.c (do_identifier): Don't use %O on IDENTIFIER_OPNAME_Ps, use + %D instead. + +Thu Aug 1 15:24:02 1996 Mike Stump <mrs@cygnus.com> + + * except.c (expand_throw): Use maybe_build_cleanup_and_delete + instead of just maybe_build_cleanup so that we deallocate the + thrown object. + +Thu Aug 1 15:18:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com> + + * decl2.c (finish_prevtable_vardecl): Make non-static for pt.c's use. + * cp-tree.h (finish_prevtable_vardecl): Add decl. + Thu Aug 1 11:53:51 1996 Bob Manson <manson@charmed.cygnus.com> + * pt.c (instantiate_class_template): Call complete_type. Also, if + we're at the end of the file and we just instantiated a template + class with a vtable, call finish_prevtable_vardecl. + * error.c (dump_decl): Don't explode (or explode more gracefully as appropriate) if the object being dumped has a null type. (dump_expr): Ditto. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 741e703c1bb..b81f35f21b3 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -508,7 +508,7 @@ convert_harshness (type, parmtype, parm) #if 1 if (TREE_CODE (ttl) != VOID_TYPE - && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm))) + && (TREE_CODE (ttr) != VOID_TYPE || !parm || !null_ptr_cst_p (parm))) { if (comp_target_types (type, parmtype, 1) <= 0) return EVIL_RETURN (h); @@ -1214,7 +1214,8 @@ build_field_call (basetype_path, instance_ptr, name, parms) return error_mark_node; if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance)) - && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance))) + && (TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance)) + || flag_ansi_overloading)) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE); if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) @@ -1245,7 +1246,8 @@ build_field_call (basetype_path, instance_ptr, name, parms) if (TREE_CODE (ftype) == REFERENCE_TYPE) ftype = TREE_TYPE (ftype); - if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype)) + if (TYPE_LANG_SPECIFIC (ftype) + && (TYPE_OVERLOADS_CALL_EXPR (ftype) || flag_ansi_overloading)) { /* Make the next search for this field very short. */ basetype = DECL_FIELD_CONTEXT (field); @@ -1759,6 +1761,9 @@ build_method_call (instance, name, parms, basetype_path, flags) LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); } + if (flag_ansi_overloading) + return build_new_method_call (instance, name, parms, basetype_path, flags); + { char *xref_name; @@ -2621,6 +2626,8 @@ build_method_call (instance, name, parms, basetype_path, flags) IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function))); result = build_call (function, value_type, parms); + if (IS_AGGR_TYPE (value_type)) + result = build_cplus_new (value_type, result); result = convert_from_reference (result); return result; } @@ -2903,3 +2910,2661 @@ build_overload_call (fnname, parms, flags) { return build_overload_call_real (fnname, parms, flags, (struct candidate *)0, 1); } + +/* New overloading code. */ + +struct z_candidate { + tree fn; + tree convs; + tree second_conv; + int viable; + tree basetype_path; + tree template; + struct z_candidate *next; +}; + +#define IDENTITY_RANK 0 +#define EXACT_RANK 1 +#define PROMO_RANK 2 +#define STD_RANK 3 +#define PBOOL_RANK 4 +#define USER_RANK 5 +#define ELLIPSIS_RANK 6 + +#define ICS_RANK(NODE) \ + (ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \ + : ICS_USER_FLAG (NODE) ? USER_RANK \ + : ICS_STD_RANK (NODE)) + +#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE) + +#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE) +#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) + +#define USER_CONV_FN(NODE) TREE_OPERAND (NODE, 1) + +static struct z_candidate * build_user_type_conversion_1 (); +static tree convert_like (); +static tree build_over_call (); +static struct z_candidate * tourney (); +static void enforce_access (); + +int +null_ptr_cst_p (t) + tree t; +{ + if (t == null_pointer_node + || integer_zerop (t) && INTEGRAL_TYPE_P (TREE_TYPE (t))) + return 1; + /* Remove this eventually. */ + if (! pedantic && TREE_TYPE (t) == ptr_type_node && integer_zerop (t)) + return 1; + return 0; +} + +tree +build_conv (code, type, from) + enum tree_code code; + tree type, from; +{ + tree t = build1 (code, type, from); + int rank = ICS_STD_RANK (from); + switch (code) + { + case PTR_CONV: + case PMEM_CONV: + case BASE_CONV: + case STD_CONV: + if (rank < STD_RANK) + rank = STD_RANK; + break; + + case LVALUE_CONV: + case QUAL_CONV: + case RVALUE_CONV: + if (rank < EXACT_RANK) + rank = EXACT_RANK; + + default: + break; + } + ICS_STD_RANK (t) = rank; + ICS_USER_FLAG (t) = ICS_USER_FLAG (from); + return t; +} + +tree +non_reference (t) + tree t; +{ + if (TREE_CODE (t) == REFERENCE_TYPE) + t = TREE_TYPE (t); + return t; +} + +/* Returns the standard conversion path (see [conv]) from type FROM to type + TO, if any. For proper handling of null pointer constants, you must + also pass the expression EXPR to convert from. */ + +tree +standard_conversion (to, from, expr) + tree to, from, expr; +{ + enum tree_code fcode, tcode; + tree conv; + + fcode = TREE_CODE (from); + tcode = TREE_CODE (to); + + conv = build1 (IDENTITY_CONV, from, expr); + + if (from == to) + return conv; + + if (fcode == FUNCTION_TYPE) + { + from = build_pointer_type (from); + fcode = TREE_CODE (from); + conv = build_conv (LVALUE_CONV, from, conv); + } + else if (fcode == ARRAY_TYPE) + { + from = build_pointer_type (TREE_TYPE (from)); + fcode = TREE_CODE (from); + conv = build_conv (LVALUE_CONV, from, conv); + } + + if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) + && expr && null_ptr_cst_p (expr)) + { + conv = build_conv (STD_CONV, to, conv); + } + else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) + { + enum tree_code ufcode = TREE_CODE (TREE_TYPE (from)); + enum tree_code utcode = TREE_CODE (TREE_TYPE (to)); + + if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (from)), + TYPE_MAIN_VARIANT (TREE_TYPE (to)), 1)) + /* OK for now */; + else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE + && ufcode != FUNCTION_TYPE) + { + from = build_pointer_type + (cp_build_type_variant (void_type_node, + TYPE_READONLY (TREE_TYPE (from)), + TYPE_VOLATILE (TREE_TYPE (from)))); + conv = build_conv (PTR_CONV, from, conv); + } + else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) + { + tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); + tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); + + if (DERIVED_FROM_P (fbase, tbase) + && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))), + TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))), + 1))) + { + from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); + from = build_pointer_type (from); + conv = build_conv (PMEM_CONV, from, conv); + } + else + return 0; + } + else if (IS_AGGR_TYPE (TREE_TYPE (from)) + && IS_AGGR_TYPE (TREE_TYPE (to))) + { + if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) + { + from = cp_build_type_variant (TREE_TYPE (to), + TYPE_READONLY (TREE_TYPE (from)), + TYPE_VOLATILE (TREE_TYPE (from))); + from = build_pointer_type (from); + conv = build_conv (PTR_CONV, from, conv); + } + else + return 0; + } + else + return 0; + + if (! comptypes (from, to, 1)) + { + if (! comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from))) + return 0; + + from = to; + conv = build_conv (QUAL_CONV, from, conv); + } + } + else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from)) + { + tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from)); + tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to)); + tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn))); + tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn))); + + if (! DERIVED_FROM_P (fbase, tbase) + || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1) + || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)), + TREE_CHAIN (TYPE_ARG_TYPES (tofn)), 1) + || TYPE_READONLY (fbase) != TYPE_READONLY (tbase) + || TYPE_VOLATILE (fbase) != TYPE_VOLATILE (tbase)) + return 0; + + from = cp_build_type_variant (tbase, TYPE_READONLY (fbase), + TYPE_VOLATILE (fbase)); + from = build_cplus_method_type (from, TREE_TYPE (fromfn), + TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); + from = build_ptrmemfunc_type (build_pointer_type (from)); + conv = build_conv (PMEM_CONV, from, conv); + } + else if (tcode == BOOLEAN_TYPE) + { + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE + || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) + return 0; + + 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; + } + /* We don't check for ENUMERAL_TYPE here because there are no standard + conversions to enum type. */ + else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE + || tcode == REAL_TYPE) + { + if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) + return 0; + 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); + else + return 0; + + return conv; +} + +tree +strip_top_quals (t) + tree t; +{ + if (TREE_CODE (t) == ARRAY_TYPE) + return t; + return TYPE_MAIN_VARIANT (t); +} + +/* Returns the conversion path from type FROM to reference type TO for + purposes of reference binding. For lvalue binding, either pass a + reference type to FROM or an lvalue expression to EXPR. + + Currently does not distinguish in the generated trees between binding to + an lvalue and a temporary. Should it? */ + +tree +reference_binding (rto, from, expr, flags) + tree rto, from, expr; + int flags; +{ + tree conv; + int lvalue = 1; + tree to = TREE_TYPE (rto); + + if (TREE_CODE (from) == REFERENCE_TYPE) + from = TREE_TYPE (from); + else if (! expr || ! real_lvalue_p (expr)) + lvalue = 0; + + if (lvalue + && TYPE_READONLY (to) >= TYPE_READONLY (from) + && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from)) + { + conv = build1 (IDENTITY_CONV, from, expr); + + if (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from)) + conv = build_conv (REF_BIND, rto, conv); + else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) + && DERIVED_FROM_P (to, from)) + { + conv = build_conv (REF_BIND, rto, conv); + ICS_STD_RANK (conv) = STD_RANK; + } + else + conv = NULL_TREE; + } + else + conv = NULL_TREE; + + if (! conv && TYPE_READONLY (to) && ! TYPE_VOLATILE (to) + && (flags & LOOKUP_NO_TEMP_BIND) == 0) + { + conv = standard_conversion + (TYPE_MAIN_VARIANT (to), strip_top_quals (from), expr); + if (conv) + { + conv = build_conv (REF_BIND, rto, conv); + + /* Bind directly to a base subobject of a class rvalue. */ + if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) + TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); + } + } + + return conv; +} + +/* Returns the implicit conversion sequence (see [over.ics]) from type FROM + to type TO. The optional expression EXPR may affect the conversion. + FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is + significant. */ + +tree +implicit_conversion (to, from, expr, flags) + tree to, from, expr; + int flags; +{ + tree conv; + struct z_candidate *cand; + + if (expr && type_unknown_p (expr)) + { + expr = instantiate_type (to, expr, 0); + if (expr == error_mark_node) + return 0; + from = TREE_TYPE (expr); + } + + if (TREE_CODE (to) == REFERENCE_TYPE) + conv = reference_binding (to, from, expr, flags); + else + conv = standard_conversion + (TYPE_MAIN_VARIANT (non_reference (to)), + strip_top_quals (non_reference (from)), expr); + + if (conv) + { + if (TREE_CODE (conv) == IDENTITY_CONV && IS_AGGR_TYPE (to) + && (TREE_CODE (from) == REFERENCE_TYPE || (expr && real_lvalue_p (expr)))) + conv = build_conv (RVALUE_CONV, to, conv); + } + else if ((IS_AGGR_TYPE (non_reference (from)) + || IS_AGGR_TYPE (non_reference (to))) + && (flags & LOOKUP_NO_CONVERSION) == 0) + { + if (TREE_CODE (to) == REFERENCE_TYPE + && TYPE_READONLY (TREE_TYPE (to)) + && ! TYPE_VOLATILE (TREE_TYPE (to)) + && (flags & LOOKUP_NO_TEMP_BIND) == 0) + { + cand = build_user_type_conversion_1 + (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING); + if (cand) + conv = build_conv (REF_BIND, to, cand->second_conv); + } + else + { + cand = build_user_type_conversion_1 + (to, expr, LOOKUP_ONLYCONVERTING); + if (cand) + conv = cand->second_conv; + } + } + + return conv; +} + +/* 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. */ + +static struct z_candidate * +add_function_candidate (candidates, fn, arglist, flags) + struct z_candidate *candidates; + tree fn, arglist; + int flags; +{ + tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); + int i, len; + tree convs; + tree parmnode = parmlist; + tree argnode = arglist; + int viable = 1; + struct z_candidate *cand; + + /* The `this' and `in_chrg' arguments to constructors are not considered + in overload resolution. */ + if (DECL_CONSTRUCTOR_P (fn)) + { + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + { + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + } + } + + len = list_length (argnode); + convs = make_tree_vec (len); + + for (i = 0; i < len; ++i) + { + tree arg = TREE_VALUE (argnode); + tree argtype = TREE_TYPE (arg); + tree t; + + argtype = cp_build_type_variant + (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg)); + + if (parmnode == void_list_node) + break; + else if (parmnode) + t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); + else + { + t = build1 (IDENTITY_CONV, argtype, arg); + ICS_ELLIPSIS_FLAG (t) = 1; + } + + TREE_VEC_ELT (convs, i) = t; + if (! t) + break; + + if (parmnode) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + } + + if (i < len) + viable = 0; + + /* Make sure there are default args for the rest of the parms. */ + for (; parmnode && parmnode != void_list_node; + parmnode = TREE_CHAIN (parmnode)) + if (! TREE_PURPOSE (parmnode)) + { + viable = 0; + break; + } + + cand = (struct z_candidate *) oballoc (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; +} + +/* Create an overload candidate for the conversion function FN which will + be invoked for expression OBJ, producing a pointer-to-function which + will in turn be called with the argument list ARGLIST, and add it to + CANDIDATES. FLAGS is passed on to implicit_conversion. */ + +static struct z_candidate * +add_conv_candidate (candidates, fn, obj, arglist) + struct z_candidate *candidates; + tree fn, obj, arglist; +{ + tree totype = TREE_TYPE (TREE_TYPE (fn)); + tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); + int i, len = list_length (arglist) + 1; + tree convs = make_tree_vec (len); + tree parmnode = parmlist; + tree argnode = arglist; + int viable = 1; + struct z_candidate *cand; + int flags = LOOKUP_NORMAL; + + for (i = 0; i < len; ++i) + { + tree arg = i == 0 ? obj : TREE_VALUE (argnode); + tree argtype = TREE_TYPE (arg); + tree t; + + argtype = cp_build_type_variant + (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg)); + + if (i == 0) + t = implicit_conversion (totype, argtype, arg, flags); + else if (parmnode == void_list_node) + break; + else if (parmnode) + t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); + else + { + t = build1 (IDENTITY_CONV, argtype, arg); + ICS_ELLIPSIS_FLAG (t) = 1; + } + + TREE_VEC_ELT (convs, i) = t; + if (! t) + break; + + if (i == 0) + continue; + + if (parmnode) + parmnode = TREE_CHAIN (parmnode); + argnode = TREE_CHAIN (argnode); + } + + if (i < len) + viable = 0; + + for (; parmnode && parmnode != void_list_node; + parmnode = TREE_CHAIN (parmnode)) + if (! TREE_PURPOSE (parmnode)) + { + viable = 0; + break; + } + + cand = (struct z_candidate *) oballoc (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; +} + +int +ptr_complete_ob (t) + tree t; +{ + return (TREE_CODE (t) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (t)) != OFFSET_TYPE + && TREE_CODE (TREE_TYPE (t)) != FUNCTION_TYPE + && TREE_CODE (TREE_TYPE (t)) != VOID_TYPE + && TYPE_SIZE (complete_type (TREE_TYPE (t))) != NULL_TREE); +} + +#define TYPE_PTRMEM_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE) +#define TYPE_PTR_P(NODE) \ + (TREE_CODE (NODE) == POINTER_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE) +#define TYPE_PTROB_P(NODE) \ + (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ + && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) + +static struct z_candidate * +build_builtin_candidate (candidates, fnname, type1, type2, + args, argtypes, flags) + struct z_candidate *candidates; + tree fnname, type1, type2, *args, *argtypes; + int flags; + +{ + tree t, convs; + int viable = 1, i; + struct z_candidate *cand; + tree types[2]; + + types[0] = type1; + types[1] = type2; + + convs = make_tree_vec (args[2] ? 3 : (args[1] ? 2 : 1)); + + for (i = 0; i < 2; ++i) + { + if (! args[i]) + break; + + t = implicit_conversion (types[i], argtypes[i], args[i], flags); + if (! t) + { + viable = 0; + /* We need something for printing the candidate. */ + t = build1 (IDENTITY_CONV, types[i], NULL_TREE); + } + TREE_VEC_ELT (convs, i) = t; + } + + /* For COND_EXPR we rearranged the arguments; undo that now. */ + if (args[2]) + { + TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1); + TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0); + t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); + if (t) + TREE_VEC_ELT (convs, 0) = t; + else + viable = 0; + } + + cand = (struct z_candidate *) oballoc (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; +} + +int +is_complete (t) + tree t; +{ + return TYPE_SIZE (complete_type (t)) != NULL_TREE; +} + +/* 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. */ + +static struct z_candidate * +add_builtin_candidate (candidates, code, code2, fnname, type1, type2, + args, argtypes, flags) + struct z_candidate *candidates; + enum tree_code code, code2; + tree fnname, type1, type2, *args, *argtypes; + int flags; +{ + switch (code) + { + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + args[1] = integer_zero_node; + type2 = integer_type_node; + } + + switch (code) + { + +/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, + and VQ is either volatile or empty, there exist candidate operator + functions of the form + VQ T& operator++(VQ T&); + T operator++(VQ T&, int); + 5 For every pair T, VQ), where T is an enumeration type or an arithmetic + type other than bool, and VQ is either volatile or empty, there exist + candidate operator functions of the form + VQ T& operator--(VQ T&); + T operator--(VQ T&, int); + 6 For every pair T, VQ), where T is a cv-qualified or cv-unqualified + complete object type, and VQ is either volatile or empty, there exist + candidate operator functions of the form + T*VQ& operator++(T*VQ&); + T*VQ& operator--(T*VQ&); + T* operator++(T*VQ&, int); + T* operator--(T*VQ&, int); */ + + case POSTDECREMENT_EXPR: + case PREDECREMENT_EXPR: + if (TREE_CODE (type1) == BOOLEAN_TYPE) + return candidates; + case POSTINCREMENT_EXPR: + case PREINCREMENT_EXPR: + if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE) + || ptr_complete_ob (type1)) + { + type1 = build_reference_type (type1); + break; + } + return candidates; + +/* 7 For every cv-qualified or cv-unqualified complete object type T, there + exist candidate operator functions of the form + + T& operator*(T*); + + 8 For every function type T, there exist candidate operator functions of + the form + T& operator*(T*); */ + + case INDIRECT_REF: + if (TREE_CODE (type1) == POINTER_TYPE + && (ptr_complete_ob (type1) + || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)) + break; + return candidates; + +/* 9 For every type T, there exist candidate operator functions of the form + T* operator+(T*); + + 10For every promoted arithmetic type T, there exist candidate operator + functions of the form + T operator+(T); + T operator-(T); */ + + case CONVERT_EXPR: /* unary + */ + if (TREE_CODE (type1) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE) + break; + case NEGATE_EXPR: + if (ARITHMETIC_TYPE_P (type1)) + break; + return candidates; + +/* 11For every promoted integral type T, there exist candidate operator + functions of the form + T operator~(T); */ + + case BIT_NOT_EXPR: + if (INTEGRAL_TYPE_P (type1)) + break; + return candidates; + +/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1 + is the same type as C2 or is a derived class of C2, T is a complete + object type or a function type, and CV1 and CV2 are cv-qualifier-seqs, + there exist candidate operator functions of the form + CV12 T& operator->*(CV1 C1*, CV2 T C2::*); + where CV12 is the union of CV1 and CV2. */ + + case MEMBER_REF: + if (TREE_CODE (type1) == POINTER_TYPE + && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))) + { + tree c1 = TREE_TYPE (type1); + tree c2 = (TYPE_PTRMEMFUNC_P (type2) + ? TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)) + : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2))); + + if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1) + && (TYPE_PTRMEMFUNC_P (type2) + || is_complete (TREE_TYPE (TREE_TYPE (type2))))) + break; + } + return candidates; + +/* 13For every pair of promoted arithmetic types L and R, there exist can- + didate operator functions of the form + LR operator*(L, R); + LR operator/(L, R); + LR operator+(L, R); + LR operator-(L, R); + bool operator<(L, R); + bool operator>(L, R); + bool operator<=(L, R); + bool operator>=(L, R); + bool operator==(L, R); + bool operator!=(L, R); + where LR is the result of the usual arithmetic conversions between + types L and R. + + 14For every pair of types T and I, where T is a cv-qualified or cv- + unqualified complete object type and I is a promoted integral type, + there exist candidate operator functions of the form + T* operator+(T*, I); + T& operator[](T*, I); + T* operator-(T*, I); + T* operator+(I, T*); + T& operator[](I, T*); + + 15For every T, where T is a pointer to complete object type, there exist + candidate operator functions of the form112) + ptrdiff_t operator-(T, T); + + 16For every pointer type T, there exist candidate operator functions of + the form + bool operator<(T, T); + bool operator>(T, T); + bool operator<=(T, T); + bool operator>=(T, T); + bool operator==(T, T); + bool operator!=(T, T); + + 17For every pointer to member type T, there exist candidate operator + functions of the form + bool operator==(T, T); + bool operator!=(T, T); */ + + case MINUS_EXPR: + if (ptr_complete_ob (type1) && ptr_complete_ob (type2)) + break; + if (ptr_complete_ob (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + return candidates; + + case EQ_EXPR: + case NE_EXPR: + if (TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2) + || TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) + break; + if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1)) + && null_ptr_cst_p (args[1])) + { + type2 = type1; + break; + } + if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)) + && null_ptr_cst_p (args[0])) + { + type1 = type2; + break; + } + 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)) + break; + if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1])) + { + type2 = type1; + break; + } + if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2)) + { + type1 = type2; + break; + } + return candidates; + + case PLUS_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + case ARRAY_REF: + if (INTEGRAL_TYPE_P (type1) && ptr_complete_ob (type2)) + { + type1 = ptrdiff_type_node; + break; + } + if (ptr_complete_ob (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + return candidates; + +/* 18For every pair of promoted integral types L and R, there exist candi- + date operator functions of the form + LR operator%(L, R); + LR operator&(L, R); + LR operator^(L, R); + LR operator|(L, R); + L operator<<(L, R); + L operator>>(L, R); + where LR is the result of the usual arithmetic conversions between + types L and R. */ + + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) + break; + return candidates; + +/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration + type, VQ is either volatile or empty, and R is a promoted arithmetic + type, there exist candidate operator functions of the form + VQ L& operator=(VQ L&, R); + VQ L& operator*=(VQ L&, R); + VQ L& operator/=(VQ L&, R); + VQ L& operator+=(VQ L&, R); + VQ L& operator-=(VQ L&, R); + + 20For every pair T, VQ), where T is any type and VQ is either volatile + or empty, there exist candidate operator functions of the form + T*VQ& operator=(T*VQ&, T*); + + 21For every pair T, VQ), where T is a pointer to member type and VQ is + either volatile or empty, there exist candidate operator functions of + the form + VQ T& operator=(VQ T&, T); + + 22For every triple T, VQ, I), where T is a cv-qualified or cv- + unqualified complete object type, VQ is either volatile or empty, and + I is a promoted integral type, there exist candidate operator func- + tions of the form + T*VQ& operator+=(T*VQ&, I); + T*VQ& operator-=(T*VQ&, I); + + 23For every triple L, VQ, R), where L is an integral or enumeration + type, VQ is either volatile or empty, and R is a promoted integral + type, there exist candidate operator functions of the form + + VQ L& operator%=(VQ L&, R); + VQ L& operator<<=(VQ L&, R); + VQ L& operator>>=(VQ L&, R); + VQ L& operator&=(VQ L&, R); + VQ L& operator^=(VQ L&, R); + VQ L& operator|=(VQ L&, R); */ + + case MODIFY_EXPR: + switch (code2) + { + case PLUS_EXPR: + case MINUS_EXPR: + if (ptr_complete_ob (type1) && INTEGRAL_TYPE_P (type2)) + { + type2 = ptrdiff_type_node; + break; + } + case MULT_EXPR: + case TRUNC_DIV_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + return candidates; + + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) + break; + return candidates; + + case NOP_EXPR: + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) + || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) + || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) + || ((TYPE_PTRMEMFUNC_P (type1) + || TREE_CODE (type1) == POINTER_TYPE) + && null_ptr_cst_p (args[1]))) + { + type2 = type1; + break; + } + return candidates; + + default: + my_friendly_abort (367); + } + type1 = build_reference_type (type1); + break; + + case COND_EXPR: + /* Kludge around broken overloading rules whereby + bool ? const char& : enum is ambiguous. */ + flags |= LOOKUP_NO_TEMP_BIND; + if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2) + break; + else if (TREE_CODE (type1) == ENUMERAL_TYPE + || TREE_CODE (type2) == ENUMERAL_TYPE) + return candidates; + if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) + break; + if (TREE_CODE (type1) == TREE_CODE (type2) + && (TREE_CODE (type1) == REFERENCE_TYPE + || TREE_CODE (type1) == POINTER_TYPE + || TYPE_PTRMEMFUNC_P (type1) + || IS_AGGR_TYPE (type1))) + break; + if (TREE_CODE (type1) == REFERENCE_TYPE + || TREE_CODE (type2) == REFERENCE_TYPE) + return candidates; + if (((TYPE_PTRMEMFUNC_P (type1) || TREE_CODE (type1) == POINTER_TYPE) + && null_ptr_cst_p (args[1])) + || IS_AGGR_TYPE (type1)) + { + type2 = type1; + break; + } + if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE) + && null_ptr_cst_p (args[0])) + || IS_AGGR_TYPE (type2)) + { + type1 = type2; + break; + } + return candidates; + + default: + my_friendly_abort (367); + } + + /* If we're dealing with two pointer types, we need candidates + for both of them. */ + if (type2 && 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))) + { + candidates = build_builtin_candidate + (candidates, fnname, type1, type1, args, argtypes, flags); + return build_builtin_candidate + (candidates, fnname, type2, type2, args, argtypes, flags); + } + + return build_builtin_candidate + (candidates, fnname, type1, type2, args, argtypes, flags); +} + +tree +type_decays_to (type) + tree type; +{ + if (TREE_CODE (type) == ARRAY_TYPE) + return build_pointer_type (TREE_TYPE (type)); + if (TREE_CODE (type) == FUNCTION_TYPE) + return build_pointer_type (type); + return type; +} + +/* There are three conditions of builtin candidates: + + 1) bool-taking candidates. These are the same regardless of the input. + 2) pointer-pair taking candidates. These are generated for each type + one of the input types converts to. + 3) arithmetic candidates. According to the WP, we should generate + all of these, but I'm trying not to... */ + +static struct z_candidate * +add_builtin_candidates (candidates, code, code2, fnname, args, flags) + struct z_candidate *candidates; + enum tree_code code, code2; + tree fnname, *args; + int flags; +{ + int ref1, i; + tree type, argtypes[3], types[2]; + + for (i = 0; i < 3; ++i) + { + if (args[i]) + argtypes[i] = cp_build_type_variant + (TREE_TYPE (args[i]), TREE_READONLY (args[i]), + TREE_THIS_VOLATILE (args[i])); + else + argtypes[i] = NULL_TREE; + } + + switch (code) + { +/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, + and VQ is either volatile or empty, there exist candidate operator + functions of the form + VQ T& operator++(VQ T&); */ + + case POSTINCREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case PREDECREMENT_EXPR: + case MODIFY_EXPR: + ref1 = 1; + break; + +/* 24There also exist candidate operator functions of the form + bool operator!(bool); + bool operator&&(bool, bool); + bool operator||(bool, bool); */ + + case TRUTH_NOT_EXPR: + return build_builtin_candidate + (candidates, fnname, boolean_type_node, + NULL_TREE, args, argtypes, flags); + + case TRUTH_ORIF_EXPR: + case TRUTH_ANDIF_EXPR: + return build_builtin_candidate + (candidates, fnname, boolean_type_node, + boolean_type_node, args, argtypes, flags); + + case ADDR_EXPR: + case COMPOUND_EXPR: + case COMPONENT_REF: + return candidates; + + default: + ref1 = 0; + } + + types[0] = types[1] = NULL_TREE; + + for (i = 0; i < 2; ++i) + { + if (! args[i]) + ; + else if (IS_AGGR_TYPE (argtypes[i])) + { + tree convs = lookup_conversions (argtypes[i]); + + if (code == COND_EXPR) + { + if (real_lvalue_p (args[i])) + types[i] = tree_cons + (NULL_TREE, build_reference_type (argtypes[i]), types[i]); + + types[i] = tree_cons + (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]); + } + + else if (! convs || (i == 0 && code == MODIFY_EXPR + && code2 == NOP_EXPR)) + return candidates; + + for (; convs; convs = TREE_CHAIN (convs)) + { + type = TREE_TYPE (TREE_TYPE (TREE_VALUE (convs))); + + if (i == 0 && ref1 + && (TREE_CODE (type) != REFERENCE_TYPE + || TYPE_READONLY (TREE_TYPE (type)))) + continue; + + if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE) + types[i] = tree_cons (NULL_TREE, type, types[i]); + + type = non_reference (type); + 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 (INTEGRAL_TYPE_P (type)) + type = type_promotes_to (type); + } + + if (! value_member (type, types[i])) + types[i] = tree_cons (NULL_TREE, type, types[i]); + } + } + else + { + if (code == COND_EXPR && real_lvalue_p (args[i])) + types[i] = tree_cons + (NULL_TREE, build_reference_type (argtypes[i]), types[i]); + type = non_reference (argtypes[i]); + 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 (INTEGRAL_TYPE_P (type)) + type = type_promotes_to (type); + } + types[i] = tree_cons (NULL_TREE, type, types[i]); + } + } + + for (; types[0]; types[0] = TREE_CHAIN (types[0])) + { + if (types[1]) + for (type = types[1]; type; type = TREE_CHAIN (type)) + candidates = add_builtin_candidate + (candidates, code, code2, fnname, TREE_VALUE (types[0]), + TREE_VALUE (type), args, argtypes, flags); + else + candidates = add_builtin_candidate + (candidates, code, code2, fnname, TREE_VALUE (types[0]), + NULL_TREE, args, argtypes, flags); + } + + return candidates; +} + +static struct z_candidate * +add_template_candidate (candidates, tmpl, arglist, flags) + struct z_candidate *candidates; + tree tmpl, arglist; + int flags; +{ + int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); + tree *targs = (tree *) alloca (sizeof (tree) * ntparms); + struct z_candidate *cand; + int i, dummy; + tree fn; + + i = type_unification (DECL_TEMPLATE_PARMS (tmpl), targs, + TYPE_ARG_TYPES (TREE_TYPE (tmpl)), + arglist, &dummy, 0, 0); + if (i != 0) + return candidates; + + fn = instantiate_template (tmpl, targs); + if (fn == error_mark_node) + return candidates; + + cand = add_function_candidate (candidates, fn, arglist, flags); + cand->template = DECL_TEMPLATE_INFO (fn); + return cand; +} + +static int +any_viable (cands) + struct z_candidate *cands; +{ + for (; cands; cands = cands->next) + if (cands->viable) + return 1; + return 0; +} + +static struct z_candidate * +splice_viable (cands) + struct z_candidate *cands; +{ + struct z_candidate **p = &cands; + + for (; *p; ) + { + if ((*p)->viable) + p = &((*p)->next); + else + *p = (*p)->next; + } + + return cands; +} + +tree +build_this (obj) + tree obj; +{ + /* Fix this to work on non-lvalues. */ + return build_unary_op (ADDR_EXPR, obj, 0); +} + +static void +print_z_candidates (candidates) + struct z_candidate *candidates; +{ + if (! candidates) + return; + + if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) + { + if (candidates->fn == ansi_opname [COND_EXPR]) + cp_error ("candidates are: %D(%T, %T, %T) <builtin>", candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); + else if (TREE_VEC_LENGTH (candidates->convs) == 2) + cp_error ("candidates are: %D(%T, %T) <builtin>", candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); + else + cp_error ("candidates are: %D(%T) <builtin>", candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); + } + else + cp_error_at ("candidates are: %D", candidates->fn); + candidates = candidates->next; + + for (; candidates; candidates = candidates->next) + { + if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) + { + if (candidates->fn == ansi_opname [COND_EXPR]) + cp_error (" %D(%T, %T, %T) <builtin>", + candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); + else if (TREE_VEC_LENGTH (candidates->convs) == 2) + cp_error (" %D(%T, %T) <builtin>", candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); + else + cp_error (" %D(%T) <builtin>", candidates->fn, + TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); + } + else + cp_error_at (" %D", candidates->fn); + } +} + +/* Returns the best overload candidate to perform the requested + conversion. */ + +static struct z_candidate * +build_user_type_conversion_1 (totype, expr, flags) + tree totype, expr; + int flags; +{ + struct z_candidate *candidates, *cand; + tree fromtype = TREE_TYPE (expr); + tree ctors = NULL_TREE, convs = NULL_TREE, *p; + tree args; + + if (IS_AGGR_TYPE (totype)) + ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); + if (IS_AGGR_TYPE (fromtype) + && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype))) + convs = lookup_conversions (fromtype); + + candidates = 0; + flags |= LOOKUP_NO_CONVERSION; + + if (ctors) + { + tree t = build_int_2 (0, 0); + TREE_TYPE (t) = build_pointer_type (totype); + args = build_tree_list (NULL_TREE, expr); + if (TYPE_USES_VIRTUAL_BASECLASSES (totype)) + args = tree_cons (NULL_TREE, integer_one_node, args); + args = tree_cons (NULL_TREE, t, args); + + ctors = TREE_VALUE (ctors); + } + for (; ctors; ctors = DECL_CHAIN (ctors)) + { + if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (ctors)) + continue; + + candidates = add_function_candidate (candidates, ctors, args, flags); + candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); + candidates->basetype_path = TYPE_BINFO (totype); + } + + if (convs) + args = build_tree_list (NULL_TREE, build_this (expr)); + + for (; convs; convs = TREE_CHAIN (convs)) + { + tree fn = TREE_VALUE (convs); + tree ics = implicit_conversion + (totype, TREE_TYPE (TREE_TYPE (fn)), 0, LOOKUP_NO_CONVERSION); + if (ics) + for (; fn; fn = DECL_CHAIN (fn)) + { + candidates = add_function_candidate (candidates, fn, args, flags); + candidates->second_conv = ics; + candidates->basetype_path = TREE_PURPOSE (convs); + } + } + + if (! any_viable (candidates)) + { +#if 0 + if (flags & LOOKUP_COMPLAIN) + { + if (candidates && ! candidates->next) + /* say why this one won't work or try to be loose */; + else + cp_error ("no viable candidates"); + } +#endif + + return 0; + } + + candidates = splice_viable (candidates); + cand = tourney (candidates, totype); + + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) + { + cp_error ("conversion from `%T' to `%T' is ambiguous", + fromtype, totype); + print_z_candidates (candidates); + } + + cand = candidates; /* any one will do */ + cand->second_conv = build1 (AMBIG_CONV, totype, expr); + ICS_USER_FLAG (cand->second_conv) = 1; + + return cand; + } + + for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) + p = &(TREE_OPERAND (*p, 0)); + + *p = build + (USER_CONV, + (DECL_CONSTRUCTOR_P (cand->fn) + ? totype : non_reference (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); + + if (cand) + { + if (TREE_CODE (cand->second_conv) == AMBIG_CONV) + return error_mark_node; + return convert_from_reference (convert_like (cand->second_conv, expr)); + } + return NULL_TREE; +} + +tree +build_new_function_call (fn, args, obj) + tree fn, args, obj; +{ + struct z_candidate *candidates = 0, *cand; + + if (obj == NULL_TREE && TREE_CODE (fn) == TREE_LIST) + { + tree t; + + for (t = args; t; t = TREE_CHAIN (t)) + if (TREE_VALUE (t) == error_mark_node) + return error_mark_node; + + for (t = TREE_VALUE (fn); t; t = DECL_CHAIN (t)) + { + if (TREE_CODE (t) == TEMPLATE_DECL) + candidates = add_template_candidate + (candidates, t, args, LOOKUP_NORMAL); + else + candidates = add_function_candidate + (candidates, t, args, LOOKUP_NORMAL); + } + + if (! any_viable (candidates)) + { + if (candidates && ! candidates->next) + return build_function_call (candidates->fn, args); + else + cp_error ("no matching function for call to `%D (%A)'", + TREE_PURPOSE (fn), args); + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates, NULL_TREE); + + if (cand == 0) + { + cp_error ("call of overloaded `%D (%A)' is ambiguous", + TREE_PURPOSE (fn), args); + print_z_candidates (candidates); + return error_mark_node; + } + + return build_over_call (cand->fn, cand->convs, args, LOOKUP_NORMAL); + } + + return build_function_call (fn, args); +} + +tree +build_object_call (obj, args) + tree obj, args; +{ + struct z_candidate *candidates = 0, *cand; + tree fns, convs, mem_args, *p; + enum tree_code code2 = NOP_EXPR; + tree type = TREE_TYPE (obj); + + fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 0); + + if (fns) + { + tree fn = TREE_VALUE (fns); + mem_args = tree_cons (NULL_TREE, build_this (obj), args); + + for (; fn; fn = DECL_CHAIN (fn)) + { + candidates = add_function_candidate + (candidates, fn, mem_args, LOOKUP_NORMAL); + candidates->basetype_path = TREE_PURPOSE (fns); + } + } + + convs = lookup_conversions (type); + + for (; convs; convs = TREE_CHAIN (convs)) + { + tree fn = TREE_VALUE (convs); + tree totype = TREE_TYPE (TREE_TYPE (fn)); + + if (TREE_CODE (totype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) + for (; fn; fn = DECL_CHAIN (fn)) + { + candidates = add_conv_candidate (candidates, fn, obj, args); + candidates->basetype_path = TREE_PURPOSE (convs); + } + } + + if (! any_viable (candidates)) + { + cp_error ("no match for call to `(%T) (%A)", TREE_TYPE (obj), args); + print_z_candidates (candidates); + return error_mark_node; + } + + candidates = splice_viable (candidates); + cand = tourney (candidates, NULL_TREE); + + if (cand == 0) + { + cp_error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args); + print_z_candidates (candidates); + return error_mark_node; + } + + if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR]) + return build_over_call (cand->fn, cand->convs, mem_args, LOOKUP_NORMAL); + + obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj); + + /* FIXME */ + return build_function_call (obj, args); +} + +static void +op_error (code, code2, arg1, arg2, arg3, problem) + enum tree_code code, code2; + tree arg1, arg2, arg3; + char *problem; +{ + char * opname + = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]); + + switch (code) + { + case COND_EXPR: + cp_error ("%s for `%T ? %T : %T'", problem, + TREE_TYPE (arg1), TREE_TYPE (arg2), TREE_TYPE (arg3)); + break; + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + cp_error ("%s for `%T%s'", problem, TREE_TYPE (arg1), opname); + break; + case ARRAY_REF: + cp_error ("%s for `%T[%T]'", problem, + TREE_TYPE (arg1), TREE_TYPE (arg2)); + break; + default: + if (arg2) + cp_error ("%s for `%T %s %T'", problem, + TREE_TYPE (arg1), opname, TREE_TYPE (arg2)); + else + cp_error ("%s for `%s%T'", problem, opname, TREE_TYPE (arg1)); + } +} + +tree +build_new_op (code, flags, arg1, arg2, arg3) + enum tree_code code; + int flags; + tree arg1, arg2, arg3; +{ + struct z_candidate *candidates = 0, *cand; + tree fns, mem_arglist, arglist, fnname, *p; + enum tree_code code2 = NOP_EXPR; + + if (arg1 == error_mark_node) + return error_mark_node; + + if (code == MODIFY_EXPR) + { + code2 = TREE_CODE (arg3); + arg3 = NULL_TREE; + fnname = ansi_assopname[code2]; + } + else + fnname = ansi_opname[code]; + + switch (code) + { + case NEW_EXPR: + case VEC_NEW_EXPR: + { + tree rval; + + arglist = tree_cons (NULL_TREE, arg2, arg3); + if (flags & LOOKUP_GLOBAL) + return build_new_function_call + (lookup_name_nonclass (fnname), arglist, NULL_TREE); + + /* FIXME */ + rval = build_method_call + (build_indirect_ref (build1 (NOP_EXPR, arg1, error_mark_node), + "new"), + fnname, arglist, NULL_TREE, flags); + if (rval == error_mark_node) + /* User might declare fancy operator new, but invoke it + like standard one. */ + return rval; + + TREE_TYPE (rval) = arg1; + TREE_CALLS_NEW (rval) = 1; + return rval; + } + + case VEC_DELETE_EXPR: + case DELETE_EXPR: + { + tree rval; + + if (flags & LOOKUP_GLOBAL) + return build_new_function_call + (lookup_name_nonclass (fnname), + build_tree_list (NULL_TREE, arg1), NULL_TREE); + + arglist = tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2)); + + arg1 = TREE_TYPE (arg1); + + /* This handles the case where we're trying to delete + X (*a)[10]; + a=new X[5][10]; + delete[] a; */ + + if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) + { + /* Strip off the pointer and the array. */ + arg1 = TREE_TYPE (TREE_TYPE (arg1)); + + while (TREE_CODE (arg1) == ARRAY_TYPE) + arg1 = (TREE_TYPE (arg1)); + + arg1 = build_pointer_type (arg1); + } + + /* FIXME */ + rval = build_method_call + (build_indirect_ref (build1 (NOP_EXPR, arg1, + error_mark_node), + NULL_PTR), + fnname, arglist, NULL_TREE, flags); +#if 0 + /* This can happen when operator delete is protected. */ + my_friendly_assert (rval != error_mark_node, 250); + TREE_TYPE (rval) = void_type_node; +#endif + return rval; + } + + case CALL_EXPR: + return build_object_call (arg1, arg2); + } + + /* The comma operator can have void args. */ + if (TREE_CODE (arg1) == OFFSET_REF) + arg1 = resolve_offset_ref (arg1); + if (arg2 && TREE_CODE (arg2) == OFFSET_REF) + arg2 = resolve_offset_ref (arg2); + if (arg3 && TREE_CODE (arg3) == OFFSET_REF) + arg3 = resolve_offset_ref (arg3); + + if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) + && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))) + && (! arg3 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3)))) + goto builtin; + + if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) + arg2 = integer_zero_node; + + fns = lookup_name_nonclass (fnname); + /* + Koenig lookup */ + + if (arg2 && arg3) + arglist = tree_cons (NULL_TREE, arg1, tree_cons + (NULL_TREE, arg2, build_tree_list (NULL_TREE, arg3))); + else if (arg2) + arglist = tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2)); + else + arglist = build_tree_list (NULL_TREE, arg1); + + if (fns && TREE_CODE (fns) == TREE_LIST) + fns = TREE_VALUE (fns); + for (; fns; fns = DECL_CHAIN (fns)) + { + if (TREE_CODE (fns) == TEMPLATE_DECL) + candidates = add_template_candidate (candidates, fns, arglist, flags); + else + candidates = add_function_candidate (candidates, fns, arglist, flags); + } + + if (IS_AGGR_TYPE (TREE_TYPE (arg1))) + fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 0); + else + fns = NULL_TREE; + + if (fns) + { + tree fn = TREE_VALUE (fns); + mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist)); + for (; fn; fn = DECL_CHAIN (fn)) + { + if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + candidates = add_function_candidate + (candidates, fn, mem_arglist, flags); + else + candidates = add_function_candidate (candidates, fn, arglist, flags); + + candidates->basetype_path = TREE_PURPOSE (fns); + } + } + + { + tree args[3]; + + /* Rearrange the arguments for ?: so that add_builtin_candidate only has + to know about two args; a builtin candidate will always have a first + parameter of type bool. We'll handle that in + build_builtin_candidate. */ + if (code == COND_EXPR) + { + args[0] = arg2; + args[1] = arg3; + args[2] = arg1; + } + else + { + args[0] = arg1; + args[1] = arg2; + args[2] = NULL_TREE; + } + + candidates = add_builtin_candidates + (candidates, code, code2, fnname, args, flags); + } + + if (! any_viable (candidates)) + { + switch (code) + { + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* Look for an `operator++ (int)'. If they didn't have + one, then we fall back to the old way of doing things. */ + if (flags & LOOKUP_COMPLAIN) + cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead", + fnname, opname_tab [code]); + if (code == POSTINCREMENT_EXPR) + code = PREINCREMENT_EXPR; + else + code = PREDECREMENT_EXPR; + return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE); + + /* The caller will deal with these. */ + case ADDR_EXPR: + case COMPOUND_EXPR: + case COMPONENT_REF: + return NULL_TREE; + } + if (flags & LOOKUP_COMPLAIN) + { + op_error (code, code2, arg1, arg2, arg3, "no match"); + print_z_candidates (candidates); + } + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates, NULL_TREE); + + if (cand == 0) + { + if (flags & LOOKUP_COMPLAIN) + { + op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); + print_z_candidates (candidates); + } + return error_mark_node; + } + + if (TREE_CODE (cand->fn) == FUNCTION_DECL) + { + extern int warn_synth; + if (warn_synth + && fnname == ansi_opname[MODIFY_EXPR] + && DECL_ARTIFICIAL (cand->fn) + && candidates->next + && ! candidates->next->next) + { + cp_warning ("using synthesized `%#D' for copy assignment", + cand->fn); + cp_warning_at (" where cfront would use `%#D'", + cand == candidates + ? candidates->next->fn + : candidates->fn); + } + + if (DECL_FUNCTION_MEMBER_P (cand->fn)) + enforce_access (cand->basetype_path, cand->fn); + + return build_over_call + (cand->fn, cand->convs, + TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE + ? mem_arglist : arglist, + LOOKUP_NORMAL); + } + + arg1 = convert_from_reference + (convert_like (TREE_VEC_ELT (cand->convs, 0), arg1)); + if (arg2) + arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2); + if (arg3) + arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3); + +builtin: + switch (code) + { + case MODIFY_EXPR: + return build_modify_expr (arg1, code2, arg2); + + case INDIRECT_REF: + return build_indirect_ref (arg1, "unary *"); + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case TRUNC_MOD_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + return build_binary_op_nodefault (code, arg1, arg2, code); + + case CONVERT_EXPR: + case NEGATE_EXPR: + case BIT_NOT_EXPR: + case TRUTH_NOT_EXPR: + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + return build_unary_op (code, arg1, candidates != 0); + + case ARRAY_REF: + return build_array_ref (arg1, arg2); + + case COND_EXPR: + return build_conditional_expr (arg1, arg2, arg3); + + case MEMBER_REF: + return build_m_component_ref + (build_indirect_ref (arg1, NULL_PTR), arg2); + + /* The caller will deal with these. */ + case ADDR_EXPR: + case COMPONENT_REF: + case COMPOUND_EXPR: + return NULL_TREE; + + default: + my_friendly_abort (367); + } +} + +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 ("`%+#D' is %s", function, + TREE_PRIVATE (function) ? "private" + : "from private base class"); + error ("within this context"); + } + else if (access == access_protected_node) + { + cp_error_at ("`%+#D' %s", function, + TREE_PROTECTED (function) ? "is protected" + : "has protected accessibility"); + error ("within this context"); + } +} + +/* Perform the conversions in CONVS on the expression EXPR. */ + +static tree +convert_like (convs, expr) + tree convs, expr; +{ + switch (TREE_CODE (convs)) + { + case USER_CONV: + { + tree fn = TREE_OPERAND (convs, 1); + tree args; + enforce_access (TREE_OPERAND (convs, 3), fn); + + if (DECL_CONSTRUCTOR_P (fn)) + { + tree t = build_int_2 (0, 0); + TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); + + args = build_tree_list (NULL_TREE, expr); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + args = tree_cons (NULL_TREE, integer_one_node, args); + args = tree_cons (NULL_TREE, t, args); + } + else + args = build_this (expr); + expr = build_over_call + (TREE_OPERAND (convs, 1), TREE_OPERAND (convs, 2), + args, LOOKUP_NORMAL); + + /* If this is a constructor or a function returning an aggr type, + we need to build up a TARGET_EXPR. */ + if (DECL_CONSTRUCTOR_P (fn)) + expr = build_cplus_new (TREE_TYPE (convs), expr); + + return expr; + } + case IDENTITY_CONV: + if (type_unknown_p (expr)) + expr = instantiate_type (TREE_TYPE (convs), expr, 1); + return expr; + case AMBIG_CONV: + /* Call build_user_type_conversion again for the error. */ + return build_user_type_conversion + (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL); + }; + + expr = convert_like (TREE_OPERAND (convs, 0), expr); + if (expr == error_mark_node) + return error_mark_node; + + switch (TREE_CODE (convs)) + { + case BASE_CONV: + case RVALUE_CONV: + return build_user_type_conversion + (TREE_TYPE (convs), expr, LOOKUP_NORMAL); + case REF_BIND: + return convert_to_reference + (TREE_TYPE (convs), expr, + CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION|INDIRECT_BIND, + error_mark_node); + case LVALUE_CONV: + return decay_conversion (expr); + } + return cp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT, + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); +} + +static tree +convert_default_arg (type, arg) + tree type, arg; +{ + arg = break_out_target_exprs (arg); + + if (TREE_CODE (arg) == CONSTRUCTOR) + { + arg = digest_init (type, arg, 0); + arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, + "default argument", 0, 0); + } + else + { + /* This could get clobbered by the following call. */ + if (TREE_HAS_CONSTRUCTOR (arg)) + arg = copy_node (arg); + + arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, + "default argument", 0, 0); +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + arg = default_conversion (arg); +#endif + } + + return arg; +} + +static tree +build_over_call (fn, convs, args, flags) + tree fn, convs, args; + int flags; +{ + tree converted_args = NULL_TREE; + tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); + tree conv, arg, val; + int i = 0; + + if (args && TREE_CODE (args) != TREE_LIST) + args = build_tree_list (NULL_TREE, args); + arg = args; + + /* The implicit parameters to a constructor are not considered by overload + resolution, and must be of the proper type. */ + if (DECL_CONSTRUCTOR_P (fn)) + { + converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) + { + converted_args = tree_cons + (NULL_TREE, TREE_VALUE (arg), converted_args); + arg = TREE_CHAIN (arg); + parm = TREE_CHAIN (parm); + } + } + /* Bypass access control for 'this' parameter. */ + else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) + { + converted_args = tree_cons + (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST), + converted_args); + parm = TREE_CHAIN (parm); + arg = TREE_CHAIN (arg); + ++i; + } + + for (; conv = TREE_VEC_ELT (convs, i), arg && parm; + parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i) + { + tree type = TREE_VALUE (parm); + val = convert_like (conv, TREE_VALUE (arg)); + +#ifdef PROMOTE_PROTOTYPES + if ((TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE) + && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) + val = default_conversion (val); +#endif + converted_args = tree_cons (NULL_TREE, val, converted_args); + } + + /* Default arguments */ + for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm)) + converted_args = tree_cons + (NULL_TREE, + convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm)), + converted_args); + + /* Ellipsis */ + for (; arg; arg = TREE_CHAIN (arg)) + { + val = TREE_VALUE (arg); + + if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE + && (TYPE_PRECISION (TREE_TYPE (val)) + < TYPE_PRECISION (double_type_node))) + /* Convert `float' to `double'. */ + val = convert (double_type_node, val); + else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val)) + && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val))) + cp_warning ("cannot pass objects of type `%T' through `...'", + TREE_TYPE (val)); + else + /* Convert `short' and `char' to full-size `int'. */ + val = default_conversion (val); + + converted_args = tree_cons (NULL_TREE, val, converted_args); + } + + converted_args = nreverse (converted_args); + + mark_used (fn); + /* Is it a synthesized method that needs to be synthesized? */ + if (DECL_ARTIFICIAL (fn) && ! DECL_INITIAL (fn) + && DECL_CLASS_CONTEXT (fn) + /* Kludge: don't synthesize for default args. */ + && current_function_decl) + synthesize_method (fn); + + if (pedantic && DECL_THIS_INLINE (fn) && ! DECL_ARTIFICIAL (fn) + && ! DECL_INITIAL (fn) && ! DECL_PENDING_INLINE_INFO (fn) + && ! (DECL_TEMPLATE_INFO (fn) + && TREE_LANG_FLAG_0 (DECL_TEMPLATE_INFO (fn)))) + cp_warning ("inline function `%#D' called before definition", fn); + + if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0) + { + tree t, *p = &TREE_VALUE (converted_args); + tree binfo = get_binfo + (DECL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0); + *p = convert_pointer_to_real (binfo, *p); + if (TREE_SIDE_EFFECTS (*p)) + *p = save_expr (*p); + t = build_pointer_type (TREE_TYPE (fn)); + fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn)); + TREE_TYPE (fn) = t; + } + else if (DECL_INLINE (fn)) + fn = inline_conversion (fn); + else + fn = build_addr_func (fn); + + fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args); + if (TREE_TYPE (fn) == void_type_node) + return fn; + if (IS_AGGR_TYPE (TREE_TYPE (fn))) + fn = build_cplus_new (TREE_TYPE (fn), fn); + return convert_from_reference (require_complete_type (fn)); +} + +tree +build_new_method_call (instance, name, args, basetype_path, flags) + tree instance, name, args, basetype_path; + int flags; +{ + struct z_candidate *candidates = 0, *cand; + tree basetype, mem_args, fns, instance_ptr; + tree pretty_name; + + if (instance == NULL_TREE) + basetype = BINFO_TYPE (basetype_path); + else + { + if (TREE_CODE (instance) == OFFSET_REF) + instance = resolve_offset_ref (instance); + if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) + instance = convert_from_reference (instance); + basetype = TREE_TYPE (instance); + + /* XXX this should be handled before we get here. */ + if (! IS_AGGR_TYPE (basetype)) + { + if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node) + cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", + name, instance, basetype); + + return error_mark_node; + } + } + + if (basetype_path == NULL_TREE) + basetype_path = TYPE_BINFO (basetype); + + if (instance) + { + instance_ptr = build_this (instance); + + /* XXX this should be handled before we get here. */ + fns = build_field_call (basetype_path, instance_ptr, name, args); + if (fns) + return fns; + } + else + { + instance_ptr = build_int_2 (0, 0); + TREE_TYPE (instance_ptr) = build_pointer_type (basetype); + } + + pretty_name = + (name == ctor_identifier ? constructor_name_full (basetype) : name); + + fns = lookup_fnfields (basetype_path, name, 1); + + if (fns == error_mark_node) + return error_mark_node; + if (fns) + { + tree t = TREE_VALUE (fns); + if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype) + && ! (flags & LOOKUP_HAS_IN_CHARGE)) + { + flags |= LOOKUP_HAS_IN_CHARGE; + args = tree_cons (NULL_TREE, integer_one_node, args); + } + mem_args = tree_cons (NULL_TREE, instance_ptr, args); + for (; t; t = DECL_CHAIN (t)) + { + /* XXX copy-init should go through build_user_type_conversion. */ + if (name == ctor_identifier + && (flags & LOOKUP_ONLYCONVERTING) + && DECL_NONCONVERTING_P (t)) + continue; + if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE) + candidates = add_function_candidate + (candidates, t, mem_args, flags); + else + candidates = add_function_candidate (candidates, t, args, flags); + candidates->basetype_path = TREE_PURPOSE (fns); + } + } + + if (! any_viable (candidates)) + { + /* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */ + if (flags & LOOKUP_SPECULATIVELY) + return NULL_TREE; + cp_error ("no matching function for call to `%T::%D (%A)%V'", basetype, + pretty_name, args, TREE_TYPE (TREE_TYPE (instance_ptr))); + print_z_candidates (candidates); + return error_mark_node; + } + candidates = splice_viable (candidates); + cand = tourney (candidates, NULL_TREE); + + if (cand == 0) + { + cp_error ("call of overloaded `%D(%A)' is ambiguous"); + print_z_candidates (candidates); + 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) + && ! (flags & LOOKUP_NONVIRTUAL) + && value_member (cand->fn, get_abstract_virtuals (basetype))) + cp_error ("abstract virtual `%#D' called from constructor", cand->fn); + if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE + && TREE_CODE (instance_ptr) == NOP_EXPR + && TREE_OPERAND (instance_ptr, 0) == error_mark_node) + cp_error ("cannot call member function `%D' without object", cand->fn); + + if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL) + && ((instance == current_class_ref && (dtor_label || ctor_label)) + || resolves_to_fixed_type_p (instance, 0))) + flags |= LOOKUP_NONVIRTUAL; + + return build_over_call + (cand->fn, cand->convs, + TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args, + flags); +} + +/* Compare two implicit conversion sequences that differ only in their + qualification conversion. Subroutine of compare_ics. */ + +static int +compare_qual (ics1, ics2) + tree ics1, ics2; +{ + tree to1 = TREE_TYPE (ics1); + tree to2 = TREE_TYPE (ics2); + + to1 = TREE_TYPE (to1); + to2 = TREE_TYPE (to2); + + if (TREE_CODE (to1) == OFFSET_TYPE) + { + to1 = TREE_TYPE (to1); + to2 = TREE_TYPE (to2); + } + + 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; +} + +/* 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 main1, main2; + + if (ICS_RANK (ics1) > ICS_RANK (ics2)) + return -1; + else if (ICS_RANK (ics1) < ICS_RANK (ics2)) + return 1; + + /* User-defined conversion sequence U1 is a better conversion sequence + than another user-defined conversion sequence U2 if they contain the + same user-defined conversion operator or constructor and if the sec- + ond standard conversion sequence of U1 is better than the second + standard conversion sequence of U2. */ + + if (ICS_RANK (ics1) == USER_RANK) + { + tree t1, t2; + + for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0)) + if (TREE_CODE (t1) == AMBIG_CONV) + return 0; + for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0)) + if (TREE_CODE (t2) == AMBIG_CONV) + return 0; + + if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) + 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 */ + } + +#if 0 /* Handled by ranking */ + /* 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. */ +#endif + + if (TREE_CODE (ics1) == QUAL_CONV) + main1 = TREE_OPERAND (ics1, 0); + else + main1 = ics1; + + if (TREE_CODE (ics2) == QUAL_CONV) + main2 = TREE_OPERAND (ics2, 0); + else + main2 = ics2; + + if (TREE_CODE (main1) != TREE_CODE (main2)) + return 0; + + if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV + || 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 (TYPE_PTRMEMFUNC_FN_TYPE (to1)); + from1 = TYPE_METHOD_BASETYPE (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) + { + to1 = TYPE_OFFSET_BASETYPE (to1); + from1 = TYPE_OFFSET_BASETYPE (from1); + } + } + + if (TYPE_PTRMEMFUNC_P (to2)) + { + to2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2)); + from2 = TYPE_METHOD_BASETYPE (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) + { + to2 = TYPE_OFFSET_BASETYPE (to2); + from2 = TYPE_OFFSET_BASETYPE (from2); + } + } + + if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2))) + return 0; + + /* The sense of pmem conversions is reversed from that of the other + conversions. */ + if (TREE_CODE (main1) == PMEM_CONV) + { + tree t = from1; from1 = from2; from2 = t; + t = to1; to1 = to2; to2 = t; + } + + distf = get_base_distance (from1, from2, 0, 0); + if (distf == -1) + { + distf = -get_base_distance (from2, from1, 0, 0); + if (distf == 1) + return 0; + } + + /* If class B is derived directly or indirectly from class A, + conver- sion 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 (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE) + { + if (distf > 0) + return 1; + else if (distf < 0) + return -1; + } + else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1) + && get_base_distance (to1, from1, 0, 0) != -1) + return 1; + else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2) + && get_base_distance (to2, from2, 0, 0) != -1) + 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 (distt == 1) + return 0; + } + + /* --conversion of C* to B* is better than conversion of C* to A*, */ + if (distf == 0) + { + if (distt > 0) + return -1; + else if (distt < 0) + return 1; + } + /* --conversion of B* to A* is better than conversion of C* to A*, */ + else if (distt == 0) + { + if (distf > 0) + return 1; + else if (distf < 0) + return -1; + } + } + else if (TREE_CODE (TREE_TYPE (main1)) == POINTER_TYPE + || TYPE_PTRMEMFUNC_P (TREE_TYPE (main1))) + { + if (TREE_TYPE (main1) == TREE_TYPE (main2)) + return compare_qual (ics1, ics2); + +#if 0 /* This is now handled by making identity better than anything else. */ + /* existing practice, not WP-endorsed: const char * -> const char * + is better than char * -> const char *. (jason 6/29/96) */ + if (TREE_TYPE (ics1) == TREE_TYPE (ics2)) + return -compare_qual (main1, main2); +#endif + } + + 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 */ + +static int +joust (cand1, cand2) + struct z_candidate *cand1, *cand2; +{ + int winner = 0; + int i, off1 = 0, off2 = 0, len; + + /* 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 comparing static and non-static member functions, we ignore the + implicit object parameter of the non-static function. The WP says to + pretend that the static function has an object parm, but that won't + work with operator overloading. */ + len = TREE_VEC_LENGTH (cand1->convs); + if (len != TREE_VEC_LENGTH (cand2->convs)) + { + if (DECL_STATIC_FUNCTION_P (cand1->fn) + && ! DECL_STATIC_FUNCTION_P (cand2->fn)) + off2 = 1; + else if (! DECL_STATIC_FUNCTION_P (cand1->fn) + && DECL_STATIC_FUNCTION_P (cand2->fn)) + { + off1 = 1; + --len; + } + else + my_friendly_abort (42); + } + + for (i = 0; i < len; ++i) + { + int comp = compare_ics (TREE_VEC_ELT (cand1->convs, i+off1), + TREE_VEC_ELT (cand2->convs, i+off2)); + + if (comp != 0) + { + if (winner && comp != winner) + return 0; + winner = comp; + } + } + + 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; + else if (cand1->template && cand2->template) + winner = more_specialized + (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template)); + + /* 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 (! winner && cand1->second_conv) + winner = compare_ics (cand1->second_conv, cand2->second_conv); + + /* If the built-in candidates are the same, arbitrarily pick one. */ + if (! winner && cand1->fn == cand2->fn + && TREE_CODE (cand1->fn) == IDENTIFIER_NODE) + { + for (i = 0; i < TREE_VEC_LENGTH (cand1->convs); ++i) + if (! comptypes (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)), + TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)), 1)) + break; + if (i == TREE_VEC_LENGTH (cand1->convs)) + return 1; + /* Kludge around broken overloading rules whereby + bool ? void *const & : void *const & is ambiguous. */ + if (cand1->fn == ansi_opname[COND_EXPR]) + { + tree c1 = TREE_VEC_ELT (cand1->convs, 1); + tree c2 = TREE_VEC_ELT (cand2->convs, 1); + tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1))); + tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2))); + + if (comptypes (t1, t2, 1)) + { + if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND) + return 1; + if (TREE_CODE (c1) != REF_BIND && TREE_CODE (c2) == REF_BIND) + return -1; + } + } + } + + 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. */ + +static struct z_candidate * +tourney (candidates) + struct z_candidate *candidates; +{ + struct z_candidate *champ = candidates, *challenger; + int fate; + + /* 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; ) + { + fate = joust (champ, challenger); + if (fate == 1) + challenger = challenger->next; + else + { + if (fate == 0) + { + champ = challenger->next; + if (champ == 0) + return 0; + } + else + champ = challenger; + + challenger = champ->next; + } + } + + /* 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) + { + fate = joust (champ, challenger); + if (fate != 1) + return 0; + } + + return champ; +} diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 01d59247b8c..676b1363326 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4841,6 +4841,8 @@ instantiate_type (lhstype, rhs, complain) if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs))) return rhs; + rhs = copy_node (rhs); + /* This should really only be used when attempting to distinguish what sort of a pointer to function we have. For now, any arithmetic operation which is not supported on pointers @@ -5246,6 +5248,12 @@ instantiate_type (lhstype, rhs, complain) TREE_TYPE (rhs) = lhstype; TREE_OPERAND (rhs, 0) = fn; TREE_CONSTANT (rhs) = staticp (fn); + if (TREE_CODE (lhstype) == POINTER_TYPE && + TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE) + { + build_ptrmemfunc_type (lhstype); + rhs = build_ptrmemfunc (lhstype, rhs, 0); + } } return rhs; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7f6fd805006..19d98689091 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -295,6 +295,11 @@ extern int flag_elide_constructors; extern int flag_ansi; +/* Nonzero means do argument matching for overloading according to the + ANSI rules, rather than what g++ used to believe to be correct. */ + +extern int flag_ansi_overloading; + /* Nonzero means recognize and handle signature language constructs. */ extern int flag_handle_signatures; @@ -1841,7 +1846,8 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ before LOOKUP_SPECULATIVELY is checked. LOOKUP_NO_CONVERSION means that user-defined conversions are not permitted. Built-in conversions are permitted. - LOOKUP_DESTRUCTOR means explicit call to destructor. */ + LOOKUP_DESTRUCTOR means explicit call to destructor. + LOOKUP_NO_TEMP_BIND means temporaries will not be bound to references. */ #define LOOKUP_PROTECT (1) #define LOOKUP_COMPLAIN (2) @@ -1855,6 +1861,7 @@ extern tree current_class_type; /* _TYPE: the type of the current class */ #define INDIRECT_BIND (256) #define LOOKUP_NO_CONVERSION (512) #define LOOKUP_DESTRUCTOR (512) +#define LOOKUP_NO_TEMP_BIND (1024) /* These flags are used by the conversion code. CONV_IMPLICIT : Perform implicit conversions (standard and user-defined). @@ -1935,6 +1942,9 @@ extern tree build_scoped_method_call PROTO((tree, tree, tree, tree)); extern tree build_method_call PROTO((tree, tree, tree, tree, int)); extern tree build_overload_call_real PROTO((tree, tree, int, struct candidate *, int)); extern tree build_overload_call PROTO((tree, tree, int)); +extern tree build_new_method_call PROTO((tree, tree, tree, tree, int)); +extern tree build_new_function_call PROTO((tree, tree, tree)); +extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree)); /* in class.c */ extern tree build_vbase_pointer PROTO((tree, tree)); @@ -2057,6 +2067,7 @@ extern tree start_method PROTO((tree, tree, tree)); extern tree finish_method PROTO((tree)); extern void hack_incomplete_structures PROTO((tree)); extern tree maybe_build_cleanup PROTO((tree)); +extern tree maybe_build_cleanup_and_delete PROTO((tree)); extern void cplus_expand_expr_stmt PROTO((tree)); extern void finish_stmt PROTO((void)); extern void pop_implicit_try_blocks PROTO((tree)); @@ -2096,6 +2107,7 @@ extern void finish_builtin_type PROTO((tree, char *, tree *, int, tree)); extern tree coerce_new_type PROTO((tree)); extern tree coerce_delete_type PROTO((tree)); extern void import_export_vtable PROTO((tree, tree, int)); +extern int finish_prevtable_vardecl PROTO((tree, tree)); extern int walk_vtables PROTO((void (*)(), int (*)())); extern void walk_sigtables PROTO((void (*)(), void (*)())); extern void finish_file PROTO((void)); @@ -2330,6 +2342,7 @@ extern void init_search_processing PROTO((void)); extern void reinit_search_statistics PROTO((void)); extern tree current_scope PROTO((void)); extern tree lookup_conversions PROTO((tree)); +extern tree get_template_base PROTO((tree, tree)); /* in sig.c */ extern tree build_signature_pointer_type PROTO((tree, int, int)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index a4c68e2180b..f92eb1de9eb 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -231,8 +231,6 @@ cp_convert_to_pointer (type, expr) if (integer_zerop (expr)) { - if (type == TREE_TYPE (null_pointer_node)) - return null_pointer_node; expr = build_int_2 (0, 0); TREE_TYPE (expr) = type; return expr; @@ -270,8 +268,6 @@ convert_to_pointer_force (type, expr) if (integer_zerop (expr)) { - if (type == TREE_TYPE (null_pointer_node)) - return null_pointer_node; expr = build_int_2 (0, 0); TREE_TYPE (expr) = type; return expr; @@ -549,7 +545,7 @@ build_up_reference (type, arg, flags, checkconst) case COMPOUND_EXPR: { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1), - LOOKUP_PROTECT, checkconst); + flags, checkconst); rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1)); return rval; @@ -561,7 +557,7 @@ build_up_reference (type, arg, flags, checkconst) case INIT_EXPR: { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0), - LOOKUP_PROTECT, checkconst); + flags, checkconst); rval = build (COMPOUND_EXPR, type, arg, real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0)); return rval; @@ -571,9 +567,9 @@ build_up_reference (type, arg, flags, checkconst) return build (COND_EXPR, type, TREE_OPERAND (targ, 0), build_up_reference (type, TREE_OPERAND (targ, 1), - LOOKUP_PROTECT, checkconst), + flags, checkconst), build_up_reference (type, TREE_OPERAND (targ, 2), - LOOKUP_PROTECT, checkconst)); + flags, checkconst)); /* Undo the folding... */ case MIN_EXPR: @@ -583,9 +579,9 @@ build_up_reference (type, arg, flags, checkconst) boolean_type_node, TREE_OPERAND (targ, 0), TREE_OPERAND (targ, 1)), build_up_reference (type, TREE_OPERAND (targ, 0), - LOOKUP_PROTECT, checkconst), + flags, checkconst), build_up_reference (type, TREE_OPERAND (targ, 1), - LOOKUP_PROTECT, checkconst)); + flags, checkconst)); case BIND_EXPR: arg = TREE_OPERAND (targ, 1); @@ -716,12 +712,11 @@ convert_to_reference (reftype, expr, convtype, flags, decl) { /* Look for a user-defined conversion to lvalue that we can use. */ -#ifdef NEW_OVER - rval_as_conversion - = build_type_conversion (CONVERT_EXPR, reftype, expr, 1); -#else - rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1); -#endif + if (flag_ansi_overloading) + rval_as_conversion + = build_type_conversion (CONVERT_EXPR, reftype, expr, 1); + else + rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1); if (rval_as_conversion && rval_as_conversion != error_mark_node && real_lvalue_p (rval_as_conversion)) @@ -1340,11 +1335,8 @@ cp_convert (type, expr, convtype, flags) return conversion; } -#ifndef NEW_OVER - if (TYPE_HAS_CONSTRUCTOR (complete_type (type))) -#else - if (TYPE_HAS_CONSTRUCTOR (complete_type (type)) && ! conversion) -#endif + if (TYPE_HAS_CONSTRUCTOR (complete_type (type)) + && (! flag_ansi_overloading || ! conversion)) ctor = build_method_call (NULL_TREE, ctor_identifier, build_tree_list (NULL_TREE, e), TYPE_BINFO (type), @@ -1504,16 +1496,16 @@ build_type_conversion (code, xtype, expr, for_sure) tree xtype, expr; int for_sure; { -#ifdef NEW_OVER - return build_user_type_conversion - (xtype, expr, for_sure ? LOOKUP_NORMAL : 0); -#else /* C++: check to see if we can convert this aggregate type into the required type. */ tree basetype; tree conv; tree winner = NULL_TREE; + if (flag_ansi_overloading) + return build_user_type_conversion + (xtype, expr, for_sure ? LOOKUP_NORMAL : 0); + if (expr == error_mark_node) return error_mark_node; @@ -1564,7 +1556,6 @@ build_type_conversion (code, xtype, expr, for_sure) DECL_NAME (winner), for_sure); return NULL_TREE; -#endif } /* Convert the given EXPR to one of a group of types suitable for use in an @@ -1852,2425 +1843,3 @@ type_promotes_to (type) return cp_build_type_variant (type, constp, volatilep); } - -/* Work in progress. Ask jason before removing. */ - -struct z_candidate { - tree fn; - tree convs; - tree second_conv; - int viable; - tree basetype_path; - tree template; - struct z_candidate *next; -}; - -#define IDENTITY_RANK 0 -#define EXACT_RANK 1 -#define PROMO_RANK 2 -#define STD_RANK 3 -#define PBOOL_RANK 4 -#define USER_RANK 5 -#define ELLIPSIS_RANK 6 - -#define ICS_RANK(NODE) \ - (ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \ - : ICS_USER_FLAG (NODE) ? USER_RANK \ - : ICS_STD_RANK (NODE)) - -#define ICS_STD_RANK(NODE) TREE_COMPLEXITY (NODE) - -#define ICS_USER_FLAG(NODE) TREE_LANG_FLAG_0 (NODE) -#define ICS_ELLIPSIS_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) - -#define USER_CONV_FN(NODE) TREE_OPERAND (NODE, 1) - -static struct z_candidate * build_user_type_conversion_1 (); -static tree convert_like (); -static tree build_over_call (); -static struct z_candidate * tourney (); -static void enforce_access (); - -int -null_ptr_cst (t) - tree t; -{ - return (INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)); -} - -tree -build_conv (code, type, from) - enum tree_code code; - tree type, from; -{ - tree t = build1 (code, type, from); - int rank = ICS_STD_RANK (from); - switch (code) - { - case PTR_CONV: - case PMEM_CONV: - case BASE_CONV: - case STD_CONV: - if (rank < STD_RANK) - rank = STD_RANK; - break; - - case LVALUE_CONV: - case QUAL_CONV: - case RVALUE_CONV: - if (rank < EXACT_RANK) - rank = EXACT_RANK; - - default: - break; - } - ICS_STD_RANK (t) = rank; - ICS_USER_FLAG (t) = ICS_USER_FLAG (from); - return t; -} - -tree -non_reference (t) - tree t; -{ - if (TREE_CODE (t) == REFERENCE_TYPE) - t = TREE_TYPE (t); - return t; -} - -/* Returns the standard conversion path (see [conv]) from type FROM to type - TO, if any. For proper handling of null pointer constants, you must - also pass the expression EXPR to convert from. */ - -tree -standard_conversion (to, from, expr) - tree to, from, expr; -{ - enum tree_code fcode, tcode; - tree conv; - - fcode = TREE_CODE (from); - tcode = TREE_CODE (to); - - conv = build1 (IDENTITY_CONV, from, expr); - - if (from == to) - return conv; - - if (fcode == FUNCTION_TYPE) - { - from = build_pointer_type (from); - fcode = TREE_CODE (from); - conv = build_conv (LVALUE_CONV, from, conv); - } - else if (fcode == ARRAY_TYPE) - { - from = build_pointer_type (TREE_TYPE (from)); - fcode = TREE_CODE (from); - conv = build_conv (LVALUE_CONV, from, conv); - } - - if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to)) - && expr && null_ptr_cst (expr)) - { - conv = build_conv (STD_CONV, to, conv); - } - else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE) - { - enum tree_code ufcode = TREE_CODE (TREE_TYPE (from)); - enum tree_code utcode = TREE_CODE (TREE_TYPE (to)); - - if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (from)), - TYPE_MAIN_VARIANT (TREE_TYPE (to)), 1)) - /* OK for now */; - else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE - && ufcode != FUNCTION_TYPE) - { - from = build_pointer_type - (cp_build_type_variant (void_type_node, - TYPE_READONLY (TREE_TYPE (from)), - TYPE_VOLATILE (TREE_TYPE (from)))); - conv = build_conv (PTR_CONV, from, conv); - } - else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE) - { - tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from)); - tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to)); - - if (DERIVED_FROM_P (fbase, tbase) - && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))), - TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))), - 1))) - { - from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from))); - from = build_pointer_type (from); - conv = build_conv (PMEM_CONV, from, conv); - } - else - return 0; - } - else if (IS_AGGR_TYPE (TREE_TYPE (from)) - && IS_AGGR_TYPE (TREE_TYPE (to))) - { - if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))) - { - from = cp_build_type_variant (TREE_TYPE (to), - TYPE_READONLY (TREE_TYPE (from)), - TYPE_VOLATILE (TREE_TYPE (from))); - from = build_pointer_type (from); - conv = build_conv (PTR_CONV, from, conv); - } - else - return 0; - } - else - return 0; - - if (! comptypes (from, to, 1)) - { - if (! comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from))) - return 0; - - from = to; - conv = build_conv (QUAL_CONV, from, conv); - } - } - else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from)) - { - tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from)); - tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to)); - tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn))); - tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn))); - - if (! DERIVED_FROM_P (fbase, tbase) - || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1) - || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)), - TREE_CHAIN (TYPE_ARG_TYPES (tofn)), 1) - || TYPE_READONLY (fbase) != TYPE_READONLY (tbase) - || TYPE_VOLATILE (fbase) != TYPE_VOLATILE (tbase)) - return 0; - - from = cp_build_type_variant (tbase, TYPE_READONLY (fbase), - TYPE_VOLATILE (fbase)); - from = build_cplus_method_type (from, TREE_TYPE (fromfn), - TREE_CHAIN (TYPE_ARG_TYPES (fromfn))); - conv = build_conv (PMEM_CONV, from, conv); - } - else if (tcode == BOOLEAN_TYPE) - { - if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE - || fcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (from))) - return 0; - - 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; - } - /* We don't check for ENUMERAL_TYPE here because there are no standard - conversions to enum type. */ - else if (tcode == INTEGER_TYPE || tcode == BOOLEAN_TYPE - || tcode == REAL_TYPE) - { - if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)) - return 0; - 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); - else - return 0; - - return conv; -} - -/* Returns the conversion path from type FROM to reference type TO for - purposes of reference binding. For lvalue binding, either pass a - reference type to FROM or an lvalue expression to EXPR. - - Currently does not distinguish in the generated trees between binding to - an lvalue and a temporary. Should it? */ - -tree -reference_binding (rto, from, expr) - tree rto, from, expr; -{ - tree conv; - int lvalue = 1; - tree to = TREE_TYPE (rto); - - if (TREE_CODE (from) == REFERENCE_TYPE) - from = TREE_TYPE (from); - else if (! expr || ! real_lvalue_p (expr)) - lvalue = 0; - - if (lvalue - && TYPE_READONLY (to) >= TYPE_READONLY (from) - && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from)) - { - conv = build1 (IDENTITY_CONV, from, expr); - - if (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from)) - conv = build_conv (REF_BIND, rto, conv); - else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) - && DERIVED_FROM_P (to, from)) - { - conv = build_conv (REF_BIND, rto, conv); - ICS_STD_RANK (conv) = STD_RANK; - } - else - conv = NULL_TREE; - } - else - conv = NULL_TREE; - - if (! conv && TYPE_READONLY (to) && ! TYPE_VOLATILE (to)) - { - conv = standard_conversion - (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), expr); - if (conv) - { - conv = build_conv (REF_BIND, rto, conv); - - /* Bind directly to a base subobject of a class rvalue. */ - if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) - TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); - } - } - - return conv; -} - -/* Returns the implicit conversion sequence (see [over.ics]) from type FROM - to type TO. The optional expression EXPR may affect the conversion. - FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is - significant. */ - -tree -implicit_conversion (to, from, expr, flags) - tree to, from, expr; - int flags; -{ - tree conv; - struct z_candidate *cand; - - if (expr && type_unknown_p (expr)) - { - expr = instantiate_type (to, expr, 0); - if (expr == error_mark_node) - return 0; - from = TREE_TYPE (expr); - } - - if (TREE_CODE (to) == REFERENCE_TYPE) - conv = reference_binding (to, from, expr); - else - conv = standard_conversion - (TYPE_MAIN_VARIANT (non_reference (to)), - TYPE_MAIN_VARIANT (non_reference (from)), expr); - - if (conv) - { - if (TREE_CODE (conv) == IDENTITY_CONV && IS_AGGR_TYPE (to) - && (TREE_CODE (from) == REFERENCE_TYPE || (expr && real_lvalue_p (expr)))) - conv = build_conv (RVALUE_CONV, to, conv); - } - else if ((IS_AGGR_TYPE (non_reference (from)) - || IS_AGGR_TYPE (non_reference (to))) - && (flags & LOOKUP_NO_CONVERSION) == 0) - { - if (TREE_CODE (to) == REFERENCE_TYPE - && TYPE_READONLY (TREE_TYPE (to)) - && ! TYPE_VOLATILE (TREE_TYPE (to))) - { - cand = build_user_type_conversion_1 - (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING); - if (cand) - conv = build_conv (REF_BIND, to, cand->second_conv); - } - else - { - cand = build_user_type_conversion_1 - (to, expr, LOOKUP_ONLYCONVERTING); - if (cand) - conv = cand->second_conv; - } - } - - return conv; -} - -/* 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. */ - -static struct z_candidate * -add_function_candidate (candidates, fn, arglist, flags) - struct z_candidate *candidates; - tree fn, arglist; - int flags; -{ - tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); - int i, len = list_length (arglist); - tree convs = make_tree_vec (len); - tree parmnode = parmlist; - tree argnode = arglist; - int viable = 1; - struct z_candidate *cand; - - /* The `this' and `in_chrg' arguments to constructors are not considered - in overload resolution. */ - if (DECL_CONSTRUCTOR_P (fn)) - { - parmnode = TREE_CHAIN (parmnode); - if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) - parmnode = TREE_CHAIN (parmnode); - } - - for (i = 0; i < len; ++i) - { - tree arg = TREE_VALUE (argnode); - tree argtype = TREE_TYPE (arg); - tree t; - - argtype = cp_build_type_variant - (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg)); - - if (parmnode == void_list_node) - break; - else if (parmnode) - t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); - else - { - t = build1 (IDENTITY_CONV, argtype, arg); - ICS_ELLIPSIS_FLAG (t) = 1; - } - - TREE_VEC_ELT (convs, i) = t; - if (! t) - break; - - if (parmnode) - parmnode = TREE_CHAIN (parmnode); - argnode = TREE_CHAIN (argnode); - } - - if (i < len) - viable = 0; - - /* Make sure there are default args for the rest of the parms. */ - for (; parmnode && parmnode != void_list_node; - parmnode = TREE_CHAIN (parmnode)) - if (! TREE_PURPOSE (parmnode)) - { - viable = 0; - break; - } - - cand = (struct z_candidate *) oballoc (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; -} - -/* Create an overload candidate for the conversion function FN which will - be invoked for expression OBJ, producing a pointer-to-function which - will in turn be called with the argument list ARGLIST, and add it to - CANDIDATES. FLAGS is passed on to implicit_conversion. */ - -static struct z_candidate * -add_conv_candidate (candidates, fn, obj, arglist) - struct z_candidate *candidates; - tree fn, obj, arglist; -{ - tree totype = TREE_TYPE (TREE_TYPE (fn)); - tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); - int i, len = list_length (arglist) + 1; - tree convs = make_tree_vec (len); - tree parmnode = parmlist; - tree argnode = arglist; - int viable = 1; - struct z_candidate *cand; - int flags = LOOKUP_NORMAL; - - for (i = 0; i < len; ++i) - { - tree arg = i == 0 ? obj : TREE_VALUE (argnode); - tree argtype = TREE_TYPE (arg); - tree t; - - argtype = cp_build_type_variant - (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg)); - - if (i == 0) - t = implicit_conversion (totype, argtype, arg, flags); - else if (parmnode == void_list_node) - break; - else if (parmnode) - t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); - else - { - t = build1 (IDENTITY_CONV, argtype, arg); - ICS_ELLIPSIS_FLAG (t) = 1; - } - - TREE_VEC_ELT (convs, i) = t; - if (! t) - break; - - if (i == 0) - continue; - - if (parmnode) - parmnode = TREE_CHAIN (parmnode); - argnode = TREE_CHAIN (argnode); - } - - if (i < len) - viable = 0; - - for (; parmnode && parmnode != void_list_node; - parmnode = TREE_CHAIN (parmnode)) - if (! TREE_PURPOSE (parmnode)) - { - viable = 0; - break; - } - - cand = (struct z_candidate *) oballoc (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; -} - -int -ptr_complete_ob (t) - tree t; -{ - return (TREE_CODE (t) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (t)) != OFFSET_TYPE - && TREE_CODE (TREE_TYPE (t)) != FUNCTION_TYPE - && TREE_CODE (TREE_TYPE (t)) != VOID_TYPE - && TYPE_SIZE (complete_type (TREE_TYPE (t))) != NULL_TREE); -} - -#define TYPE_PTRMEM_P(NODE) \ - (TREE_CODE (NODE) == POINTER_TYPE \ - && TREE_CODE (TREE_TYPE (NODE)) == OFFSET_TYPE) -#define TYPE_PTR_P(NODE) \ - (TREE_CODE (NODE) == POINTER_TYPE \ - && TREE_CODE (TREE_TYPE (NODE)) != OFFSET_TYPE) -#define TYPE_PTROB_P(NODE) \ - (TYPE_PTR_P (NODE) && TREE_CODE (TREE_TYPE (NODE)) != FUNCTION_TYPE \ - && TREE_CODE (TREE_TYPE (NODE)) != VOID_TYPE) - -static struct z_candidate * -build_builtin_candidate (candidates, fnname, type1, type2, - args, argtypes, flags) - struct z_candidate *candidates; - tree fnname, type1, type2, *args, *argtypes; - int flags; - -{ - tree t, convs; - int viable = 1, i; - struct z_candidate *cand; - tree types[2]; - - types[0] = type1; - types[1] = type2; - - convs = make_tree_vec (args[2] ? 3 : (args[1] ? 2 : 1)); - - for (i = 0; i < 2; ++i) - { - if (! args[i]) - break; - - t = implicit_conversion (types[i], argtypes[i], args[i], flags); - if (! t) - { - viable = 0; - /* We need something for printing the candidate. */ - t = build1 (IDENTITY_CONV, types[i], NULL_TREE); - } - TREE_VEC_ELT (convs, i) = t; - } - - /* For COND_EXPR we rearranged the arguments; undo that now. */ - if (args[2]) - { - TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1); - TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0); - t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); - if (t) - TREE_VEC_ELT (convs, 0) = t; - else - viable = 0; - } - - cand = (struct z_candidate *) oballoc (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; -} - -int -is_complete (t) - tree t; -{ - return TYPE_SIZE (complete_type (t)) != NULL_TREE; -} - -/* 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. */ - -static struct z_candidate * -add_builtin_candidate (candidates, code, code2, fnname, type1, type2, - args, argtypes, flags) - struct z_candidate *candidates; - enum tree_code code, code2; - tree fnname, type1, type2, *args, *argtypes; - int flags; -{ - switch (code) - { - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - args[1] = integer_zero_node; - type2 = integer_type_node; - } - - switch (code) - { - -/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, - and VQ is either volatile or empty, there exist candidate operator - functions of the form - VQ T& operator++(VQ T&); - T operator++(VQ T&, int); - 5 For every pair T, VQ), where T is an enumeration type or an arithmetic - type other than bool, and VQ is either volatile or empty, there exist - candidate operator functions of the form - VQ T& operator--(VQ T&); - T operator--(VQ T&, int); - 6 For every pair T, VQ), where T is a cv-qualified or cv-unqualified - complete object type, and VQ is either volatile or empty, there exist - candidate operator functions of the form - T*VQ& operator++(T*VQ&); - T*VQ& operator--(T*VQ&); - T* operator++(T*VQ&, int); - T* operator--(T*VQ&, int); */ - - case POSTDECREMENT_EXPR: - case PREDECREMENT_EXPR: - if (TREE_CODE (type1) == BOOLEAN_TYPE) - return candidates; - case POSTINCREMENT_EXPR: - case PREINCREMENT_EXPR: - if (ARITHMETIC_TYPE_P (type1) || ptr_complete_ob (type1)) - { - type1 = build_reference_type (type1); - break; - } - return candidates; - -/* 7 For every cv-qualified or cv-unqualified complete object type T, there - exist candidate operator functions of the form - - T& operator*(T*); - - 8 For every function type T, there exist candidate operator functions of - the form - T& operator*(T*); */ - - case INDIRECT_REF: - if (TREE_CODE (type1) == POINTER_TYPE - && (ptr_complete_ob (type1) - || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)) - break; - return candidates; - -/* 9 For every type T, there exist candidate operator functions of the form - T* operator+(T*); - - 10For every promoted arithmetic type T, there exist candidate operator - functions of the form - T operator+(T); - T operator-(T); */ - - case CONVERT_EXPR: /* unary + */ - if (TREE_CODE (type1) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (type1)) != OFFSET_TYPE) - break; - case NEGATE_EXPR: - if (ARITHMETIC_TYPE_P (type1)) - break; - return candidates; - -/* 11For every promoted integral type T, there exist candidate operator - functions of the form - T operator~(T); */ - - case BIT_NOT_EXPR: - if (INTEGRAL_TYPE_P (type1)) - break; - return candidates; - -/* 12For every quintuple C1, C2, T, CV1, CV2), where C2 is a class type, C1 - is the same type as C2 or is a derived class of C2, T is a complete - object type or a function type, and CV1 and CV2 are cv-qualifier-seqs, - there exist candidate operator functions of the form - CV12 T& operator->*(CV1 C1*, CV2 T C2::*); - where CV12 is the union of CV1 and CV2. */ - - case MEMBER_REF: - if (TREE_CODE (type1) == POINTER_TYPE - && (TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))) - { - tree c1 = TREE_TYPE (type1); - tree c2 = (TYPE_PTRMEMFUNC_P (type2) - ? TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (type2)) - : TYPE_OFFSET_BASETYPE (TREE_TYPE (type2))); - - if (IS_AGGR_TYPE (c1) && DERIVED_FROM_P (c2, c1) - && (TYPE_PTRMEMFUNC_P (type2) - || is_complete (TREE_TYPE (TREE_TYPE (type2))))) - break; - } - return candidates; - -/* 13For every pair of promoted arithmetic types L and R, there exist can- - didate operator functions of the form - LR operator*(L, R); - LR operator/(L, R); - LR operator+(L, R); - LR operator-(L, R); - bool operator<(L, R); - bool operator>(L, R); - bool operator<=(L, R); - bool operator>=(L, R); - bool operator==(L, R); - bool operator!=(L, R); - where LR is the result of the usual arithmetic conversions between - types L and R. - - 14For every pair of types T and I, where T is a cv-qualified or cv- - unqualified complete object type and I is a promoted integral type, - there exist candidate operator functions of the form - T* operator+(T*, I); - T& operator[](T*, I); - T* operator-(T*, I); - T* operator+(I, T*); - T& operator[](I, T*); - - 15For every T, where T is a pointer to complete object type, there exist - candidate operator functions of the form112) - ptrdiff_t operator-(T, T); - - 16For every pointer type T, there exist candidate operator functions of - the form - bool operator<(T, T); - bool operator>(T, T); - bool operator<=(T, T); - bool operator>=(T, T); - bool operator==(T, T); - bool operator!=(T, T); - - 17For every pointer to member type T, there exist candidate operator - functions of the form - bool operator==(T, T); - bool operator!=(T, T); */ - - case MINUS_EXPR: - if (ptr_complete_ob (type1) && ptr_complete_ob (type2)) - break; - if (ptr_complete_ob (type1) && INTEGRAL_TYPE_P (type2)) - { - type2 = ptrdiff_type_node; - break; - } - case MULT_EXPR: - case TRUNC_DIV_EXPR: - if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) - break; - return candidates; - - case EQ_EXPR: - case NE_EXPR: - if (TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2) - || TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) - break; - if ((TYPE_PTRMEMFUNC_P (type1) || TYPE_PTRMEM_P (type1)) - && null_ptr_cst (args[1])) - { - type2 = type1; - break; - } - if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2)) - && null_ptr_cst (args[0])) - { - type1 = type2; - break; - } - 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)) - break; - if (TYPE_PTR_P (type1) && null_ptr_cst (args[1])) - { - type2 = type1; - break; - } - if (null_ptr_cst (args[0]) && TYPE_PTR_P (type2)) - { - type1 = type2; - break; - } - return candidates; - - case PLUS_EXPR: - if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) - break; - case ARRAY_REF: - if (INTEGRAL_TYPE_P (type1) && ptr_complete_ob (type2)) - { - type1 = ptrdiff_type_node; - break; - } - if (ptr_complete_ob (type1) && INTEGRAL_TYPE_P (type2)) - { - type2 = ptrdiff_type_node; - break; - } - return candidates; - -/* 18For every pair of promoted integral types L and R, there exist candi- - date operator functions of the form - LR operator%(L, R); - LR operator&(L, R); - LR operator^(L, R); - LR operator|(L, R); - L operator<<(L, R); - L operator>>(L, R); - where LR is the result of the usual arithmetic conversions between - types L and R. */ - - case TRUNC_MOD_EXPR: - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) - break; - return candidates; - -/* 19For every triple L, VQ, R), where L is an arithmetic or enumeration - type, VQ is either volatile or empty, and R is a promoted arithmetic - type, there exist candidate operator functions of the form - VQ L& operator=(VQ L&, R); - VQ L& operator*=(VQ L&, R); - VQ L& operator/=(VQ L&, R); - VQ L& operator+=(VQ L&, R); - VQ L& operator-=(VQ L&, R); - - 20For every pair T, VQ), where T is any type and VQ is either volatile - or empty, there exist candidate operator functions of the form - T*VQ& operator=(T*VQ&, T*); - - 21For every pair T, VQ), where T is a pointer to member type and VQ is - either volatile or empty, there exist candidate operator functions of - the form - VQ T& operator=(VQ T&, T); - - 22For every triple T, VQ, I), where T is a cv-qualified or cv- - unqualified complete object type, VQ is either volatile or empty, and - I is a promoted integral type, there exist candidate operator func- - tions of the form - T*VQ& operator+=(T*VQ&, I); - T*VQ& operator-=(T*VQ&, I); - - 23For every triple L, VQ, R), where L is an integral or enumeration - type, VQ is either volatile or empty, and R is a promoted integral - type, there exist candidate operator functions of the form - - VQ L& operator%=(VQ L&, R); - VQ L& operator<<=(VQ L&, R); - VQ L& operator>>=(VQ L&, R); - VQ L& operator&=(VQ L&, R); - VQ L& operator^=(VQ L&, R); - VQ L& operator|=(VQ L&, R); */ - - case MODIFY_EXPR: - switch (code2) - { - case PLUS_EXPR: - case MINUS_EXPR: - if (ptr_complete_ob (type1) && INTEGRAL_TYPE_P (type2)) - { - type2 = ptrdiff_type_node; - break; - } - case MULT_EXPR: - case TRUNC_DIV_EXPR: - if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) - break; - return candidates; - - case TRUNC_MOD_EXPR: - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)) - break; - return candidates; - - case NOP_EXPR: - if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) - break; - if ((TYPE_PTRMEMFUNC_P (type1) && TYPE_PTRMEMFUNC_P (type2)) - || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) - || (TYPE_PTRMEM_P (type1) && TYPE_PTRMEM_P (type2)) - || ((TYPE_PTRMEMFUNC_P (type1) - || TREE_CODE (type1) == POINTER_TYPE) - && null_ptr_cst (args[1]))) - { - type2 = type1; - break; - } - return candidates; - - default: - my_friendly_abort (367); - } - type1 = build_reference_type (type1); - break; - - case COND_EXPR: - if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2) - break; - else if (TREE_CODE (type1) == ENUMERAL_TYPE - || TREE_CODE (type2) == ENUMERAL_TYPE) - return candidates; - if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2)) - break; - if (TREE_CODE (type1) == TREE_CODE (type2) - && (TREE_CODE (type1) == REFERENCE_TYPE - || TREE_CODE (type1) == POINTER_TYPE - || TYPE_PTRMEMFUNC_P (type1) - || IS_AGGR_TYPE (type1))) - break; - if (TREE_CODE (type1) == REFERENCE_TYPE - || TREE_CODE (type2) == REFERENCE_TYPE) - return candidates; - if (((TYPE_PTRMEMFUNC_P (type1) || TREE_CODE (type1) == POINTER_TYPE) - && null_ptr_cst (args[1])) - || IS_AGGR_TYPE (type1)) - { - type2 = type1; - break; - } - if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE) - && null_ptr_cst (args[0])) - || IS_AGGR_TYPE (type2)) - { - type1 = type2; - break; - } - return candidates; - - default: - my_friendly_abort (367); - } - - /* If we're dealing with two pointer types, we need candidates - for both of them. */ - if (type2 && type1 != type2 - && TREE_CODE (type1) == TREE_CODE (type2) - && (TREE_CODE (type1) == REFERENCE_TYPE - || TREE_CODE (type1) == POINTER_TYPE - || TYPE_PTRMEMFUNC_P (type1) - || IS_AGGR_TYPE (type1))) - { - candidates = build_builtin_candidate - (candidates, fnname, type1, type1, args, argtypes, flags); - return build_builtin_candidate - (candidates, fnname, type2, type2, args, argtypes, flags); - } - - return build_builtin_candidate - (candidates, fnname, type1, type2, args, argtypes, flags); -} - -tree -type_decays_to (type) - tree type; -{ - if (TREE_CODE (type) == ARRAY_TYPE) - return build_pointer_type (TREE_TYPE (type)); - if (TREE_CODE (type) == FUNCTION_TYPE) - return build_pointer_type (type); - return type; -} - -/* There are three conditions of builtin candidates: - - 1) bool-taking candidates. These are the same regardless of the input. - 2) pointer-pair taking candidates. These are generated for each type - one of the input types converts to. - 3) arithmetic candidates. According to the WP, we should generate - all of these, but I'm trying not to... */ - -static struct z_candidate * -add_builtin_candidates (candidates, code, code2, fnname, args, flags) - struct z_candidate *candidates; - enum tree_code code, code2; - tree fnname, *args; - int flags; -{ - int ref1, i; - tree type, argtypes[3], types[2]; - - for (i = 0; i < 3; ++i) - { - if (args[i]) - argtypes[i] = cp_build_type_variant - (TREE_TYPE (args[i]), TREE_READONLY (args[i]), - TREE_THIS_VOLATILE (args[i])); - else - argtypes[i] = NULL_TREE; - } - - switch (code) - { -/* 4 For every pair T, VQ), where T is an arithmetic or enumeration type, - and VQ is either volatile or empty, there exist candidate operator - functions of the form - VQ T& operator++(VQ T&); */ - - case POSTINCREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case PREDECREMENT_EXPR: - case MODIFY_EXPR: - ref1 = 1; - break; - -/* 24There also exist candidate operator functions of the form - bool operator!(bool); - bool operator&&(bool, bool); - bool operator||(bool, bool); */ - - case TRUTH_NOT_EXPR: - return build_builtin_candidate - (candidates, fnname, boolean_type_node, - NULL_TREE, args, argtypes, flags); - - case TRUTH_ORIF_EXPR: - case TRUTH_ANDIF_EXPR: - return build_builtin_candidate - (candidates, fnname, boolean_type_node, - boolean_type_node, args, argtypes, flags); - - case ADDR_EXPR: - case COMPOUND_EXPR: - case COMPONENT_REF: - return candidates; - - default: - ref1 = 0; - } - - types[0] = types[1] = NULL_TREE; - - for (i = 0; i < 2; ++i) - { - if (! args[i]) - ; - else if (IS_AGGR_TYPE (argtypes[i])) - { - tree convs = lookup_conversions (argtypes[i]); - - if (code == COND_EXPR) - { - if (real_lvalue_p (args[i])) - types[i] = tree_cons - (NULL_TREE, build_reference_type (argtypes[i]), types[i]); - - types[i] = tree_cons - (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]); - } - - else if (! convs || (i == 0 && code == MODIFY_EXPR)) - return candidates; - - for (; convs; convs = TREE_CHAIN (convs)) - { - type = TREE_TYPE (TREE_TYPE (TREE_VALUE (convs))); - - if (i == 0 && ref1 - && (TREE_CODE (type) != REFERENCE_TYPE - || TYPE_READONLY (TREE_TYPE (type)))) - continue; - - if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE) - types[i] = tree_cons (NULL_TREE, type, types[i]); - - type = non_reference (type); - if (i != 0 || ! ref1) - { - type = type_decays_to (TYPE_MAIN_VARIANT (type)); - if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) - types[i] = tree_cons (NULL_TREE, type, types[i]); - type = type_promotes_to (type); - } - - if (! value_member (type, types[i])) - types[i] = tree_cons (NULL_TREE, type, types[i]); - } - } - else - { - if (code == COND_EXPR && real_lvalue_p (args[i])) - types[i] = tree_cons - (NULL_TREE, build_reference_type (argtypes[i]), types[i]); - type = non_reference (argtypes[i]); - if (i != 0 || ! ref1) - { - type = type_decays_to (TYPE_MAIN_VARIANT (type)); - if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) - types[i] = tree_cons (NULL_TREE, type, types[i]); - type = type_promotes_to (type); - } - types[i] = tree_cons (NULL_TREE, type, types[i]); - } - } - - for (; types[0]; types[0] = TREE_CHAIN (types[0])) - { - if (types[1]) - for (type = types[1]; type; type = TREE_CHAIN (type)) - candidates = add_builtin_candidate - (candidates, code, code2, fnname, TREE_VALUE (types[0]), - TREE_VALUE (type), args, argtypes, flags); - else - candidates = add_builtin_candidate - (candidates, code, code2, fnname, TREE_VALUE (types[0]), - NULL_TREE, args, argtypes, flags); - } - - return candidates; -} - -static struct z_candidate * -add_template_candidate (candidates, tmpl, arglist, flags) - struct z_candidate *candidates; - tree tmpl, arglist; - int flags; -{ - int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); - tree *targs = (tree *) alloca (sizeof (tree) * ntparms); - struct z_candidate *cand; - int i, dummy; - tree fn; - - i = type_unification (DECL_TEMPLATE_PARMS (tmpl), targs, - TYPE_ARG_TYPES (TREE_TYPE (tmpl)), - arglist, &dummy, 0, 0); - if (i != 0) - return candidates; - - fn = instantiate_template (tmpl, targs); - if (fn == error_mark_node) - return candidates; - - cand = add_function_candidate (candidates, fn, arglist, flags); - cand->template = DECL_TEMPLATE_INFO (fn); - return cand; -} - -static int -any_viable (cands) - struct z_candidate *cands; -{ - for (; cands; cands = cands->next) - if (cands->viable) - return 1; - return 0; -} - -static struct z_candidate * -splice_viable (cands) - struct z_candidate *cands; -{ - struct z_candidate **p = &cands; - - for (; *p; ) - { - if ((*p)->viable) - p = &((*p)->next); - else - *p = (*p)->next; - } - - return cands; -} - -tree -build_this (obj) - tree obj; -{ - /* Fix this to work on non-lvalues. */ - return build_unary_op (ADDR_EXPR, obj, 0); -} - -static void -print_z_candidates (candidates) - struct z_candidate *candidates; -{ - if (! candidates) - return; - - if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) - { - if (candidates->fn == ansi_opname [COND_EXPR]) - cp_error ("candidates are: %D(%T, %T, %T) <builtin>", candidates->fn, - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); - else if (TREE_VEC_LENGTH (candidates->convs) == 2) - cp_error ("candidates are: %D(%T, %T) <builtin>", candidates->fn, - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); - else - cp_error ("candidates are: %D(%T) <builtin>", candidates->fn, - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); - } - else - cp_error_at ("candidates are: %D", candidates->fn); - candidates = candidates->next; - - for (; candidates; candidates = candidates->next) - { - if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) - { - if (candidates->fn == ansi_opname [COND_EXPR]) - cp_error (" %D(%T, %T, %T) <builtin>", - candidates->fn, - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); - else if (TREE_VEC_LENGTH (candidates->convs) == 2) - cp_error (" %D(%T, %T) <builtin>", candidates->fn, - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); - else - cp_error (" %D(%T) <builtin>", candidates->fn, - TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); - } - else - cp_error_at (" %D", candidates->fn); - } -} - -/* Returns the best overload candidate to perform the requested - conversion. */ - -static struct z_candidate * -build_user_type_conversion_1 (totype, expr, flags) - tree totype, expr; - int flags; -{ - struct z_candidate *candidates, *cand; - tree fromtype = TREE_TYPE (expr); - tree ctors = NULL_TREE, convs = NULL_TREE, *p; - tree args; - - if (IS_AGGR_TYPE (totype)) - ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); - if (IS_AGGR_TYPE (fromtype) - && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype))) - convs = lookup_conversions (fromtype); - - candidates = 0; - flags |= LOOKUP_NO_CONVERSION; - - if (ctors) - { - ctors = TREE_VALUE (ctors); - args = build_tree_list (NULL_TREE, expr); - } - for (; ctors; ctors = DECL_CHAIN (ctors)) - { - if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (ctors)) - continue; - - candidates = add_function_candidate (candidates, ctors, args, flags); - candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); - candidates->basetype_path = TYPE_BINFO (totype); - } - - if (convs) - args = build_tree_list (NULL_TREE, build_this (expr)); - - for (; convs; convs = TREE_CHAIN (convs)) - { - tree fn = TREE_VALUE (convs); - tree ics = implicit_conversion - (totype, TREE_TYPE (TREE_TYPE (fn)), 0, LOOKUP_NO_CONVERSION); - if (ics) - for (; fn; fn = DECL_CHAIN (fn)) - { - candidates = add_function_candidate (candidates, fn, args, flags); - candidates->second_conv = ics; - candidates->basetype_path = TREE_PURPOSE (convs); - } - } - - if (! any_viable (candidates)) - { -#if 0 - if (flags & LOOKUP_COMPLAIN) - { - if (candidates && ! candidates->next) - /* say why this one won't work or try to be loose */; - else - cp_error ("no viable candidates"); - } -#endif - - return 0; - } - - candidates = splice_viable (candidates); - cand = tourney (candidates, totype); - - if (cand == 0) - { - if (flags & LOOKUP_COMPLAIN) - { - cp_error ("ambiguous user-defined type conversion"); - print_z_candidates (candidates); - } - - cand = candidates; /* any one will do */ - cand->second_conv = build1 (AMBIG_CONV, totype, expr); - ICS_USER_FLAG (cand->second_conv) = 1; - - return cand; - } - - for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) - p = &(TREE_OPERAND (*p, 0)); - - *p = build - (USER_CONV, - (DECL_CONSTRUCTOR_P (cand->fn) - ? totype : non_reference (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); - - if (cand) - { - if (TREE_CODE (cand->second_conv) == AMBIG_CONV) - return error_mark_node; - return convert_from_reference (convert_like (cand->second_conv, expr)); - } - return NULL_TREE; -} - -tree -build_new_function_call (fn, args, obj) - tree fn, args, obj; -{ - struct z_candidate *candidates = 0, *cand; - - if (obj == NULL_TREE && TREE_CODE (fn) == TREE_LIST) - { - tree t = TREE_VALUE (fn); - - for (; t; t = DECL_CHAIN (t)) - { - if (TREE_CODE (t) == TEMPLATE_DECL) - candidates = add_template_candidate - (candidates, t, args, LOOKUP_NORMAL); - else - candidates = add_function_candidate - (candidates, t, args, LOOKUP_NORMAL); - } - - if (! any_viable (candidates)) - { - if (candidates && ! candidates->next) - return build_function_call (candidates->fn, args); - else - cp_error ("no viable candidates"); - return error_mark_node; - } - candidates = splice_viable (candidates); - cand = tourney (candidates, NULL_TREE); - - if (cand == 0) - { - cp_error ("ambiguous function call"); - print_z_candidates (candidates); - return error_mark_node; - } - - return build_over_call (cand->fn, cand->convs, args, LOOKUP_NORMAL); - } - - return build_function_call (fn, args); -} - -tree -build_object_call (obj, args) - tree obj, args; -{ - struct z_candidate *candidates = 0, *cand; - tree fns, convs, mem_args, *p; - enum tree_code code2 = NOP_EXPR; - tree type = TREE_TYPE (obj); - - fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 0); - - if (fns) - { - tree fn = TREE_VALUE (fns); - mem_args = tree_cons (NULL_TREE, build_this (obj), args); - - for (; fn; fn = DECL_CHAIN (fn)) - { - candidates = add_function_candidate - (candidates, fn, mem_args, LOOKUP_NORMAL); - candidates->basetype_path = TREE_PURPOSE (fns); - } - } - - convs = lookup_conversions (type); - - for (; convs; convs = TREE_CHAIN (convs)) - { - tree fn = TREE_VALUE (convs); - tree totype = TREE_TYPE (TREE_TYPE (fn)); - - if (TREE_CODE (totype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) - { - candidates = add_conv_candidate (candidates, fn, obj, args); - candidates->basetype_path = TREE_PURPOSE (convs); - } - } - - if (! any_viable (candidates)) - { - cp_error ("no viable candidates"); - print_z_candidates (candidates); - return error_mark_node; - } - - candidates = splice_viable (candidates); - cand = tourney (candidates, NULL_TREE); - - if (cand == 0) - { - cp_error ("ambiguous object call"); - print_z_candidates (candidates); - return error_mark_node; - } - - if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR]) - return build_over_call (cand->fn, cand->convs, mem_args, LOOKUP_NORMAL); - - obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj); - - /* FIXME */ - return build_function_call (obj, args); -} - -static void -op_error (code, code2, arg1, arg2, arg3, problem) - enum tree_code code, code2; - tree arg1, arg2, arg3; - char *problem; -{ - char * opname - = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]); - - switch (code) - { - case COND_EXPR: - cp_error ("%s for `%T ? %T : %T'", problem, - TREE_TYPE (arg1), TREE_TYPE (arg2), TREE_TYPE (arg3)); - break; - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - cp_error ("%s for `%T%s'", problem, TREE_TYPE (arg1), opname); - break; - case ARRAY_REF: - cp_error ("%s for `%T[%T]'", problem, - TREE_TYPE (arg1), TREE_TYPE (arg2)); - break; - default: - if (arg2) - cp_error ("%s for `%T %s %T'", problem, - TREE_TYPE (arg1), opname, TREE_TYPE (arg2)); - else - cp_error ("%s for `%s%T'", problem, opname, TREE_TYPE (arg1)); - } -} - -tree -build_new_op (code, flags, arg1, arg2, arg3) - enum tree_code code; - int flags; - tree arg1, arg2, arg3; -{ - struct z_candidate *candidates = 0, *cand; - tree fns, mem_arglist, arglist, fnname, *p; - enum tree_code code2 = NOP_EXPR; - - if (arg1 == error_mark_node) - return error_mark_node; - - if (code == MODIFY_EXPR) - { - code2 = TREE_CODE (arg3); - arg3 = NULL_TREE; - fnname = ansi_assopname[code2]; - } - else - fnname = ansi_opname[code]; - - switch (code) - { - case NEW_EXPR: - case VEC_NEW_EXPR: - { - tree rval; - - arglist = tree_cons (NULL_TREE, arg2, arg3); - if (flags & LOOKUP_GLOBAL) - return build_new_function_call - (lookup_name_nonclass (fnname), arglist, NULL_TREE); - - /* FIXME */ - rval = build_method_call - (build_indirect_ref (build1 (NOP_EXPR, arg1, error_mark_node), - "new"), - fnname, arglist, NULL_TREE, flags); - if (rval == error_mark_node) - /* User might declare fancy operator new, but invoke it - like standard one. */ - return rval; - - TREE_TYPE (rval) = arg1; - TREE_CALLS_NEW (rval) = 1; - return rval; - } - - case VEC_DELETE_EXPR: - case DELETE_EXPR: - { - tree rval; - - if (flags & LOOKUP_GLOBAL) - return build_new_function_call - (lookup_name_nonclass (fnname), - build_tree_list (NULL_TREE, arg1), NULL_TREE); - - arglist = tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2)); - - arg1 = TREE_TYPE (arg1); - - /* This handles the case where we're trying to delete - X (*a)[10]; - a=new X[5][10]; - delete[] a; */ - - if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) - { - /* Strip off the pointer and the array. */ - arg1 = TREE_TYPE (TREE_TYPE (arg1)); - - while (TREE_CODE (arg1) == ARRAY_TYPE) - arg1 = (TREE_TYPE (arg1)); - - arg1 = build_pointer_type (arg1); - } - - /* FIXME */ - rval = build_method_call - (build_indirect_ref (build1 (NOP_EXPR, arg1, - error_mark_node), - NULL_PTR), - fnname, arglist, NULL_TREE, flags); -#if 0 - /* This can happen when operator delete is protected. */ - my_friendly_assert (rval != error_mark_node, 250); - TREE_TYPE (rval) = void_type_node; -#endif - return rval; - } - - case CALL_EXPR: - return build_object_call (arg1, arg2); - } - - /* The comma operator can have void args. */ - if (TREE_CODE (arg1) == OFFSET_REF) - arg1 = resolve_offset_ref (arg1); - if (arg2 && TREE_CODE (arg2) == OFFSET_REF) - arg2 = resolve_offset_ref (arg2); - if (arg3 && TREE_CODE (arg3) == OFFSET_REF) - arg3 = resolve_offset_ref (arg3); - - if (! IS_OVERLOAD_TYPE (TREE_TYPE (arg1)) - && (! arg2 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg2))) - && (! arg3 || ! IS_OVERLOAD_TYPE (TREE_TYPE (arg3)))) - return NULL_TREE; - - if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) - arg2 = integer_zero_node; - - fns = lookup_name_nonclass (fnname); - /* + Koenig lookup */ - - if (arg2 && arg3) - arglist = tree_cons (NULL_TREE, arg1, tree_cons - (NULL_TREE, arg2, build_tree_list (NULL_TREE, arg3))); - else if (arg2) - arglist = tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2)); - else - arglist = build_tree_list (NULL_TREE, arg1); - - if (fns && TREE_CODE (fns) == TREE_LIST) - fns = TREE_VALUE (fns); - for (; fns; fns = DECL_CHAIN (fns)) - { - if (TREE_CODE (fns) == TEMPLATE_DECL) - candidates = add_template_candidate (candidates, fns, arglist, flags); - else - candidates = add_function_candidate (candidates, fns, arglist, flags); - } - - if (IS_AGGR_TYPE (TREE_TYPE (arg1))) - fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 0); - else - fns = NULL_TREE; - - if (fns) - { - tree fn = TREE_VALUE (fns); - mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist)); - for (; fn; fn = DECL_CHAIN (fn)) - { - if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) - candidates = add_function_candidate - (candidates, fn, mem_arglist, flags); - else - candidates = add_function_candidate (candidates, fn, arglist, flags); - - candidates->basetype_path = TREE_PURPOSE (fns); - } - } - -#if 0 /* Don't handle builtin COND_EXPR for now */ - if (code != COND_EXPR) -#endif - { - tree args[3]; - - /* Rearrange the arguments for ?: so that add_builtin_candidate only has - to know about two args; a builtin candidate will always have a first - parameter of type bool. We'll handle that in - build_builtin_candidate. */ - if (code == COND_EXPR) - { - args[0] = arg2; - args[1] = arg3; - args[2] = arg1; - } - else - { - args[0] = arg1; - args[1] = arg2; - args[2] = NULL_TREE; - } - - candidates = add_builtin_candidates - (candidates, code, code2, fnname, args, flags); - } - - if (! any_viable (candidates)) - { - switch (code) - { - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - /* Look for an `operator++ (int)'. If they didn't have - one, then we fall back to the old way of doing things. */ - if (flags & LOOKUP_COMPLAIN) - cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead", - fnname, opname_tab [code]); - if (code == POSTINCREMENT_EXPR) - code = PREINCREMENT_EXPR; - else - code = PREDECREMENT_EXPR; - return build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE); - - /* FIXME */ - case ADDR_EXPR: - /*return build_unary_op (code, arg1, 1);*/ - case COMPOUND_EXPR: - /*return build (COMPOUND_EXPR, TREE_TYPE (arg2), - break_out_cleanups (arg1), arg2);*/ - case COMPONENT_REF: - /*return build_x_arrow (arg1);*/ -#if 0 /* Don't handle builtin COND_EXPR for now */ - case COND_EXPR: -#endif - return NULL_TREE; - } - if (flags & LOOKUP_COMPLAIN) - { - op_error (code, code2, arg1, arg2, arg3, "no match"); - print_z_candidates (candidates); - } - return error_mark_node; - } - candidates = splice_viable (candidates); - cand = tourney (candidates, NULL_TREE); - - if (cand == 0) - { - if (flags & LOOKUP_COMPLAIN) - { - op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); - print_z_candidates (candidates); - } - return error_mark_node; - } - - if (TREE_CODE (cand->fn) == FUNCTION_DECL) - { - extern int warn_synth; - if (warn_synth - && fnname == ansi_opname[MODIFY_EXPR] - && DECL_ARTIFICIAL (cand->fn) - && candidates->next - && ! candidates->next->next) - { - cp_warning ("using synthesized `%#D' for copy assignment", - cand->fn); - cp_warning_at (" where cfront would use `%#D'", - cand == candidates - ? candidates->next->fn - : candidates->fn); - } - - if (DECL_FUNCTION_MEMBER_P (cand->fn)) - enforce_access (cand->basetype_path, cand->fn); - - return build_over_call - (cand->fn, cand->convs, - TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE - ? mem_arglist : arglist, - LOOKUP_NORMAL); - } - - arg1 = convert_from_reference - (convert_like (TREE_VEC_ELT (cand->convs, 0), arg1)); - if (arg2) - arg2 = convert_like (TREE_VEC_ELT (cand->convs, 1), arg2); - if (arg3) - arg3 = convert_like (TREE_VEC_ELT (cand->convs, 2), arg3); - - switch (code) - { - case MODIFY_EXPR: - return build_modify_expr (arg1, code2, arg2); - - case INDIRECT_REF: - return build_indirect_ref (arg1, "unary *"); - - case PLUS_EXPR: - case MINUS_EXPR: - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case GT_EXPR: - case LT_EXPR: - case GE_EXPR: - case LE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case MAX_EXPR: - case MIN_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case TRUNC_MOD_EXPR: - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - return build_binary_op_nodefault (code, arg1, arg2, code); - - case CONVERT_EXPR: - case NEGATE_EXPR: - case BIT_NOT_EXPR: - case TRUTH_NOT_EXPR: - case PREINCREMENT_EXPR: - case POSTINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case POSTDECREMENT_EXPR: - return build_unary_op (code, arg1, 1); - - case ARRAY_REF: - return build_array_ref (arg1, arg2); - - case COND_EXPR: - return build_conditional_expr (arg1, arg2, arg3); - - default: - my_friendly_abort (367); - } -} - -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 ("`%+#D' is %s", function, - TREE_PRIVATE (function) ? "private" - : "from private base class"); - error ("within this context"); - } - else if (access == access_protected_node) - { - cp_error_at ("`%+#D' %s", function, - TREE_PROTECTED (function) ? "is protected" - : "has protected accessibility"); - error ("within this context"); - } -} - -/* Perform the conversions in CONVS on the expression EXPR. */ - -static tree -convert_like (convs, expr) - tree convs, expr; -{ - switch (TREE_CODE (convs)) - { - case USER_CONV: - { - tree fn = TREE_OPERAND (convs, 1); - enforce_access (TREE_OPERAND (convs, 3), fn); - expr = build_over_call - (TREE_OPERAND (convs, 1), TREE_OPERAND (convs, 2), - DECL_CONSTRUCTOR_P (fn) ? expr : build_this (expr), LOOKUP_NORMAL); - - /* If this is a constructor or a function returning an aggr type, - we need to build up a TARGET_EXPR. */ - if (DECL_CONSTRUCTOR_P (fn) - || IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (fn)))) - expr = build_cplus_new (TREE_TYPE (convs), expr); - - return expr; - } - case IDENTITY_CONV: - if (type_unknown_p (expr)) - expr = instantiate_type (TREE_TYPE (convs), expr, 1); - return expr; - case AMBIG_CONV: - /* Call build_user_type_conversion again for the error. */ - return build_user_type_conversion - (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL); - }; - - expr = convert_like (TREE_OPERAND (convs, 0), expr); - if (expr == error_mark_node) - return error_mark_node; - - switch (TREE_CODE (convs)) - { - case BASE_CONV: - case RVALUE_CONV: - return build_user_type_conversion - (TREE_TYPE (convs), expr, LOOKUP_NORMAL); - case REF_BIND: - return convert_to_reference - (TREE_TYPE (convs), expr, - CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION|INDIRECT_BIND, - error_mark_node); - case LVALUE_CONV: - return decay_conversion (expr); - } - return cp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT, - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); -} - -static tree -convert_default_arg (type, arg) - tree type, arg; -{ - arg = break_out_target_exprs (arg); - - if (TREE_CODE (arg) == CONSTRUCTOR) - { - arg = digest_init (type, arg, 0); - arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, - "default argument", 0, 0); - } - else - { - /* This could get clobbered by the following call. */ - if (TREE_HAS_CONSTRUCTOR (arg)) - arg = copy_node (arg); - - arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, - "default argument", 0, 0); -#ifdef PROMOTE_PROTOTYPES - if ((TREE_CODE (type) == INTEGER_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) - arg = default_conversion (arg); -#endif - } - - return arg; -} - -static tree -build_over_call (fn, convs, args, flags) - tree fn, convs, args; - int flags; -{ - tree converted_args = NULL_TREE; - tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); - tree conv, arg, val; - int i = 0; - - if (args && TREE_CODE (args) != TREE_LIST) - args = build_tree_list (NULL_TREE, args); - arg = args; - - if (DECL_CONSTRUCTOR_P (fn)) - { - tree t = build_int_2 (0, 0); - TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn)); - converted_args = tree_cons (NULL_TREE, t, converted_args); - parm = TREE_CHAIN (parm); - - if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) - { - converted_args = tree_cons - (NULL_TREE, integer_one_node, converted_args); - parm = TREE_CHAIN (parm); - } - } - /* Bypass access control for 'this' parameter. */ - else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) - { - converted_args = tree_cons - (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST), - converted_args); - parm = TREE_CHAIN (parm); - arg = TREE_CHAIN (arg); - ++i; - } - - for (; conv = TREE_VEC_ELT (convs, i), arg && parm; - parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i) - { - tree type = TREE_VALUE (parm); - val = convert_like (conv, TREE_VALUE (arg)); - -#ifdef PROMOTE_PROTOTYPES - if ((TREE_CODE (type) == INTEGER_TYPE - || TREE_CODE (type) == ENUMERAL_TYPE) - && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) - val = default_conversion (val); -#endif - converted_args = tree_cons (NULL_TREE, val, converted_args); - } - - /* Default arguments */ - for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm)) - converted_args = tree_cons - (NULL_TREE, - convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm)), - converted_args); - - /* Ellipsis */ - for (; arg; arg = TREE_CHAIN (arg)) - { - val = TREE_VALUE (arg); - - if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE - && (TYPE_PRECISION (TREE_TYPE (val)) - < TYPE_PRECISION (double_type_node))) - /* Convert `float' to `double'. */ - val = convert (double_type_node, val); - else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val)) - && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val))) - cp_warning ("cannot pass objects of type `%T' through `...'", - TREE_TYPE (val)); - else - /* Convert `short' and `char' to full-size `int'. */ - val = default_conversion (val); - - converted_args = tree_cons (NULL_TREE, val, converted_args); - } - - converted_args = nreverse (converted_args); - - mark_used (fn); - /* Is it a synthesized method that needs to be synthesized? */ - if (DECL_ARTIFICIAL (fn) && ! DECL_INITIAL (fn) - /* Kludge: don't synthesize for default args. */ - && current_function_decl) - synthesize_method (fn); - - if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0) - { - tree t = build_pointer_type (TREE_TYPE (fn)); - fn = build_vfn_ref (&TREE_VALUE (converted_args), - build_indirect_ref (TREE_VALUE (args), 0), - DECL_VINDEX (fn)); - TREE_TYPE (fn) = t; - } - else if (DECL_INLINE (fn)) - fn = inline_conversion (fn); - else - fn = build_addr_func (fn); - - fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args); - if (TREE_TYPE (fn) == void_type_node) - return fn; - return convert_from_reference (require_complete_type (fn)); -} - -/* Compare two implicit conversion sequences that differ only in their - qualification conversion. Subroutine of compare_ics. */ - -static int -compare_qual (ics1, ics2) - tree ics1, ics2; -{ - tree to1 = TREE_TYPE (ics1); - tree to2 = TREE_TYPE (ics2); - - to1 = TREE_TYPE (to1); - to2 = TREE_TYPE (to2); - - if (TREE_CODE (to1) == OFFSET_TYPE) - { - to1 = TREE_TYPE (to1); - to2 = TREE_TYPE (to2); - } - - 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; -} - -/* 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 main1, main2; - - if (ICS_RANK (ics1) > ICS_RANK (ics2)) - return -1; - else if (ICS_RANK (ics1) < ICS_RANK (ics2)) - return 1; - - /* User-defined conversion sequence U1 is a better conversion sequence - than another user-defined conversion sequence U2 if they contain the - same user-defined conversion operator or constructor and if the sec- - ond standard conversion sequence of U1 is better than the second - standard conversion sequence of U2. */ - - if (ICS_RANK (ics1) == USER_RANK) - { - tree t1, t2; - - for (t1 = ics1; TREE_CODE (t1) != USER_CONV; t1 = TREE_OPERAND (t1, 0)) - if (TREE_CODE (t1) == AMBIG_CONV) - return 0; - for (t2 = ics2; TREE_CODE (t2) != USER_CONV; t2 = TREE_OPERAND (t2, 0)) - if (TREE_CODE (t2) == AMBIG_CONV) - return 0; - - if (USER_CONV_FN (t1) != USER_CONV_FN (t2)) - 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 */ - } - -#if 0 /* Handled by ranking */ - /* 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. */ -#endif - - if (TREE_CODE (ics1) == QUAL_CONV) - main1 = TREE_OPERAND (ics1, 0); - else - main1 = ics1; - - if (TREE_CODE (ics2) == QUAL_CONV) - main2 = TREE_OPERAND (ics2, 0); - else - main2 = ics2; - - if (TREE_CODE (main1) != TREE_CODE (main2)) - return 0; - - if (TREE_CODE (main1) == IDENTITY_CONV - && (TREE_CODE (TREE_TYPE (main1)) == POINTER_TYPE - || TYPE_PTRMEMFUNC_P (TREE_TYPE (main1)))) - { - if (TREE_TYPE (main1) == TREE_TYPE (main2)) - return compare_qual (ics1, ics2); - -#if 0 /* This is now handled by making identity better than anything else. */ - /* existing practice, not WP-endorsed: const char * -> const char * - is better than char * -> const char *. (jason 6/29/96) */ - if (TREE_TYPE (ics1) == TREE_TYPE (ics2)) - return -compare_qual (main1, main2); -#endif - } - - if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV - || 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 (TYPE_PTRMEMFUNC_FN_TYPE (to1)); - from1 = TYPE_METHOD_BASETYPE (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) - { - to1 = TYPE_OFFSET_BASETYPE (to1); - from1 = TYPE_OFFSET_BASETYPE (from1); - } - } - - if (TYPE_PTRMEMFUNC_P (to2)) - { - to2 = TYPE_METHOD_BASETYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2)); - from2 = TYPE_METHOD_BASETYPE (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) - { - to2 = TYPE_OFFSET_BASETYPE (to2); - from2 = TYPE_OFFSET_BASETYPE (from2); - } - } - - if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2))) - return 0; - - /* The sense of pmem conversions is reversed from that of the other - conversions. */ - if (TREE_CODE (main1) == PMEM_CONV) - { - tree t = from1; from1 = from2; from2 = t; - t = to1; to1 = to2; to2 = t; - } - - distf = get_base_distance (from1, from2, 0, 0); - if (distf == -1) - { - distf = -get_base_distance (from2, from1, 0, 0); - if (distf == 1) - return 0; - } - - /* If class B is derived directly or indirectly from class A, - conver- sion 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 (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE) - { - if (distf > 0) - return 1; - else if (distf < 0) - return -1; - } - else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1) - && get_base_distance (to1, from1, 0, 0) != -1) - return 1; - else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2) - && get_base_distance (to2, from2, 0, 0) != -1) - 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 (distt == 1) - return 0; - } - - /* --conversion of C* to B* is better than conversion of C* to A*, */ - if (distf == 0) - { - if (distt > 0) - return -1; - else if (distt < 0) - return 1; - } - /* --conversion of B* to A* is better than conversion of C* to A*, */ - else if (distt == 0) - { - if (distf > 0) - return 1; - else if (distf < 0) - return -1; - } - } - 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 */ - -static 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), - TREE_VEC_ELT (cand2->convs, i)); - - if (comp != 0) - { - if (winner && comp != winner) - return 0; - winner = comp; - } - } - - 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; - else if (cand1->template && cand2->template) - winner = more_specialized - (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template)); - - /* 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 (! winner && cand1->second_conv) - winner = compare_ics (cand1->second_conv, cand2->second_conv); - - /* If the built-in candidates are the same, arbitrarily pick one. */ - if (! winner && cand1->fn == cand2->fn - && TREE_CODE (cand1->fn) == IDENTIFIER_NODE) - { - for (i = 0; i < TREE_VEC_LENGTH (cand1->convs); ++i) - if (! comptypes (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)), - TREE_TYPE (TREE_VEC_ELT (cand2->convs, i)), 1)) - break; - if (i == TREE_VEC_LENGTH (cand1->convs)) - return 1; - } - - 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. */ - -static struct z_candidate * -tourney (candidates) - struct z_candidate *candidates; -{ - struct z_candidate *champ = candidates, *challenger; - int fate; - - /* 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; ) - { - fate = joust (champ, challenger); - if (fate == 1) - challenger = challenger->next; - else - { - if (fate == 0) - { - champ = challenger->next; - if (champ == 0) - return 0; - } - else - champ = challenger; - - challenger = champ->next; - } - } - - /* 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) - { - fate = joust (champ, challenger); - if (fate != 1) - return 0; - } - - return champ; -} diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6aa922f3f86..98d3f14f8ec 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4912,9 +4912,7 @@ init_decl_processing () void_list_node = build_tree_list (NULL_TREE, void_type_node); TREE_PARMLIST (void_list_node) = 1; - null_pointer_node = build_int_2 (0, 0); TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node); - layout_type (TREE_TYPE (null_pointer_node)); /* Used for expressions that do nothing, but are not errors. */ void_zero_node = build_int_2 (0, 0); @@ -9864,6 +9862,10 @@ grokparms (first_parm, funcdef_flag) } else init = require_instantiated_type (type, init, integer_zero_node); + if (! current_template_parms + && ! implicit_conversion (type, TREE_TYPE (init), init, LOOKUP_NORMAL)) + cp_pedwarn ("invalid type `%T' for default argument to `%#D'", + TREE_TYPE (init), decl); } } else @@ -11962,7 +11964,7 @@ finish_function (lineno, call_poplevel, nested) pop_memoized_context (1); /* Must mark the RESULT_DECL as being in this function. */ - DECL_CONTEXT (DECL_RESULT (fndecl)) = DECL_INITIAL (fndecl); + DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; /* Obey `register' declarations if `setjmp' is called in this fn. */ if (flag_traditional && current_function_calls_setjmp) @@ -12303,15 +12305,14 @@ hack_incomplete_structures (type) } /* If DECL is of a type which needs a cleanup, build that cleanup here. - We don't build cleanups if just going for syntax checking, since - fixup_cleanups does not know how to not handle them. + See build_delete for information about AUTO_DELETE. Don't build these on the momentary obstack; they must live the life of the binding contour. */ -tree -maybe_build_cleanup (decl) - tree decl; +static tree +maybe_build_cleanup_1 (decl, auto_delete) + tree decl, auto_delete; { tree type = TREE_TYPE (decl); if (TYPE_NEEDS_DESTRUCTOR (type)) @@ -12335,7 +12336,7 @@ maybe_build_cleanup (decl) || flag_expensive_optimizations) flags |= LOOKUP_NONVIRTUAL; - rval = build_delete (TREE_TYPE (rval), rval, integer_two_node, flags, 0); + rval = build_delete (TREE_TYPE (rval), rval, auto_delete, flags, 0); if (TYPE_USES_VIRTUAL_BASECLASSES (type) && ! TYPE_HAS_DESTRUCTOR (type)) @@ -12352,6 +12353,26 @@ maybe_build_cleanup (decl) } return 0; } + +/* If DECL is of a type which needs a cleanup, build that cleanup + here. The cleanup does free the storage with a call to delete. */ + +tree +maybe_build_cleanup_and_delete (decl) + tree decl; +{ + return maybe_build_cleanup_1 (decl, integer_three_node); +} + +/* If DECL is of a type which needs a cleanup, build that cleanup + here. The cleanup does not free the storage with a call a delete. */ + +tree +maybe_build_cleanup (decl) + tree decl; +{ + return maybe_build_cleanup_1 (decl, integer_two_node); +} /* Expand a C++ expression at the statement level. This is needed to ferret out nodes which have UNKNOWN_TYPE. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 632ce767c03..b4de01b9e3d 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -125,6 +125,15 @@ int flag_no_ident; int flag_ansi; +/* Nonzero means do argument matching for overloading according to the + ANSI rules, rather than what g++ used to believe to be correct. */ + +#ifdef NEW_OVER +int flag_ansi_overloading = 1; +#else +int flag_ansi_overloading; +#endif + /* Nonzero means do emit exported implementations of functions even if they can be inlined. */ @@ -157,7 +166,11 @@ int warn_ctor_dtor_privacy = 1; /* True if we want to implement vtables using "thunks". The default is off. */ +#if defined(NEW_OVER) && defined (__i386__) +int flag_vtable_thunks = 1; +#else int flag_vtable_thunks; +#endif /* True if we want to deal with repository information. */ @@ -410,6 +423,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] = {"implement-inlines", &flag_implement_inlines, 1}, {"external-templates", &flag_external_templates, 1}, {"implicit-templates", &flag_implicit_templates, 1}, + {"ansi-overloading", &flag_ansi_overloading, 1}, {"huge-objects", &flag_huge_objects, 1}, {"conserve-space", &flag_conserve_space, 1}, {"vtable-thunks", &flag_vtable_thunks, 1}, @@ -2562,7 +2576,7 @@ import_export_template (type) } } -static int +int finish_prevtable_vardecl (prev, vars) tree prev, vars; { diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 4dd7e6096d3..964f8c05ce7 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1539,9 +1539,20 @@ args_as_string (p, v) int v; { if (p == NULL_TREE) - return "..."; + return ""; - return type_as_string (p, v); + if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't') + return type_as_string (p, v); + + OB_INIT (); + for (; p; p = TREE_CHAIN (p)) + { + dump_type (TREE_TYPE (TREE_VALUE (p)), v); + if (TREE_CHAIN (p)) + OB_PUTS (", "); + } + OB_FINISH (); + return (char *)obstack_base (&scratch_obstack); } char * diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 1d207e54664..257ec113a12 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1079,7 +1079,7 @@ expand_throw (exp) start_sequence (); object = build_reinterpret_cast (TREE_TYPE (exp), saved_throw_value); object = build_indirect_ref (object, NULL_PTR); - cleanup = maybe_build_cleanup (object); + cleanup = maybe_build_cleanup_and_delete (object); if (cleanup) expand_expr (cleanup, const0_rtx, VOIDmode, 0); cleanup_insns = get_insns (); @@ -1089,7 +1089,8 @@ expand_throw (exp) { cleanup = start_anon_func (); - expand_expr (maybe_build_cleanup (object), const0_rtx, VOIDmode, 0); + expand_expr (maybe_build_cleanup_and_delete (object), + const0_rtx, VOIDmode, 0); end_anon_func (); diff --git a/gcc/cp/gxx.gperf b/gcc/cp/gxx.gperf index e5465e89b48..f846f5ce508 100644 --- a/gcc/cp/gxx.gperf +++ b/gcc/cp/gxx.gperf @@ -15,6 +15,7 @@ __extension__, EXTENSION, NORID __inline, SCSPEC, RID_INLINE __inline__, SCSPEC, RID_INLINE __label__, LABEL, NORID +__null, CONSTANT, RID_NULL __signature__, AGGR, RID_SIGNATURE /* Extension */, __signed, TYPESPEC, RID_SIGNED __signed__, TYPESPEC, RID_SIGNED diff --git a/gcc/cp/hash.h b/gcc/cp/hash.h index 4848aba4775..d8bdc06ee2b 100644 --- a/gcc/cp/hash.h +++ b/gcc/cp/hash.h @@ -1,14 +1,14 @@ /* C code produced by gperf version 2.5 (GNU C++ version) */ -/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ ../../../devo/gcc/cp/gxx.gperf */ +/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ /yorick/splunge/jason/g++/small/devo/gcc/cp/gxx.gperf */ /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */ struct resword { char *name; short token; enum rid rid;}; -#define TOTAL_KEYWORDS 97 +#define TOTAL_KEYWORDS 98 #define MIN_WORD_LENGTH 2 #define MAX_WORD_LENGTH 16 #define MIN_HASH_VALUE 4 -#define MAX_HASH_VALUE 219 -/* maximum key range = 216, duplicates = 0 */ +#define MAX_HASH_VALUE 258 +/* maximum key range = 255, duplicates = 0 */ #ifdef __GNUC__ inline @@ -18,21 +18,21 @@ hash (str, len) register char *str; register int unsigned len; { - static unsigned char asso_values[] = + static unsigned short asso_values[] = { - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 0, 220, 88, 16, 19, - 52, 0, 9, 72, 1, 77, 220, 0, 0, 38, - 13, 44, 38, 30, 27, 57, 1, 14, 0, 2, - 2, 7, 220, 220, 220, 220, 220, 220, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 259, 259, 259, 259, 259, + 259, 259, 259, 259, 259, 0, 259, 27, 17, 20, + 40, 0, 64, 6, 10, 89, 259, 2, 110, 44, + 13, 107, 40, 10, 18, 55, 1, 3, 5, 17, + 2, 4, 259, 259, 259, 259, 259, 259, }; register int hval = len; @@ -49,6 +49,7 @@ hash (str, len) case 2: case 1: hval += asso_values[str[0]]; + break; } return hval + asso_values[str[len - 1]]; } @@ -66,143 +67,150 @@ is_reserved_word (str, len) {"",}, {"",}, {"",}, {"",}, {"else", ELSE, NORID,}, {"true", CXX_TRUE, NORID,}, - {"",}, - {"while", WHILE, NORID,}, - {"virtual", SCSPEC, RID_VIRTUAL,}, {"",}, {"",}, {"try", TRY, NORID,}, - {"",}, {"",}, {"",}, {"",}, - {"typeof", TYPEOF, NORID,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"not", '!', NORID,}, - {"new", NEW, NORID,}, + {"xor_eq", ASSIGN, NORID,}, {"extern", SCSPEC, RID_EXTERN,}, - {"bool", TYPESPEC, RID_BOOL,}, - {"",}, {"",}, + {"",}, {"",}, {"",}, + {"xor", '^', NORID,}, {"case", CASE, NORID,}, - {"__alignof__", ALIGNOF, NORID}, - {"",}, - {"typedef", SCSPEC, RID_TYPEDEF,}, - {"",}, + {"",}, {"",}, + {"using", USING, NORID,}, {"__extension__", EXTENSION, NORID}, + {"not_eq", EQCOMPARE, NORID,}, {"",}, {"",}, - {"__alignof", ALIGNOF, NORID}, - {"xor", '^', NORID,}, - {"",}, + {"continue", CONTINUE, NORID,}, + {"new", NEW, NORID,}, {"__inline", SCSPEC, RID_INLINE}, {"",}, {"__inline__", SCSPEC, RID_INLINE}, - {"",}, - {"xor_eq", ASSIGN, NORID,}, - {"for", FOR, NORID,}, + {"",}, {"",}, {"",}, + {"return", RETURN, NORID,}, {"",}, {"",}, - {"continue", CONTINUE, NORID,}, - {"",}, - {"catch", CATCH, NORID,}, - {"private", VISSPEC, RID_PRIVATE,}, - {"",}, - {"typename", TYPENAME_KEYWORD, NORID,}, - {"template", TEMPLATE, RID_TEMPLATE,}, - {"not_eq", EQCOMPARE, NORID,}, + {"and_eq", ASSIGN, NORID,}, {"",}, {"",}, - {"throw", THROW, NORID,}, - {"__const", TYPE_QUAL, RID_CONST}, - {"__const__", TYPE_QUAL, RID_CONST}, - {"__volatile", TYPE_QUAL, RID_VOLATILE}, - {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,}, - {"__volatile__", TYPE_QUAL, RID_VOLATILE}, {"delete", DELETE, NORID,}, {"typeid", TYPEID, NORID,}, - {"return", RETURN, NORID,}, - {"__typeof__", TYPEOF, NORID}, - {"compl", '~', NORID,}, - {"public", VISSPEC, RID_PUBLIC,}, - {"__asm__", GCC_ASM_KEYWORD, NORID}, - {"switch", SWITCH, NORID,}, + {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,}, + {"namespace", NAMESPACE, NORID,}, + {"template", TEMPLATE, RID_TEMPLATE,}, + {"break", BREAK, NORID,}, + {"private", VISSPEC, RID_PRIVATE,}, + {"typename", TYPENAME_KEYWORD, NORID,}, {"",}, - {"friend", SCSPEC, RID_FRIEND,}, - {"__typeof", TYPEOF, NORID}, + {"catch", CATCH, NORID,}, + {"",}, {"",}, {"",}, {"",}, + {"char", TYPESPEC, RID_CHAR,}, {"",}, - {"static_cast", STATIC_CAST, NORID,}, - {"false", CXX_FALSE, NORID,}, - {"sizeof", SIZEOF, NORID,}, - {"or", OROR, NORID,}, + {"__asm__", GCC_ASM_KEYWORD, NORID}, {"double", TYPESPEC, RID_DOUBLE,}, {"",}, - {"union", AGGR, RID_UNION,}, - {"char", TYPESPEC, RID_CHAR,}, {"struct", AGGR, RID_RECORD,}, - {"or_eq", ASSIGN, NORID,}, - {"enum", ENUM, NORID,}, - {"int", TYPESPEC, RID_INT,}, - {"const", TYPE_QUAL, RID_CONST,}, - {"static", SCSPEC, RID_STATIC,}, {"reinterpret_cast", REINTERPRET_CAST, NORID,}, {"",}, - {"explicit", SCSPEC, RID_EXPLICIT,}, - {"__signed__", TYPESPEC, RID_SIGNED}, - {"if", IF, NORID,}, - {"__attribute", ATTRIBUTE, NORID}, + {"static_cast", STATIC_CAST, NORID,}, + {"",}, + {"and", ANDAND, NORID,}, + {"typeof", TYPEOF, NORID,}, + {"switch", SWITCH, NORID,}, + {"",}, + {"asm", ASM_KEYWORD, NORID,}, + {"",}, + {"default", DEFAULT, NORID,}, + {"",}, + {"mutable", SCSPEC, RID_MUTABLE,}, {"short", TYPESPEC, RID_SHORT,}, - {"__attribute__", ATTRIBUTE, NORID}, - {"bitor", '|', NORID,}, {"signature", AGGR, RID_SIGNATURE /* Extension */,}, + {"const", TYPE_QUAL, RID_CONST,}, + {"static", SCSPEC, RID_STATIC,}, + {"",}, {"",}, + {"for", FOR, NORID,}, + {"",}, {"",}, {"",}, + {"void", TYPESPEC, RID_VOID,}, + {"bitand", '&', NORID,}, + {"protected", VISSPEC, RID_PROTECTED,}, + {"enum", ENUM, NORID,}, + {"int", TYPESPEC, RID_INT,}, + {"",}, {"",}, {"",}, + {"float", TYPESPEC, RID_FLOAT,}, {"",}, - {"__sigof__", SIGOF, NORID /* Extension */,}, - {"volatile", TYPE_QUAL, RID_VOLATILE,}, - {"__label__", LABEL, NORID}, - {"do", DO, NORID,}, + {"__signed__", TYPESPEC, RID_SIGNED}, + {"dynamic_cast", DYNAMIC_CAST, NORID,}, + {"__attribute", ATTRIBUTE, NORID}, {"",}, + {"__attribute__", ATTRIBUTE, NORID}, {"__asm", GCC_ASM_KEYWORD, NORID}, - {"protected", VISSPEC, RID_PROTECTED,}, - {"",}, - {"float", TYPESPEC, RID_FLOAT,}, - {"using", USING, NORID,}, {"",}, {"const_cast", CONST_CAST, NORID,}, - {"",}, - {"void", TYPESPEC, RID_VOID,}, - {"break", BREAK, NORID,}, - {"namespace", NAMESPACE, NORID,}, - {"",}, {"",}, {"",}, {"",}, - {"sigof", SIGOF, NORID /* Extension */,}, {"",}, {"",}, {"",}, - {"this", THIS, NORID,}, - {"",}, {"",}, {"",}, {"",}, - {"and_eq", ASSIGN, NORID,}, + {"friend", SCSPEC, RID_FRIEND,}, {"",}, {"",}, {"",}, {"signed", TYPESPEC, RID_SIGNED,}, - {"asm", ASM_KEYWORD, NORID,}, - {"",}, {"",}, {"",}, - {"mutable", SCSPEC, RID_MUTABLE,}, - {"",}, {"",}, {"",}, - {"__signed", TYPESPEC, RID_SIGNED}, - {"class", AGGR, RID_CLASS,}, - {"register", SCSPEC, RID_REGISTER,}, - {"",}, {"",}, {"",}, - {"and", ANDAND, NORID,}, - {"",}, {"",}, {"",}, {"",}, - {"long", TYPESPEC, RID_LONG,}, - {"default", DEFAULT, NORID,}, - {"operator", OPERATOR, NORID,}, - {"unsigned", TYPESPEC, RID_UNSIGNED,}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"inline", SCSPEC, RID_INLINE,}, + {"this", THIS, NORID,}, + {"__const", TYPE_QUAL, RID_CONST}, + {"__const__", TYPE_QUAL, RID_CONST}, + {"__volatile", TYPE_QUAL, RID_VOLATILE}, + {"__null", CONSTANT, RID_NULL}, + {"__volatile__", TYPE_QUAL, RID_VOLATILE}, + {"__typeof__", TYPEOF, NORID}, + {"or_eq", ASSIGN, NORID,}, {"",}, - {"bitand", '&', NORID,}, + {"false", CXX_FALSE, NORID,}, + {"sizeof", SIZEOF, NORID,}, + {"long", TYPESPEC, RID_LONG,}, + {"or", OROR, NORID,}, + {"union", AGGR, RID_UNION,}, + {"__signature__", AGGR, RID_SIGNATURE /* Extension */,}, + {"throw", THROW, NORID,}, {"",}, - {"goto", GOTO, NORID,}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"dynamic_cast", DYNAMIC_CAST, NORID,}, + {"while", WHILE, NORID,}, + {"register", SCSPEC, RID_REGISTER,}, + {"__alignof__", ALIGNOF, NORID}, + {"class", AGGR, RID_CLASS,}, + {"typedef", SCSPEC, RID_TYPEDEF,}, + {"__signed", TYPESPEC, RID_SIGNED}, + {"",}, {"",}, + {"unsigned", TYPESPEC, RID_UNSIGNED,}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"__signature__", AGGR, RID_SIGNATURE /* Extension */,}, + {"__label__", LABEL, NORID}, + {"bitor", '|', NORID,}, {"",}, - {"auto", SCSPEC, RID_AUTO,}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, - {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"do", DO, NORID,}, + {"volatile", TYPE_QUAL, RID_VOLATILE,}, + {"",}, {"",}, {"",}, {"",}, + {"if", IF, NORID,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"__sigof__", SIGOF, NORID /* Extension */,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, + {"compl", '~', NORID,}, + {"public", VISSPEC, RID_PUBLIC,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"__typeof", TYPEOF, NORID}, + {"inline", SCSPEC, RID_INLINE,}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"__alignof", ALIGNOF, NORID}, + {"",}, {"",}, {"",}, {"overload", OVERLOAD, NORID,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"explicit", SCSPEC, RID_EXPLICIT,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"goto", GOTO, NORID,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"sigof", SIGOF, NORID /* Extension */,}, + {"",}, + {"virtual", SCSPEC, RID_VIRTUAL,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"bool", TYPESPEC, RID_BOOL,}, + {"",}, {"",}, {"",}, + {"auto", SCSPEC, RID_AUTO,}, + {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, + {"",}, {"",}, {"",}, + {"operator", OPERATOR, NORID,}, }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 62e3909c86b..1d49c409bea 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1541,9 +1541,14 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) { tree rval = build_type_conversion (CONVERT_EXPR, type, init, 1); - if (rval) + if (flag_ansi_overloading && rval) + { + if (rval != error_mark_node) + expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags); + return; + } + else if (rval) { -#ifndef NEW_OVER /* See if there is a constructor for``type'' that takes a ``ttype''-typed object. */ tree parms = build_tree_list (NULL_TREE, init); @@ -1557,9 +1562,8 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags) cp_error ("ambiguity between conversion to `%T' and constructor", type); else -#endif - if (rval != error_mark_node) - expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags); + if (rval != error_mark_node) + expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags); return; } } diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 56cf159cdc9..66e00463e32 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -673,6 +673,9 @@ init_lex () TREE_TYPE (signature_type_node) = signature_type_node; ridpointers[(int) RID_SIGNATURE] = signature_type_node; + null_pointer_node = build_int_2 (0, 0); + ridpointers[RID_NULL] = null_pointer_node; + opname_tab[(int) COMPONENT_REF] = "->"; opname_tab[(int) MEMBER_REF] = "->*"; opname_tab[(int) METHOD_CALL_EXPR] = "->()"; @@ -2561,7 +2564,7 @@ do_identifier (token, parsing) else if (IDENTIFIER_OPNAME_P (token)) { if (token != ansi_opname[ERROR_MARK]) - cp_error ("operator %O not defined", token); + cp_error ("`%D' not defined", token); id = error_mark_node; } else if (parsing && (yychar == '(' || yychar == LEFT_RIGHT)) diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h index 1c20f596f9a..4a2c7d133d2 100644 --- a/gcc/cp/lex.h +++ b/gcc/cp/lex.h @@ -72,6 +72,7 @@ enum rid RID_EXCEPTION, RID_TEMPLATE, RID_SIGNATURE, + RID_NULL, /* Before adding enough to get up to 64, the RIDBIT_* macros will have to be changed a little. */ RID_MAX diff --git a/gcc/cp/method.c b/gcc/cp/method.c index bb8a2046688..64563438e7e 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -674,7 +674,14 @@ build_overload_name (parmtypes, begin, end) if (TREE_USED (parmtype)) { +#if 0 + /* We can turn this on at some point when we want + improved symbol mangling. */ + nrepeats++; +#else + /* This is bug compatible with 2.7.x */ flush_repeats (parmtype); +#endif goto next; } @@ -1193,9 +1200,8 @@ build_opfncall (code, flags, xarg1, xarg2, arg3) int try_second; int binary_is_unary; -#ifdef NEW_OVER - return build_new_op (code, flags, xarg1, xarg2, arg3); -#endif + if (flag_ansi_overloading) + return build_new_op (code, flags, xarg1, xarg2, arg3); if (xarg1 == error_mark_node) return error_mark_node; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d86e852f401..40a4582332e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1189,10 +1189,15 @@ instantiate_class_template (type) tree tmp; for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp)) if (TREE_CODE (tmp) == FIELD_DECL) - require_complete_type (tmp); + { + TREE_TYPE (tmp) = complete_type (TREE_TYPE (tmp)); + require_complete_type (tmp); + } type = finish_struct_1 (type, 0); CLASSTYPE_GOT_SEMICOLON (type) = 1; + if (at_eof && TYPE_BINFO_VTABLE (type) != NULL_TREE) + finish_prevtable_vardecl (NULL, TYPE_BINFO_VTABLE (type)); repo_template_used (type); } @@ -2707,13 +2712,11 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts, strict) if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm)) { tree t = NULL_TREE; -#ifdef NEW_OVER - if (! strict) + if (flag_ansi_overloading && ! strict) t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg); - else -#endif - if (CLASSTYPE_TEMPLATE_INFO (arg) - && CLASSTYPE_TI_TEMPLATE (parm) == CLASSTYPE_TI_TEMPLATE (arg)) + else if + (CLASSTYPE_TEMPLATE_INFO (arg) + && CLASSTYPE_TI_TEMPLATE (parm) == CLASSTYPE_TI_TEMPLATE (arg)) t = arg; if (! t || t == error_mark_node) return 1; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index ed7843329ec..ebb692ddef7 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -3087,8 +3087,8 @@ build_mi_matrix (type) dfs_walk (binfo, dfs_number, unnumberedp); mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type); - if (mi_size < cid) - mi_size = cid; + if (mi_size < (cid-1)) + mi_size = cid-1; mi_matrix = (char *)xmalloc ((mi_size + 1) * (mi_size + 1)); mi_type = type; bzero (mi_matrix, (mi_size + 1) * (mi_size + 1)); @@ -3551,6 +3551,7 @@ add_conversions (binfo) break; conversions = tree_cons (binfo, tmp, conversions); } + SET_BINFO_MARKED (binfo); } tree @@ -3559,7 +3560,10 @@ lookup_conversions (type) { conversions = NULL_TREE; if (TYPE_SIZE (type)) - dfs_walk (TYPE_BINFO (type), add_conversions, 0); + { + dfs_walk (TYPE_BINFO (type), add_conversions, unmarkedp); + dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp); + } return conversions; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 775e2c81318..a43443bd7fe 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -135,6 +135,10 @@ complete_type (type) if (TYPE_SIZE (t) != NULL_TREE && current_template_parms == NULL_TREE) layout_type (type); + TYPE_NEEDS_CONSTRUCTING (type) + = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t)); + TYPE_NEEDS_DESTRUCTOR (type) + = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t)); } else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) instantiate_class_template (TYPE_MAIN_VARIANT (type)); @@ -771,7 +775,7 @@ comptypes (type1, type2, strict) { int rval; look_hard: - rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2); + rval = t1 == t2 || DERIVED_FROM_P (t1, t2); if (rval) { @@ -780,7 +784,7 @@ comptypes (type1, type2, strict) } if (strict < 0) { - val = UNIQUELY_DERIVED_FROM_P (t2, t1); + val = DERIVED_FROM_P (t2, t1); break; } } @@ -2239,8 +2243,12 @@ build_x_function_call (function, params, decl) /* Handle methods, friends, and overloaded functions, respectively. */ if (is_method) { + tree basetype = NULL_TREE; + if (TREE_CODE (function) == FUNCTION_DECL) { + basetype = DECL_CLASS_CONTEXT (function); + if (DECL_NAME (function)) function = DECL_NAME (function); else @@ -2249,6 +2257,7 @@ build_x_function_call (function, params, decl) else if (TREE_CODE (function) == TREE_LIST) { my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312); + basetype = DECL_CLASS_CONTEXT (TREE_VALUE (function)); function = TREE_PURPOSE (function); } else if (TREE_CODE (function) != IDENTIFIER_NODE) @@ -2276,6 +2285,10 @@ build_x_function_call (function, params, decl) must go through here in case it is a virtual function. @@ Perhaps this could be optimized. */ + if (basetype && (! current_class_type + || ! DERIVED_FROM_P (basetype, current_class_type))) + return build_member_call (basetype, function, params); + if (decl == NULL_TREE) { if (current_class_type == NULL_TREE) @@ -2315,11 +2328,11 @@ build_x_function_call (function, params, decl) } else { -#ifdef NEW_OVER - return build_new_function_call (function, params, NULL_TREE); -#else tree val = TREE_VALUE (function); + if (flag_ansi_overloading) + return build_new_function_call (function, params, NULL_TREE); + if (TREE_CODE (val) == TEMPLATE_DECL) return build_overload_call_real (function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0); @@ -2328,7 +2341,6 @@ build_x_function_call (function, params, decl) (function, params, LOOKUP_COMPLAIN); else my_friendly_abort (360); -#endif } } @@ -2628,6 +2640,8 @@ build_function_call_real (function, params, require_complete, flags) return result; result = require_complete_type (result); } + if (IS_AGGR_TYPE (value_type)) + result = build_cplus_new (value_type, result); return convert_from_reference (result); } } @@ -2899,6 +2913,9 @@ build_x_binary_op (code, arg1, arg2) if (current_template_parms) return build_min_nt (code, arg1, arg2); + if (flag_ansi_overloading) + return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE); + rval = build_opfncall (code, LOOKUP_SPECULATIVELY, arg1, arg2, NULL_TREE); if (rval) @@ -3955,11 +3972,23 @@ build_x_unary_op (code, xarg) /* don't look for a function */; else { - tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, - NULL_TREE, NULL_TREE); - if (rval) - return build_opfncall (code, LOOKUP_NORMAL, xarg, + tree rval; + + if (flag_ansi_overloading) + { + rval = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE); + if (rval || code != ADDR_EXPR) + return rval; + } + else + { + rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, + NULL_TREE, NULL_TREE); + if (rval) + return build_opfncall (code, LOOKUP_NORMAL, xarg, + NULL_TREE, NULL_TREE); + } } if (code == ADDR_EXPR) @@ -4629,6 +4658,9 @@ build_x_conditional_expr (ifexp, op1, op2) if (current_template_parms) return build_min_nt (COND_EXPR, ifexp, op1, op2); + if (flag_ansi_overloading) + return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2); + /* See comments in `build_x_binary_op'. */ if (op1 != 0) rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2); @@ -4723,6 +4755,15 @@ build_conditional_expr (ifexp, op1, op2) result = fold (build (COND_EXPR, type1, ifexp, op1, op2)); if (TREE_TYPE (result) != type1) result = build1 (NOP_EXPR, type1, result); + /* Expand both sides into the same slot, + hopefully the target of the ?: expression. */ + if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR) + { + tree slot = build (VAR_DECL, TREE_TYPE (result)); + layout_decl (slot, 0); + result = build (TARGET_EXPR, TREE_TYPE (result), + slot, result, NULL_TREE, NULL_TREE); + } return result; } @@ -6093,12 +6134,7 @@ build_ptrmemfunc (type, pfn, force) if (TREE_CODE (pfn) == TREE_LIST || (TREE_CODE (pfn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST)) - { - pfn = instantiate_type (type, pfn, 1); - if (pfn == error_mark_node) - return error_mark_node; - pfn = build_addr_func (pfn); - } + return instantiate_type (type, pfn, 1); /* Allow pointer to member conversions here. */ delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))), @@ -6354,7 +6390,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) if (TYPE_MAIN_VARIANT (ttl) != void_type_node && TYPE_MAIN_VARIANT (ttr) == void_type_node - && rhs != null_pointer_node) + && ! null_ptr_cst_p (rhs)) { if (coder == RECORD_TYPE) cp_pedwarn ("implicit conversion of signature pointer to type `%T'", @@ -6545,9 +6581,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) else cp_pedwarn ("%s to `%T' from `%T' lacks a cast", errtype, type, rhstype); - return convert (type, rhs); } - return null_pointer_node; + return convert (type, rhs); } else if (codel == INTEGER_TYPE && (coder == POINTER_TYPE |