/* * Copyright (c) 2002, The Tendra Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * Crown Copyright (c) 1997 * * This TenDRA(r) Computer Program is subject to Copyright * owned by the United Kingdom Secretary of State for Defence * acting through the Defence Evaluation and Research Agency * (DERA). It is made available to Recipients with a * royalty-free licence for its use, reproduction, transfer * to other parties and amendment for any purpose not excluding * product development provided that any such use et cetera * shall be deemed to be acceptance of the following conditions:- * * (1) Its Recipients shall ensure that this Notice is * reproduced upon any copies or amended versions of it; * * (2) Any amended version of it shall be clearly marked to * show both the nature of and the organisation responsible * for the relevant amendment or amendments; * * (3) Its onward transfer from a recipient to another * party shall be deemed to be that party's acceptance of * these conditions; * * (4) DERA gives no warranty or assurance as to its * quality or suitability for any purpose and DERA accepts * no liability whatsoever in relation to any use to which * it may be put. * * $TenDRA: tendra/src/producers/common/construct/overload.c,v 1.8 2004/08/15 11:13:35 bp Exp $ */ #include "config.h" #include "producer.h" #include "fmm.h" #include "msgcat.h" #include "c_types.h" #include "ctype_ops.h" #include "etype_ops.h" #include "exp_ops.h" #include "graph_ops.h" #include "hashid_ops.h" #include "id_ops.h" #include "itype_ops.h" #include "member_ops.h" #include "nspace_ops.h" #include "tok_ops.h" #include "type_ops.h" #include "error.h" #include "catalog.h" #include "assign.h" #include "basetype.h" #include "cast.h" #include "chktype.h" #include "class.h" #include "construct.h" #include "convert.h" #include "copy.h" #include "declare.h" #include "derive.h" #include "destroy.h" #include "dump.h" #include "exception.h" #include "expression.h" #include "function.h" #include "hash.h" #include "identifier.h" #include "initialise.h" #include "instance.h" #include "namespace.h" #include "operator.h" #include "option.h" #include "overload.h" #include "predict.h" #include "syntax.h" #include "template.h" #include "tokdef.h" #include "token.h" #include "ustring.h" /* * CANDIDATE LIST * * This variable gives the main candidate list used in overload resolution. */ CANDIDATE_LIST candidates = { NULL, 0, 0, NULL, 0 }; /* * ADD A CANDIDATE TO A LIST * * This routine adds the candidate given by id, bid and kind to the * candidate list p. */ static void add_candidate(CANDIDATE_LIST *p, IDENTIFIER id, IDENTIFIER bid, int kind) { CANDIDATE *q = p->elem; unsigned n = p->size; unsigned m = p->max_size; if (n >= m) { /* Increase size if necessary */ m += 200; q = xrealloc (q, sizeof(*q) * m); p->elem = q; p->max_size = m; } q [n].func = id; q [n].base = bid; q [n].kind = kind; q [n].rank = RANK_NONE; q [n].convs = NULL; q [n].cond = NULL_exp; p->size = n + 1; return; } /* * ADD AN IDENTIFIER TO A CANDIDATE LIST * * This routine adds the overloaded function identifier id to the candidate * list given by p. The kind argument is stored in the kind field of each * candidate. The table of candidate functions may need extending. Note * that the candidates are added in the reverse order in which they were * declared. */ void add_candidates(CANDIDATE_LIST *p, IDENTIFIER id, int over, int kind) { unsigned tag = TAG_id (id); switch (tag) { case id_function_tag : case id_mem_func_tag : case id_stat_mem_func_tag : { /* Functions */ while (!IS_NULL_id (id)) { IDENTIFIER bid = DEREF_id (id_alias (id)); add_candidate (p, id, bid, kind); if (!over) break; id = DEREF_id (id_function_etc_over (id)); } break; } case id_builtin_tag : { /* Built-in operators */ add_candidate (p, id, id, kind); break; } case id_ambig_tag : { /* Ambiguous functions */ LIST (IDENTIFIER) r = DEREF_list (id_ambig_ids (id)); if (over) over = DEREF_int (id_ambig_over (id)); while (!IS_NULL_list (r)) { IDENTIFIER rid = DEREF_id (HEAD_list (r)); add_candidates (p, rid, over, kind); r = TAIL_list (r); } break; } } return; } /* * LOOK UP A FUNCTION IN AN ARGUMENT NAMESPACE * * This routine looks up the function id in the namespace containing the * type name cid. Any functions found are added to the candidate list p. */ static IDENTIFIER koenig_id(CANDIDATE_LIST *p, IDENTIFIER id, IDENTIFIER cid, int kind) { if (!IS_NULL_id (cid)) { NAMESPACE cns = DEREF_nspace (id_parent (cid)); if (!IS_NULL_nspace (cns)) { switch (TAG_nspace (cns)) { case nspace_named_tag : case nspace_unnamed_tag : case nspace_global_tag : { /* Look up identifier in parent class */ HASHID nm = DEREF_hashid (id_name (id)); MEMBER mem = search_member (cns, nm, 0); if (!IS_NULL_member (mem)) { IDENTIFIER fid = DEREF_id (member_id (mem)); if (!IS_NULL_id (fid) && !EQ_id (fid, id)) { add_candidates (p, fid, 1, kind); id = fid; } } break; } case nspace_ctype_tag : { /* Allow for nested classes */ IDENTIFIER pid = DEREF_id (nspace_name (cns)); id = koenig_id (p, id, pid, kind); break; } } } } return (id); } /* * PERFORM ARGUMENT DEPENDENT NAME LOOK-UP FOR A CLASS * * This routine performs argument dependent name look-up for the function * id and the argument class type ct. */ static IDENTIFIER koenig_class(CANDIDATE_LIST *p, IDENTIFIER id, CLASS_TYPE ct, int kind) { TYPE form = DEREF_type (ctype_form (ct)); if (IS_NULL_type (form)) { IDENTIFIER cid = DEREF_id (ctype_name (ct)); GRAPH gr = DEREF_graph (ctype_base (ct)); LIST (GRAPH) br = DEREF_list (graph_tails (gr)); id = koenig_id (p, id, cid, kind); while (!IS_NULL_list (br)) { GRAPH gs = DEREF_graph (HEAD_list (br)); CLASS_TYPE cs = DEREF_ctype (graph_head (gs)); id = koenig_class (p, id, cs, kind); br = TAIL_list (br); } } else { id = koenig_candidates (p, id, form, kind); } return (id); } /* * PERFORM ARGUMENT DEPENDENT NAME LOOK-UP FOR A TOKEN ARGUMENT * * This routine performs argument dependent name look-up for the function * id and the token argument tok. */ static IDENTIFIER koenig_token(CANDIDATE_LIST *p, IDENTIFIER id, TOKEN tok, int kind) { if (!IS_NULL_tok (tok)) { ASSERT (ORDER_tok == 10); switch (TAG_tok (tok)) { case tok_type_tag : { TYPE t = DEREF_type (tok_type_value (tok)); id = koenig_candidates (p, id, t, kind); break; } case tok_class_tag : { IDENTIFIER tid = DEREF_id (tok_class_value (tok)); id = koenig_id (p, id, tid, kind); break; } } } return (id); } /* * PERFORM ARGUMENT DEPENDENT NAME LOOK-UP * * This routine performs argument dependent name look-up for the function * id and the argument type t, adding any candidates found to the list p. */ IDENTIFIER koenig_candidates(CANDIDATE_LIST *p, IDENTIFIER id, TYPE t, int kind) { if (!IS_NULL_type (t)) { ASSERT (ORDER_type == 18); switch (TAG_type (t)) { case type_ptr_tag : case type_ref_tag : { TYPE s = DEREF_type (type_ptr_etc_sub (t)); id = koenig_candidates (p, id, s, kind); break; } case type_ptr_mem_tag : { CLASS_TYPE cs = DEREF_ctype (type_ptr_mem_of (t)); TYPE s = DEREF_type (type_ptr_mem_sub (t)); id = koenig_class (p, id, cs, kind); id = koenig_candidates (p, id, s, kind); break; } case type_func_tag : { TYPE r = DEREF_type (type_func_ret (t)); LIST (TYPE) q = DEREF_list (type_func_ptypes (t)); id = koenig_candidates (p, id, r, kind); while (!IS_NULL_list (q)) { TYPE s = DEREF_type (HEAD_list (q)); id = koenig_candidates (p, id, s, kind); q = TAIL_list (q); } break; } case type_array_tag : { TYPE s = DEREF_type (type_array_sub (t)); id = koenig_candidates (p, id, s, kind); break; } case type_compound_tag : { CLASS_TYPE ct = DEREF_ctype (type_compound_defn (t)); id = koenig_class (p, id, ct, kind); break; } case type_enumerate_tag : { ENUM_TYPE et = DEREF_etype (type_enumerate_defn (t)); IDENTIFIER eid = DEREF_id (etype_name (et)); id = koenig_id (p, id, eid, kind); break; } case type_token_tag : { IDENTIFIER tid = DEREF_id (type_token_tok (t)); LIST (TOKEN) args = DEREF_list (type_token_args (t)); if (IS_id_token (tid)) { tid = DEREF_id (id_token_alt (tid)); } id = koenig_id (p, id, tid, kind); while (!IS_NULL_list (args)) { TOKEN arg = DEREF_tok (HEAD_list (args)); id = koenig_token (p, id, arg, kind); args = TAIL_list (args); } break; } case type_templ_tag : { TYPE s = DEREF_type (type_templ_defn (t)); id = koenig_candidates (p, id, s, kind); break; } } } return (id); } /* * FREE A LIST OF CANDIDATES * * This routine frees the elements of the candidate list p. */ void free_candidates(CANDIDATE_LIST *p) { xfree (p->elem); xfree (p->convs); p->elem = NULL; p->size = 0; p->max_size = 0; p->convs = NULL; p->nconvs = 0; return; } /* * SWAP PARAMETER TYPE FIELDS FOR A FUNCTION * * Overload resolution is based on the mtypes field of the function type. * This routine can be used to force resolution on the ptypes field by * swapping the two fields for the overloaded function identifier id. * Note that after overload resolution the fields should be swapped back. */ void swap_ptypes(IDENTIFIER id) { LIST (TYPE) ptypes; LIST (TYPE) mtypes; TYPE fn = DEREF_type (id_function_etc_type (id)); while (IS_type_templ (fn)) { /* Allow for template functions */ fn = DEREF_type (type_templ_defn (fn)); } ptypes = DEREF_list (type_func_ptypes (fn)); mtypes = DEREF_list (type_func_mtypes (fn)); if (!EQ_list (ptypes, mtypes)) { COPY_list (type_func_ptypes (fn), mtypes); COPY_list (type_func_mtypes (fn), ptypes); } return; } /* * SWAP PARAMETER TYPE FIELDS FOR CANDIDATES FUNCTIONS * * This routine swaps the parameter type fields for all the constructor * candidates in p, starting with the nth entry. */ void swap_candidates(CANDIDATE_LIST *p, unsigned n) { unsigned i, m = p->size; for (i = n ; i < m ; i++) { CANDIDATE *r = p->elem + i; if (r->kind == KIND_CONSTR) { swap_ptypes (r->base); } } return; } /* * LIST CANDIDATES FOR ERROR REPORTING * * This routine appends messages listing all the candidates from the list * p of rank at least rank to the end of the error message err. No action * is taken if err is the null error. */ ERROR list_candidates(ERROR err, CANDIDATE_LIST *p, unsigned rank) { if (!IS_NULL_err (err)) { ERROR err2 = ERR_over_match_viable_list (); if (!IS_NULL_err (err2)) { unsigned m = 0; CANDIDATE *q = p->elem; unsigned n = p->size; err = concat_error (err, err2); while (n) { CANDIDATE *r = q + (--n); if (r->rank >= rank) { /* List viable candidates */ IDENTIFIER bid = r->base; DECL_SPEC ds = DEREF_dspec (id_storage (bid)); if (!(ds & dspec_register)) { IDENTIFIER id = r->func; if (IS_id_builtin (id)) { /* Dump dummy built-in operators */ if (do_dump) dump_builtin (id); } m++; err2 = ERR_fail_list_item (m, id, id_loc (id)); err = concat_error (err, err2); ds |= dspec_register; COPY_dspec (id_storage (bid), ds); } } } if (m) { n = p->size; while (n) { /* Clear marks */ CANDIDATE *r = q + (--n); IDENTIFIER bid = r->base; DECL_SPEC ds = DEREF_dspec (id_storage (bid)); if (ds & dspec_register) { ds &= ~dspec_register; COPY_dspec (id_storage (bid), ds); } } } err = concat_error (err, ERR_fail_list_end (m)); } } return (err); } /* * OVERLOAD MATCHING INFORMATION * * These variables are used to store information gained during overload * resolution. If match_no_args is nonzero it gives the number of * candidates which take the right number of arguments, otherwise if it * is zero it indicates that either there are no such functions or there * is only one candidate. Similarly match_no_viable gives the number of * viable candidates (counting viable templates twice). */ unsigned match_no_args = 0; unsigned match_no_viable = 0; static unsigned viable_templates = 0; int resolved_kind = KIND_FUNC; /* * IS A CANDIDATE FUNCTION PLAUSIBLE? * * A candidate function is plausible for a list of arguments if it accepts * that number of arguments. This routine tests whether the candidate r * is plausible. It returns the absolute difference between the number * of arguments and the number of parameters (i.e. zero for a plausible * candidate). */ static unsigned plausible_candidate(CANDIDATE *r, unsigned nargs) { IDENTIFIER id = r->base; if (IS_id_builtin (id)) { /* Built-in candidates */ LIST (TYPE) mtypes = DEREF_list (id_builtin_ptypes (id)); unsigned npars = LENGTH_list (mtypes); if (nargs == npars) { /* Equal numbers of arguments and parameters */ return (0); } else if (nargs > npars) { /* More arguments than parameters */ return (nargs - npars); } else { /* Less arguments than parameters */ return (npars - nargs); } } else { /* Function candidates */ unsigned npars; LIST (TYPE) mtypes; TYPE fn = DEREF_type (id_function_etc_type (id)); while (IS_type_templ (fn)) { /* Allow for template functions */ fn = DEREF_type (type_templ_defn (fn)); } mtypes = DEREF_list (type_func_mtypes (fn)); npars = LENGTH_list (mtypes); if (nargs == npars) { /* Equal numbers of arguments and parameters */ return (0); } else if (nargs > npars) { /* More arguments than parameters */ int ell = DEREF_int (type_func_ellipsis (fn)); if (ell) { /* Match with ellipsis */ return (0); } return (nargs - npars); } else { /* Less arguments than parameters */ unsigned margs = min_no_args (fn); if (nargs >= margs) { /* Match with default arguments */ return (0); } return (margs - nargs); } } /* NOTREACHED */ } /* * INHERITANCE MATCHING FLAG * * This flag may be set to true to make the match for the implicit * this parameter for an inherited function as good as a match for * a non-inherited function from the point of view of function * overloading. */ int match_this = 0; /* * IS A PLAUSIBLE CANDIDATE FUNCTION VIABLE? * * A plausible candidate function is viable for a list of arguments if * there is an implicit conversion sequence for each argument to the * corresponding parameter type. This routine tests whether the plausible * candidate r is viable, building up the corresponding list of conversions. * It returns the number of arguments for which a sequence exists, plus * one. */ static unsigned viable_candidate(CANDIDATE *r, LIST (EXP) args, TYPE ret) { TYPE rtype; int bind = 0; unsigned conv; unsigned match = 1; LIST (TYPE) mtypes; IDENTIFIER id = r->base; CONVERSION *convs = r->convs; HASHID nm = DEREF_hashid (id_name (id)); /* Extract type information */ if (IS_id_builtin (id)) { if (IS_hashid_op (nm)) { int op = DEREF_int (hashid_op_lex (nm)); if (op == lex_assign) bind = 1; } mtypes = DEREF_list (id_builtin_ptypes (id)); rtype = DEREF_type (id_builtin_ret (id)); } else { LIST (TYPE) ptypes; TYPE fn = DEREF_type (id_function_etc_type (id)); if (IS_type_templ (fn)) { /* Allow for template functions */ ERROR err = NULL_err; if (r->kind == KIND_CONSTR) { /* Deal with swapped candidates */ IDENTIFIER tid; EXP a = NULL_exp; LIST (EXP) dargs; swap_ptypes (id); CONS_exp (a, args, dargs); tid = deduce_args (id, dargs, 2, 0, 1, &err); DESTROY_CONS_exp (destroy, a, args, dargs); UNUSED (a); if (IS_NULL_id (tid)) { swap_ptypes (id); return (0); } swap_ptypes (tid); id = tid; } else { /* Deal with normal candidates */ id = deduce_args (id, args, 2, 0, 1, &err); if (IS_NULL_id (id)) return (0); } fn = DEREF_type (id_function_etc_type (id)); if (!IS_type_func (fn)) return (0); viable_templates++; r->func = id; r->base = id; } mtypes = DEREF_list (type_func_mtypes (fn)); ptypes = DEREF_list (type_func_ptypes (fn)); if (IS_hashid_constr (nm)) { rtype = DEREF_type (hashid_constr_type (nm)); } else { rtype = DEREF_type (type_func_ret (fn)); } if (!EQ_list (mtypes, ptypes)) { /* Member function */ if (!IS_NULL_list (ptypes)) ptypes = TAIL_list (ptypes); if (EQ_list (mtypes, ptypes)) { /* Parameter types have been swapped */ /* EMPTY */ } else { /* Matching implicit this parameter */ if (match_this) { /* Force exact match */ bind = 2; } else { IDENTIFIER fid = r->func; DECL_SPEC ds = DEREF_dspec (id_storage (fid)); if ((ds & dspec_inherit) && !(ds & dspec_alias)) { /* Inherited member function */ bind = 3; } else { bind = 2; } } } } } /* Check for implicit conversion sequences */ while (!IS_NULL_list (mtypes) && !IS_NULL_list (args)) { conv = convs->rank; if (conv == CONV_NONE) { /* Recalculate if necessary */ EXP a = DEREF_exp (HEAD_list (args)); TYPE t = DEREF_type (HEAD_list (mtypes)); convs->to = t; if (IS_NULL_exp (a)) { /* A null expression counts as an exact match */ convs->from = t; conv = CONV_EXACT; } else { /* Calculate conversion sequence */ TYPE s = DEREF_type (exp_type (a)); convs->from = s; if (IS_NULL_type (ret)) { conv = convert_seq (convs, a, bind, 0); } else { conv = std_convert_seq (convs, a, bind, 0); } convs->from = s; convs->to = t; } } if (conv != CONV_NONE) match++; convs->rank = conv; convs++; args = TAIL_list (args); mtypes = TAIL_list (mtypes); bind = 0; } /* Remaining arguments match with ellipsis */ while (!IS_NULL_list (args)) { convs->rank = CONV_ELLIPSIS; convs++; match++; args = TAIL_list (args); } /* Check for return conversion sequences */ if (!IS_NULL_type (ret)) { conv = convs->rank; if (conv == CONV_NONE) { convs->to = ret; convs->from = rtype; conv = std_convert_seq (convs, NULL_exp, 0, 0); convs->from = rtype; convs->to = ret; } } else { conv = CONV_ELLIPSIS; } convs->rank = conv; return (match); } /* * COMPARE TWO FUNCTIONS * * This routine compares the candidate functions rid and sid to determine * which is better under the template specialisation rules. It returns * 1 if rid is better than sid, 2 if sid is better than rid, and 0 otherwise. */ static int compare_funcs(IDENTIFIER rid, IDENTIFIER sid) { int res = 0; if (EQ_id (rid, sid)) { /* Select first if equal */ res = 1; } else { if (IS_NULL_id (rid)) { res = 2; } else if (IS_NULL_id (sid)) { res = 1; } else { rid = find_template (rid, 0); sid = find_template (sid, 0); if (!IS_NULL_id (rid)) { if (!IS_NULL_id (sid)) { /* Both template functions */ res = compare_specs (rid, sid); } else { /* rid is a template function */ res = 2; } } else if (!IS_NULL_id (sid)) { /* sid is a template function */ res = 1; } } } return (res); } /* * COMPARE TWO CANDIDATE FUNCTIONS * * This routine compares the candidate functions r and s for the argument * list args and return type ret. It returns 1 if r is better than s, 2 if * s is better than r, and some other value otherwise. Better in this * sense means at least as good for all arguments, plus strictly better * in at least one argument or the return type. */ static int compare_candidates(CANDIDATE *r, CANDIDATE *s, LIST (EXP) args, TYPE ret) { int res = 0; CONVERSION *cr = r->convs; CONVERSION *cs = s->convs; /* Compare each argument in turn */ while (!IS_NULL_list (args)) { int cmp = compare_seq (cr, cs); if (cmp == 1) { /* r better in this argument */ if (res == 2) return (0); res = 1; } else if (cmp == 2) { /* s better in this argument */ if (res == 1) return (0); res = 2; } cr++; cs++; args = TAIL_list (args); } /* Tie breakers */ if (res == 0) { res = compare_funcs (r->base, s->base); if (res == 0 && !IS_NULL_type (ret)) { /* Resolve on return type */ res = compare_seq (cr, cs); } } return (res); } /* * OVERLOADED FUNCTION RESOLUTION * * This routine selects the best match from the list of overloaded function * given by p based on the argument list args and the return type ret (which * may be the null type). The list of candidate functions will not be empty. * If replay is true then the conversion sequences have already been * calculated and only the final tournament to select the best viable * candidate is necessary. */ CANDIDATE *resolve_overload(CANDIDATE_LIST *p, LIST (EXP) args, TYPE ret, int replay) { unsigned round; unsigned match = 0; CANDIDATE *q = p->elem; CANDIDATE *best = q; CANDIDATE *beat = NULL; unsigned i, n = p->size; if (!replay) { /* Eliminate all non-viable candidates */ unsigned nargs; unsigned margs; unsigned mconvs; unsigned best_margs; unsigned nconvs = p->nconvs; CONVERSION *convs = p->convs; /* Check for plausible candidates */ nargs = LENGTH_list (args); best_margs = nargs + 1; for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank != RANK_IGNORE) { margs = plausible_candidate (r, nargs); if (margs == 0) { /* Plausible candidate */ r->rank = RANK_ARGS; best = r; match++; } else if (match == 0 && margs <= best_margs) { /* Most nearly plausible candidate so far */ best_margs = margs; best = r; } } } match_no_args = match; if (match == 0) { /* No plausible candidates - return most nearly plausible */ match_no_viable = 0; return (best); } /* Allocate room for conversion ranks */ nargs++; mconvs = match * nargs; if (mconvs >= nconvs) { nconvs = mconvs + 200; convs = xrealloc (convs, sizeof(*convs) * nconvs); p->nconvs = nconvs; p->convs = convs; } /* Check for viable candidates */ match = 0; best_margs = 0; viable_templates = 0; for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank == RANK_ARGS) { /* Only check plausible candidates */ unsigned m; r->convs = convs; for (m = 0 ; m < nargs ; m++) { convs->rank = CONV_NONE; convs++; } margs = viable_candidate (r, args, ret); if (margs == nargs) { /* Viable candidate */ r->rank = RANK_VIABLE; best = r; match++; } else if (match == 0 && margs >= best_margs) { /* Most nearly viable candidate so far */ best_margs = margs; best = r; } } } match_no_viable = match + viable_templates; if (match == 0) { /* No viable candidates - return most nearly viable */ return (best); } if (match == 1) { /* Exactly one viable candidate - must be the winner */ best->rank = RANK_BEST; return (best); } } else { /* Replay - pick a viable candidate */ for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank >= RANK_VIABLE) { r->rank = RANK_VIABLE; best = r; match++; } } } /* Play tournament among viable candidates */ round = RANK_VIABLE; while (match > 1) { CANDIDATE *s = NULL; match = 0; for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank == round) { /* Only check those through to this round */ if (s == NULL) { /* r is first candidate in contest */ s = r; } else { /* r is second candidate in contest */ int cmp = compare_candidates (s, r, args, ret); if (cmp == 1) { /* s wins */ s->rank = round + 1; r->rank = RANK_VIABLE; best = s; beat = r; match++; } else if (cmp == 2) { /* r wins */ r->rank = round + 1; s->rank = RANK_VIABLE; best = r; beat = s; match++; } else { /* Draw - both eliminated */ s->rank = RANK_VIABLE; r->rank = RANK_VIABLE; } s = NULL; } } } if (s != NULL) { /* Bye - s goes through */ s->rank = round + 1; best = s; match++; } round++; } /* Examine the tournament winner */ if (match == 1) { /* Tournament winner must now beat all the others */ best->rank = RANK_BEST; for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank >= RANK_VIABLE) { if (r == best) { /* Don't compare against self */ /* EMPTY */ } else if (r == beat) { /* This has already been beaten */ /* EMPTY */ } else { int cmp = compare_candidates (best, r, args, ret); if (cmp != 1) { /* r is at least as good as best */ best->rank = RANK_VIABLE; break; } } } } } else { /* No clear tournament winner */ if (best->rank >= RANK_VIABLE) best->rank = RANK_VIABLE; } return (best); } /* * FIND A LIST OF POSSIBLE TYPE VALUES * * This routine constructs a list of the possible resolutions for the * target dependent type t or its promotion. In the latter case prom * is set to true. If neither t or its promotion is target dependent * then the empty list is returned. */ static LIST (TYPE) possible_types(TYPE t, int *prom) { LIST (TYPE) r = NULL_list (TYPE); switch (TAG_type (t)) { case type_integer_tag : { /* Integral type */ INT_TYPE it = DEREF_itype (type_integer_rep (t)); r = DEREF_list (itype_cases (it)); if (LENGTH_list (r) == 1) { /* Type is not target dependent */ t = DEREF_type (itype_prom (it)); it = DEREF_itype (type_integer_rep (t)); r = DEREF_list (itype_cases (it)); if (LENGTH_list (r) == 1) { /* Promoted type is not target dependent */ r = NULL_list (TYPE); } else { *prom = 1; } } break; } case type_bitfield_tag : case type_enumerate_tag : { /* Enumeration and bitfield types */ t = promote_type (t); r = possible_types (t, prom); *prom = 1; break; } } return (r); } /* * CHECK FOR TARGET DEPENDENT OVERLOADED FUNCTION RESOLUTIONS * * This routine is called when an ambiguous overload resolution is * detected to determine which of the viable candidates to proceed with. * The parameters are as in resolve_overload. */ CANDIDATE *resolve_ambiguous(CANDIDATE_LIST *p, LIST (EXP) args, TYPE ret, int depth) { CANDIDATE *q = p->elem; CANDIDATE *best = q; unsigned i, n = p->size; unsigned overall_rank = RANK_VIABLE; /* Check for arguments of error type */ if (depth == 0) { LIST (EXP) a = args; while (!IS_NULL_list (a)) { EXP e = DEREF_exp (HEAD_list (a)); if (!IS_NULL_exp (e)) { TYPE t = DEREF_type (exp_type (e)); if (IS_type_error (t)) { /* Error types are ignored */ overall_rank = RANK_BEST; break; } } a = TAIL_list (a); } } /* Check for target dependent resolutions */ if (overall_rank != RANK_BEST) { unsigned na = 0; LIST (EXP) a = args; EXP saved [100]; EXP *save = saved; if (n >= 100) save = xmalloc_nof (EXP, n); for (i = 0 ; i < n ; i++) save [i] = NULL_exp; while (!IS_NULL_list (a)) { EXP e = DEREF_exp (HEAD_list (a)); if (!IS_NULL_exp (e)) { int prom = 0; int have_match = 0; TYPE t = DEREF_type (exp_type (e)); LIST (TYPE) pt = possible_types (t, &prom); if (!IS_NULL_list (pt)) { CANDIDATE *r; LIST (TYPE) ps = pt; unsigned new_rank = RANK_TARGET; if (prom) { /* Only use promoted types if no exact match */ for (i = 0 ; i < n ; i++) { r = q + i; if (r->rank >= RANK_VIABLE) { if (r->convs [ na ].rank == CONV_EXACT) { ps = NULL_list (TYPE); new_rank = overall_rank; break; } } } } overall_rank = new_rank; while (!IS_NULL_list (ps)) { TYPE u = t; TYPE s = DEREF_type (HEAD_list (ps)); COPY_type (exp_type (e), s); for (i = 0 ; i < n ; i++) { r = q + i; if (r->rank >= RANK_VIABLE) { /* Recalculate conversions */ r->convs [ na ].rank = CONV_NONE; IGNORE viable_candidate (r, args, ret); r->rank = RANK_VIABLE; } } r = resolve_overload (p, args, ret, 1); if (r->rank == RANK_VIABLE) { /* Check further arguments */ for (i = 0 ; i < n ; i++) { /* Save conditions */ save [i] = q [i].cond; q [i].cond = NULL_exp; } r = resolve_ambiguous (p, args, ret, 1); for (i = 0 ; i < n ; i++) { /* Restore conditions */ EXP c = q [i].cond; q [i].cond = save [i]; save [i] = c; } } COPY_type (exp_type (e), t); if (r->rank >= RANK_TARGET) { /* Create condition for resolution */ if (prom) u = promote_type (u); for (i = 0 ; i < n ; i++) { r = q + i; if (r->rank >= RANK_TARGET) { EXP c1, c2; TYPE ti = type_sint; TYPE tb = type_bool; NTEST nt = ntest_eq; MAKE_exp_rtti_no (ti, u, c1); MAKE_exp_rtti_no (ti, s, c2); MAKE_exp_compare (tb, nt, c1, c2, c1); c2 = save [i]; if (!IS_NULL_exp (c2)) { MAKE_exp_log_and (tb, c1, c2, c1); } c2 = r->cond; if (!IS_NULL_exp (c2)) { MAKE_exp_log_or (tb, c1, c2, c1); } r->cond = c1; have_match = 1; } save [i] = NULL_exp; } } else if (option (OPT_overload_strict)) { /* Don't have match in all cases */ have_match = 0; break; } ps = TAIL_list (ps); } if (!have_match) { overall_rank = RANK_VIABLE; break; } } } a = TAIL_list (a); na++; } if (save != saved) xfree (save); } /* Select last viable candidate */ for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank >= RANK_VIABLE) { if (overall_rank == RANK_TARGET) { if (IS_NULL_exp (r->cond)) { if (depth == 0) r->rank = RANK_ARGS; } else { r->rank = overall_rank; best = r; } } else { r->rank = overall_rank; best = r; } } } return (best); } /* * LIST OF ALL AMBIGUOUS OVERLOADED FUNCTIONS * * This list is used to hold all the dummy tokenised functions constructed * to represent target dependent overload resolutions. The functions are * determined by the list of candidates, the list of argument types and * the qualifier used. */ typedef struct ambig_func_tag { IDENTIFIER id; LIST (IDENTIFIER) funcs; LIST (TYPE) types; QUALIFIER qual; struct ambig_func_tag *next; } AMBIG_FUNCTION; static AMBIG_FUNCTION *all_ambig_funcs = NULL; /* * FIND A PREVIOUS AMBIGUOUS OVERLOADED FUNCTION * * This routine searches the list of all ambiguous overloaded functions * for one which candidate functions p, argument types q and qualifier * qual. */ static IDENTIFIER previous_ambig_func(LIST (IDENTIFIER) p, LIST (TYPE) q, QUALIFIER qual) { AMBIG_FUNCTION *f = all_ambig_funcs; if (f) { unsigned np = LENGTH_list (p); unsigned nq = LENGTH_list (q); while (f != NULL) { if (f->qual == qual) { int ok = 1; LIST (IDENTIFIER) pf = f->funcs; LIST (TYPE) qf = f->types; if (LENGTH_list (pf) == np) { LIST (IDENTIFIER) pg = p; while (!IS_NULL_list (pg)) { IDENTIFIER nf = DEREF_id (HEAD_list (pf)); IDENTIFIER ng = DEREF_id (HEAD_list (pg)); if (!EQ_id (nf, ng)) { ok = 0; break; } pf = TAIL_list (pf); pg = TAIL_list (pg); } } if (ok && LENGTH_list (qf) == nq) { LIST (TYPE) qg = q; while (!IS_NULL_list (qg)) { TYPE tf = DEREF_type (HEAD_list (qf)); TYPE tg = DEREF_type (HEAD_list (qg)); if (!eq_type (tf, tg)) { ok = 0; break; } qf = TAIL_list (qf); qg = TAIL_list (qg); } } if (ok) return (f->id); } f = f->next; } } return (NULL_id); } /* * CONSTRUCT AN AMBIGUOUS OVERLOADED FUNCTION * * This routine constructs a dummy tokenised function to represent the * target dependent overload resolution given by the candidates p for * the function call 'id (args)' detected by the previous call to * resolve_ambiguous. Any errors arising are added to err. */ IDENTIFIER make_ambig_func(CANDIDATE_LIST *p, IDENTIFIER id, LIST (EXP) args, QUALIFIER qual, ERROR *err) { EXP res; TYPE fn; TOKEN tok; TYPE form; MEMBER mem; DECL_SPEC ds; IDENTIFIER tid; LIST (TYPE) mt; AMBIG_FUNCTION *all; TYPE ret = NULL_type; TYPE et = type_error; CANDIDATE *q = p->elem; unsigned i, n = p->size; NAMESPACE ns = crt_namespace; QUALIFIER cq = crt_id_qualifier; int tq = crt_templ_qualifier; int td = have_type_declaration; unsigned tag = id_function_tag; HASHID nm = DEREF_hashid (id_name (id)); /* List of viable candidates */ LIST (EXP) conds = NULL_list (EXP); LIST (TYPE) types = NULL_list (TYPE); LIST (IDENTIFIER) funcs = NULL_list (IDENTIFIER); /* Check function return types */ for (i = 0 ; i < n ; i++) { CANDIDATE *r = q + i; if (r->rank >= RANK_VIABLE) { int suspect = 0; TYPE ta = NULL_type; IDENTIFIER fid = r->base; switch (TAG_id (fid)) { case id_builtin_tag : { ta = DEREF_type (id_builtin_ret (fid)); break; } case id_function_tag : { TYPE fa = DEREF_type (id_function_type (fid)); if (IS_type_func (fa)) { ta = DEREF_type (type_func_ret (fa)); } break; } case id_mem_func_tag : { TYPE fa = DEREF_type (id_mem_func_type (fid)); if (IS_type_func (fa)) { HASHID fnm = DEREF_hashid (id_name (fid)); mt = DEREF_list (type_func_mtypes (fa)); et = DEREF_type (HEAD_list (mt)); if (IS_hashid_constr (fnm)) { ta = DEREF_type (hashid_constr_type (fnm)); } else { ta = DEREF_type (type_func_ret (fa)); tag = id_mem_func_tag; } } break; } case id_stat_mem_func_tag : { TYPE fa = DEREF_type (id_stat_mem_func_type (fid)); if (IS_type_func (fa)) { mt = DEREF_list (type_func_mtypes (fa)); et = DEREF_type (HEAD_list (mt)); ta = DEREF_type (type_func_ret (fa)); if (tag != id_mem_func_tag) { tag = id_stat_mem_func_tag; } } break; } } ret = common_type (ret, ta, &suspect); if (suspect) ret = NULL_type; CONS_exp (r->cond, conds, conds); CONS_id (fid, funcs, funcs); } } if (IS_NULL_type (ret)) { /* Couldn't bring return types to common type */ ERROR err2 = ERR_over_match_best_common (); add_error (err, err2); ret = type_error; } if (err != KILL_err) { *err = list_candidates (*err, p, RANK_VIABLE); } /* Create list of argument types */ while (!IS_NULL_list (args)) { TYPE t; EXP e = DEREF_exp (HEAD_list (args)); if (IS_NULL_exp (e)) { t = et; et = type_error; } else { t = DEREF_type (exp_type (e)); if (IS_type_bitfield (t)) { t = promote_type (t); } else { CV_SPEC cv = DEREF_cv (type_qual (t)); if (cv & cv_lvalue) { MAKE_type_ref (cv_none, t, t); } } } CONS_type (t, types, types); args = TAIL_list (args); } types = REVERSE_list (types); /* Check for previous instance */ tid = previous_ambig_func (funcs, types, qual); if (!IS_NULL_id (tid)) { DESTROY_list (funcs, SIZE_id); DESTROY_list (types, SIZE_type); free_exp_list (conds, 1); return (tid); } /* Create new instance */ all = xmalloc (sizeof(*all)); all->id = NULL_id; all->funcs = funcs; all->types = types; all->qual = qual; all->next = all_ambig_funcs; all_ambig_funcs = all; /* Scan through argument types */ crt_id_qualifier = qual_none; crt_templ_qualifier = 0; have_type_declaration = TYPE_DECL_NONE; decl_loc = crt_loc; begin_param (id); mt = types; while (!IS_NULL_list (mt)) { HASHID pnm = lookup_anon (); IDENTIFIER pid = DEREF_id (hashid_id (pnm)); TYPE t = DEREF_type (HEAD_list (mt)); pid = make_param_decl (dspec_none, t, pid, CONTEXT_PARAMETER); init_param (pid, NULL_exp); mt = TAIL_list (mt); } fn = make_func_type (ret, FUNC_NONE, cv_none, empty_type_set); if (tag != id_function_tag) { mt = DEREF_list (type_func_ptypes (fn)); mt = TAIL_list (mt); COPY_list (type_func_ptypes (fn), mt); } end_param (); /* Create a function identifier */ ds = (dspec_static | dspec_token | dspec_reserve); MAKE_id_function_etc (tag, nm, ds, ns, crt_loc, fn, NULL_id, id); /* Create token identifier */ ns = token_namespace; nm = lookup_anon (); mem = search_member (ns, nm, 1); MAKE_tok_func (fn, tok); MAKE_id_token (nm, ds, ns, crt_loc, tok, id, tid); MAKE_type_token (cv_none, tid, NULL_list (TOKEN), form); COPY_type (id_function_etc_form (id), form); set_member (mem, tid); tok = func_proc_token (tok); /* Define token */ res = install_error (&crt_loc, ERR_over_match_best_install ()); while (!IS_NULL_list (funcs)) { EXP c, f; LIST (EXP) fargs = NULL_list (EXP); LIST (IDENTIFIER) pids = DEREF_list (tok_proc_bids (tok)); IDENTIFIER fid = DEREF_id (HEAD_list (funcs)); DESTROY_CONS_exp (destroy, c, conds, conds); while (!IS_NULL_list (pids)) { /* Build up argument list */ TYPE t; int prom = 0; LIST (TYPE) pt; IDENTIFIER pid = DEREF_id (HEAD_list (pids)); EXP e = apply_exp_token (pid, NULL_list (TOKEN), 0); e = convert_reference (e, REF_NORMAL); t = DEREF_type (exp_type (e)); pt = possible_types (t, &prom); if (!IS_NULL_list (pt)) { /* Mark target dependent arguments */ MAKE_exp_paren (t, e, e); } CONS_exp (e, fargs, fargs); pids = TAIL_list (pids); } fargs = REVERSE_list (fargs); if (IS_id_builtin (fid)) { f = apply_builtin (fid, fargs); } else { HASHID fnm = DEREF_hashid (id_name (fid)); use_func_id (fid, 1, 0); if (IS_hashid_constr (fnm)) { f = apply_constr (fid, fargs); } else { f = apply_func_id (fid, qual, NULL_graph, fargs); } } if (!IS_type_top_etc (ret)) { /* Convert to common return type */ ERROR err2 = NULL_err; f = convert_reference (f, REF_ASSIGN); f = cast_exp (ret, f, &err2, CAST_IMPLICIT); if (!IS_NULL_err (err2)) report (crt_loc, err2); } if (IS_NULL_exp (res)) { free_exp (c, 1); res = f; } else { MAKE_exp_hash_if (ret, c, f, res, res); } funcs = TAIL_list (funcs); } IGNORE define_exp_token (tid, res, 1); /* Restore previous state */ have_type_declaration = td; crt_templ_qualifier = tq; crt_id_qualifier = cq; all->id = id; return (id); } /* * IS AN IDENTIFIER A FUNCTION TEMPLATE? * * This routine returns true if id is a function template. In this case * overload resolution is always done even if id is not overloaded. */ static int is_template_func(IDENTIFIER id) { if (IS_id_function_etc (id)) { TYPE fn = DEREF_type (id_function_etc_type (id)); if (IS_type_templ (fn)) return (1); } return (0); } /* * RESOLVE AN OVERLOADED FUNCTION CALL * * This routine resolves the overloaded function call 'id (args)' where * id is an identifier expression. dep is true when id is a simple * unqualified function name. It returns the identifier for id which * provides the best match for the given arguments. For ambiguities the * identifier returned is the first of the viable functions to be declared * (this is a side effect of the algorithm in resolve_overload and the * way in which overloaded functions are represented). */ IDENTIFIER resolve_call(IDENTIFIER id, LIST (EXP) args, QUALIFIER qual, int dep) { /* Build up candidate list */ unsigned sz; IDENTIFIER fid = id; CANDIDATE_LIST *p = &candidates; p->size = 0; if (dep) { /* Allow for argument dependent look-up */ LIST (EXP) q = args; while (!IS_NULL_list (q)) { EXP a = DEREF_exp (HEAD_list (q)); if (!IS_NULL_exp (a)) { TYPE t = DEREF_type (exp_type (a)); IGNORE koenig_candidates (p, fid, t, KIND_FUNC); } q = TAIL_list (q); } } add_candidates (p, fid, 1, KIND_FUNC); sz = p->size; if (sz == 0) { /* No candidates */ EXP a; int fn = 2; QUALIFIER cq = crt_id_qualifier; crt_id_qualifier = (qual & qual_explicit); if (qual & qual_mark) fn = 1; a = implicit_id_exp (fid, fn); if (IS_exp_identifier_etc (a)) { fid = DEREF_id (exp_identifier_etc_id (a)); add_candidates (p, fid, 1, KIND_FUNC); sz = p->size; if (sz != 0) fid = p->elem [0].func; } crt_id_qualifier = cq; } else { fid = p->elem [0].func; } /* Resolve overloaded functions */ if (sz > 1) { CANDIDATE *q = resolve_overload (p, args, NULL_type, 0); IDENTIFIER qid = q->func; unsigned rank = q->rank; int kind = q->kind; if (rank == RANK_BEST) { /* Unambiguous resolution */ if (match_no_viable > 1) { ERROR err = ERR_over_match_call_ok (qid); if (!IS_NULL_err (err)) report (crt_loc, err); } } else if (rank == RANK_VIABLE) { /* Ambiguous resolution */ q = resolve_ambiguous (p, args, NULL_type, 0); qid = q->func; rank = q->rank; if (rank == RANK_TARGET) { ERROR err = ERR_over_match_call_target (id); qid = make_ambig_func (p, qid, args, qual, &err); kind = KIND_FUNC; report (crt_loc, err); } else if (rank == RANK_VIABLE) { ERROR err = ERR_over_match_call_ambig (id); err = list_candidates (err, p, RANK_VIABLE); report (crt_loc, err); } } else { /* Unviable resolution */ report (crt_loc, ERR_over_match_viable_none (id)); } resolved_kind = kind; return (qid); } /* Check template functions */ if (is_template_func (fid)) { ERROR err = NULL_err; IDENTIFIER qid = deduce_args (fid, args, 2, 0, 1, &err); if (IS_NULL_id (qid)) { /* No viable resolution */ err = concat_error (err, ERR_over_match_viable_none (id)); qid = fid; } if (!IS_NULL_err (err)) { /* Report any argument deduction errors */ err = concat_error (err, ERR_temp_deduct_fail (id)); report (crt_loc, err); } else { /* Successful argument deduction */ report (crt_loc, ERR_over_match_call_ok (qid)); } fid = qid; } /* Don't check non-overloaded functions */ match_no_args = 0; match_no_viable = 0; resolved_kind = KIND_FUNC; return (fid); } /* * RESOLVE AN AMBIGUOUS FUNCTION ADDRESS * * This routine resolves the list of functions ids to see which is the * best under the template specialisation rules. If no one best candidate * is found the null identifier is returned. This rule is not actually * in ISO C++, but it could have been. */ static IDENTIFIER resolve_ambig_func(LIST (IDENTIFIER) ids, int depth) { if (!IS_NULL_list (ids)) { int cmp; IDENTIFIER rid, sid; LIST (IDENTIFIER) pids = ids; /* Find the first two functions */ rid = DEREF_id (HEAD_list (pids)); pids = TAIL_list (pids); if (IS_NULL_list (pids)) return (rid); sid = DEREF_id (HEAD_list (pids)); pids = TAIL_list (pids); /* Compare them */ cmp = compare_funcs (rid, sid); if (cmp == 2) { rid = sid; } else if (cmp != 1) { rid = NULL_id; } /* Compare the winner against the best of the rest */ sid = resolve_ambig_func (pids, depth + 1); cmp = compare_funcs (rid, sid); if (cmp == 2) { rid = sid; } else if (cmp != 1) { rid = NULL_id; } /* Check overall winner */ if (depth == 0 && !IS_NULL_id (rid)) { pids = ids; while (!IS_NULL_list (pids)) { sid = DEREF_id (HEAD_list (pids)); if (!EQ_id (rid, sid)) { cmp = compare_funcs (rid, sid); if (cmp != 1) return (NULL_id); } pids = TAIL_list (pids); } } return (rid); } return (NULL_id); } /* * FIND AN OVERLOADED FUNCTION OF A GIVEN TYPE * * This routine returns whichever of the set of overloaded or ambiguous * functions id has type t. Type deduction is allowed for the template * parameters pids if templ is true. The null identifier is returned if * none has the correct type, an ambiguous identifier is returned if * more than one has the correct type (although overload resolution * occurs if res is true). If there is a match ignoring linkage * specifiers then this is returned, the value of eq_func_type for the * result is assigned to peq. */ IDENTIFIER resolve_func(IDENTIFIER id, TYPE t, int templ, int res, LIST (IDENTIFIER) pids, int *peq) { int best = 2; IDENTIFIER rid = NULL_id; switch (TAG_id (id)) { case id_function_tag : case id_mem_func_tag : case id_stat_mem_func_tag : { /* Check overloaded functions */ IDENTIFIER fid = id; int have_templates = 0; LIST (IDENTIFIER) rids = NULL_list (IDENTIFIER); while (!IS_NULL_id (fid)) { TYPE s; int d = 0; int eq = 0; IDENTIFIER tid = fid; if (!IS_NULL_list (pids)) { /* Save template parameter values */ d = save_token_args (pids, NULL_list (TOKEN)); } s = DEREF_type (id_function_etc_type (fid)); if (IS_type_templ (s) && templ) { /* Template functions */ tid = deduce_func (tid, t, &eq); if (!IS_NULL_id (tid)) have_templates = 1; } else { /* Simple functions */ #if LANGUAGE_CPP eq = eq_func_type (s, t, 1, 0); #else TYPE r = type_composite (s, t, 1, 0, KILL_err, 0); if (!IS_NULL_type (r)) eq = 3; #endif } if (eq >= best) { if (eq > best) { /* Better match than previous */ if (!IS_NULL_list (rids)) { DESTROY_list (rids, SIZE_id); rids = NULL_list (IDENTIFIER); } rid = NULL_id; best = eq; } if (!IS_NULL_id (rid)) { CONS_id (rid, rids, rids); } rid = tid; } if (!IS_NULL_list (pids)) { /* Restore template parameters */ restore_token_args (pids, d); } fid = DEREF_id (id_function_etc_over (fid)); } if (!IS_NULL_list (rids)) { /* Construct ambiguous result */ HASHID nm; NAMESPACE ns; DECL_SPEC ds; CONS_id (rid, rids, rids); if (have_templates && res) { /* Perform overload resolution */ rid = resolve_ambig_func (rids, 0); if (!IS_NULL_id (rid)) { DESTROY_list (rids, SIZE_id); break; } } nm = DEREF_hashid (id_name (id)); ns = DEREF_nspace (id_parent (id)); ds = find_ambig_dspec (rids); MAKE_id_ambig (nm, ds, ns, crt_loc, rids, 0, rid); } break; } case id_ambig_tag : { /* Check ambiguous functions */ LIST (IDENTIFIER) rids = NULL_list (IDENTIFIER); LIST (IDENTIFIER) p = DEREF_list (id_ambig_ids (id)); while (!IS_NULL_list (p)) { int eq = 0; IDENTIFIER pid = DEREF_id (HEAD_list (p)); pid = resolve_func (pid, t, templ, 0, pids, &eq); if (!IS_NULL_id (pid) && eq >= best) { if (eq > best) { /* Better match than previous */ if (!IS_NULL_list (rids)) { DESTROY_list (rids, SIZE_id); rids = NULL_list (IDENTIFIER); } rid = NULL_id; best = eq; } if (IS_id_ambig (pid)) { LIST (IDENTIFIER) q; q = DEREF_list (id_ambig_ids (pid)); while (!IS_NULL_list (q)) { pid = DEREF_id (HEAD_list (q)); if (!IS_NULL_id (rid)) { CONS_id (rid, rids, rids); } rid = pid; q = TAIL_list (q); } } else { if (!IS_NULL_id (rid)) { CONS_id (rid, rids, rids); } rid = pid; } } p = TAIL_list (p); } if (!IS_NULL_list (rids)) { HASHID nm; NAMESPACE ns; DECL_SPEC ds; CONS_id (rid, rids, rids); if (res) { /* Perform overload resolution */ rid = resolve_ambig_func (rids, 0); if (!IS_NULL_id (rid)) { DESTROY_list (rids, SIZE_id); break; } } nm = DEREF_hashid (id_name (id)); ns = DEREF_nspace (id_parent (id)); ds = find_ambig_dspec (rids); MAKE_id_ambig (nm, ds, ns, crt_loc, rids, 0, rid); } break; } } if (IS_NULL_id (rid)) best = 0; *peq = best; return (rid); } /* * CREATE A RESOLVED OVERLOADED FUNCTION EXPRESSION * * This routine creates a resolved overloaded function expression for * the function id. */ static EXP make_resolved_exp(IDENTIFIER id, QUALIFIER q, EXP b, int addr, int paren) { EXP e; TYPE fn = DEREF_type (id_function_etc_type (id)); if (IS_id_mem_func (id)) { if (!IS_NULL_exp (b)) { report (crt_loc, ERR_expr_ref_call ()); q = qual_nested; } MAKE_exp_member (fn, id, q, e); } else { MAKE_exp_identifier (fn, id, q, e); if (!IS_NULL_exp (b)) e = join_exp (b, e); } if (addr) { if (paren) e = make_paren_exp (e); e = make_ref_exp (e, 1); } return (e); } /* * RESOLVE THE ADDRESS OF AN OVERLOADED FUNCTION * * This routine checks the conversion of the expression e to type t. If * e is an overloaded function identifier expression and t is a function * type, or pointer to function type, or pointer to member function type, * then the various versions of e are checked for the one which matches * the function type underlying t in the context of the template * parameters pids. An error is added to err if this does not exist. * The result is the appropriate version of e. Note that member * expressions which resolve to static function members are replaced * by identifier expressions at this stage (see make_id_exp). */ EXP resolve_cast(TYPE t, EXP e, ERROR *err, int use, int rescan, LIST (IDENTIFIER) pids) { /* Check for identifier expressions */ EXP a = e; QUALIFIER q; int addr = 0; int paren = 0; IDENTIFIER id; EXP b = NULL_exp; unsigned tag = TAG_exp (a); while (tag == exp_paren_tag) { a = DEREF_exp (exp_paren_arg (a)); tag = TAG_exp (a); } if (tag == exp_address_tag) { /* Address expression */ a = DEREF_exp (exp_address_arg (a)); tag = TAG_exp (a); addr = 1; } else if (tag == exp_address_mem_tag) { /* Address of member expression */ paren = DEREF_int (exp_address_mem_paren (a)); a = DEREF_exp (exp_address_mem_arg (a)); tag = TAG_exp (a); addr = 1; } else if (tag == exp_op_tag) { /* Check for undetermined address expressions */ int op = DEREF_int (exp_op_lex (a)); EXP c = DEREF_exp (exp_op_arg2 (a)); if (op == lex_and_H1 && IS_NULL_exp (c)) { a = DEREF_exp (exp_op_arg1 (a)); tag = TAG_exp (a); addr = 1; } } while (tag == exp_paren_tag) { a = DEREF_exp (exp_paren_arg (a)); paren = 1; tag = TAG_exp (a); } if (tag == exp_call_tag) { /* Member reference expression */ b = DEREF_exp (exp_call_arg (a)); a = DEREF_exp (exp_call_ptr (a)); } if (!IS_exp_identifier_etc (a)) { /* Not an identifier expression */ return (e); } /* Mark identifiers as resolved */ id = DEREF_id (exp_identifier_etc_id (a)); q = DEREF_qual (exp_identifier_etc_qual (a)); if (q & qual_mark) return (e); if (rescan) { /* Rescan function name if necessary */ id = rescan_func_id (id, q); } q |= qual_mark; /* Check for overloaded functions */ tag = TAG_id (id); switch (tag) { case id_function_tag : case id_mem_func_tag : case id_stat_mem_func_tag : function_lab : { /* Check functions for overloading */ TYPE s; IDENTIFIER over; if (rescan) goto overload_lab; if (dependent_cast (id, t)) { /* Allow for template parameters */ if (!IS_type_func (t)) t = rvalue_type (t); MAKE_exp_op (t, lex_function, e, NULL_exp, e); return (e); } over = DEREF_id (id_function_etc_over (id)); if (!IS_NULL_id (over)) goto overload_lab; s = DEREF_type (id_function_etc_type (id)); if (IS_type_templ (s)) goto overload_lab; if (tag == id_mem_func_tag) { if (!IS_NULL_exp (b) || addr) { /* Force error in this case */ e = make_resolved_exp (id, q, b, addr, paren); } } if (use) { COPY_qual (exp_identifier_etc_qual (a), q); use_id (id, suppress_usage); } break; } case id_ambig_tag : case id_undef_tag : overload_lab : { /* Overloaded and ambiguous functions */ TYPE fn = find_func_type (t); if (!IS_NULL_type (fn)) { /* Overload resolution */ int eq = 0; IDENTIFIER rid; if (dependent_cast (id, t)) { /* Allow for template parameters */ if (!IS_type_func (t)) t = rvalue_type (t); MAKE_exp_op (t, lex_function, e, NULL_exp, e); return (e); } if (tag == id_undef_tag) goto default_lab; rid = resolve_func (id, fn, 1, 0, pids, &eq); if (!IS_NULL_id (rid)) { if (IS_id_ambig (rid)) { /* Ambiguous resolution */ if (use) { /* Select one function */ LIST (IDENTIFIER) ids; IGNORE report_ambiguous (rid, 0, 0, 0); ids = DEREF_list (id_ambig_ids (rid)); rid = resolve_ambig_func (ids, 0); if (IS_NULL_id (rid)) { rid = DEREF_id (HEAD_list (ids)); } } else { e = NULL_exp; rid = NULL_id; } } if (!IS_NULL_id (rid)) { /* Unique resolution */ report (crt_loc, ERR_over_over_ok (rid)); e = make_resolved_exp (rid, q, b, addr, paren); if (use) use_id (rid, suppress_usage); } } else { /* Unsuccessful resolution */ if (use) { add_error (err, ERR_over_over_none (id, fn)); e = make_error_exp (0); } else { e = NULL_exp; } } } else { /* No context for resolution */ if (tag == id_undef_tag) goto default_lab; if (use) { add_error (err, ERR_over_over_context (id)); e = make_error_exp (0); } else { e = NULL_exp; } } break; } default : default_lab : { /* Other identifiers */ if (rescan) { if (use) { EXP c = implicit_id_exp (id, 1); if (IS_exp_identifier_etc (c)) { id = DEREF_id (exp_identifier_etc_id (a)); if (IS_id_function_etc (id)) { goto function_lab; } } } else { e = NULL_exp; } } break; } } return (e); }