+/* Search through the methods of an object (and its bases)
+ * to find a specified method. Return the pointer to the
+ * fn_field list of overloaded instances.
+ * Helper function for value_find_oload_list.
+ * ARGP is a pointer to a pointer to a value (the object)
+ * METHOD is a string containing the method name
+ * OFFSET is the offset within the value
+ * STATIC_MEMFUNCP is set if the method is static
+ * TYPE is the assumed type of the object
+ * NUM_FNS is the number of overloaded instances
+ * BASETYPE is set to the actual type of the subobject where the method is found
+ * BOFFSET is the offset of the base subobject where the method is found */
+
+static struct fn_field *
+find_method_list (value_ptr *argp, char *method, int offset,
+ int *static_memfuncp, struct type *type, int *num_fns,
+ struct type **basetype, int *boffset)
+{
+ int i;
+ struct fn_field *f;
+ CHECK_TYPEDEF (type);
+
+ *num_fns = 0;
+
+ /* First check in object itself */
+ for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
+ {
+ /* pai: FIXME What about operators and type conversions? */
+ char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
+ {
+ *num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ *basetype = type;
+ *boffset = offset;
+ return TYPE_FN_FIELDLIST1 (type, i);
+ }
+ }
+
+ /* Not found in object, check in base subobjects */
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ int base_offset;
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ if (TYPE_HAS_VTABLE (type))
+ {
+ /* HP aCC compiled type, search for virtual base offset
+ * according to HP/Taligent runtime spec. */
+ int skip;
+ find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
+ VALUE_CONTENTS_ALL (*argp),
+ offset + VALUE_EMBEDDED_OFFSET (*argp),
+ &base_offset, &skip);
+ if (skip >= 0)
+ error ("Virtual base class offset not found in vtable");
+ }
+ else
+ {
+ /* probably g++ runtime model */
+ base_offset = VALUE_OFFSET (*argp) + offset;
+ base_offset =
+ baseclass_offset (type, i,
+ VALUE_CONTENTS (*argp) + base_offset,
+ VALUE_ADDRESS (*argp) + base_offset);
+ if (base_offset == -1)
+ error ("virtual baseclass botch");
+ }
+ }
+ else
+ /* non-virtual base, simply use bit position from debug info */
+ {
+ base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
+ }
+ f = find_method_list (argp, method, base_offset + offset,
+ static_memfuncp, TYPE_BASECLASS (type, i), num_fns, basetype, boffset);
+ if (f)
+ return f;
+ }
+ return NULL;
+}
+
+/* Return the list of overloaded methods of a specified name.
+ * ARGP is a pointer to a pointer to a value (the object)
+ * METHOD is the method name
+ * OFFSET is the offset within the value contents
+ * STATIC_MEMFUNCP is set if the method is static
+ * NUM_FNS is the number of overloaded instances
+ * BASETYPE is set to the type of the base subobject that defines the method
+ * BOFFSET is the offset of the base subobject which defines the method */
+
+struct fn_field *
+value_find_oload_method_list (value_ptr *argp, char *method, int offset,
+ int *static_memfuncp, int *num_fns,
+ struct type **basetype, int *boffset)
+{
+ struct type *t;
+
+ t = check_typedef (VALUE_TYPE (*argp));
+
+ /* code snarfed from value_struct_elt */
+ while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+ {
+ *argp = value_ind (*argp);
+ /* Don't coerce fn pointer to fn and then back again! */
+ if (TYPE_CODE (VALUE_TYPE (*argp)) != TYPE_CODE_FUNC)
+ COERCE_ARRAY (*argp);
+ t = check_typedef (VALUE_TYPE (*argp));
+ }
+
+ if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+ error ("Not implemented: member type in value_find_oload_lis");
+
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Attempt to extract a component of a value that is not a struct or union");
+
+ /* Assume it's not static, unless we see that it is. */
+ if (static_memfuncp)
+ *static_memfuncp = 0;
+
+ return find_method_list (argp, method, 0, static_memfuncp, t, num_fns, basetype, boffset);
+
+}
+
+/* Given an array of argument types (ARGTYPES) (which includes an
+ entry for "this" in the case of C++ methods), the number of
+ arguments NARGS, the NAME of a function whether it's a method or
+ not (METHOD), and the degree of laxness (LAX) in conforming to
+ overload resolution rules in ANSI C++, find the best function that
+ matches on the argument types according to the overload resolution
+ rules.
+
+ In the case of class methods, the parameter OBJ is an object value
+ in which to search for overloaded methods.
+
+ In the case of non-method functions, the parameter FSYM is a symbol
+ corresponding to one of the overloaded functions.
+
+ Return value is an integer: 0 -> good match, 10 -> debugger applied
+ non-standard coercions, 100 -> incompatible.
+
+ If a method is being searched for, VALP will hold the value.
+ If a non-method is being searched for, SYMP will hold the symbol for it.
+
+ If a method is being searched for, and it is a static method,
+ then STATICP will point to a non-zero value.
+
+ Note: This function does *not* check the value of
+ overload_resolution. Caller must check it to see whether overload
+ resolution is permitted.
+ */
+
+int
+find_overload_match (struct type **arg_types, int nargs, char *name, int method,
+ int lax, value_ptr obj, struct symbol *fsym,
+ value_ptr *valp, struct symbol **symp, int *staticp)
+{
+ int nparms;
+ struct type **parm_types;
+ int champ_nparms = 0;
+
+ short oload_champ = -1; /* Index of best overloaded function */
+ short oload_ambiguous = 0; /* Current ambiguity state for overload resolution */
+ /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs */
+ short oload_ambig_champ = -1; /* 2nd contender for best match */
+ short oload_non_standard = 0; /* did we have to use non-standard conversions? */
+ short oload_incompatible = 0; /* are args supplied incompatible with any function? */
+
+ struct badness_vector *bv; /* A measure of how good an overloaded instance is */
+ struct badness_vector *oload_champ_bv = NULL; /* The measure for the current best match */
+
+ value_ptr temp = obj;
+ struct fn_field *fns_ptr = NULL; /* For methods, the list of overloaded methods */
+ struct symbol **oload_syms = NULL; /* For non-methods, the list of overloaded function symbols */
+ int num_fns = 0; /* Number of overloaded instances being considered */
+ struct type *basetype = NULL;
+ int boffset;
+ register int jj;
+ register int ix;
+
+ char *obj_type_name = NULL;
+ char *func_name = NULL;
+
+ /* Get the list of overloaded methods or functions */
+ if (method)
+ {
+ int i;
+ int len;
+ struct type *domain;
+ obj_type_name = TYPE_NAME (VALUE_TYPE (obj));
+ /* Hack: evaluate_subexp_standard often passes in a pointer
+ value rather than the object itself, so try again */
+ if ((!obj_type_name || !*obj_type_name) &&
+ (TYPE_CODE (VALUE_TYPE (obj)) == TYPE_CODE_PTR))
+ obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (VALUE_TYPE (obj)));
+
+ fns_ptr = value_find_oload_method_list (&temp, name, 0,
+ staticp,
+ &num_fns,
+ &basetype, &boffset);
+ if (!fns_ptr || !num_fns)
+ error ("Couldn't find method %s%s%s",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ domain = TYPE_DOMAIN_TYPE (fns_ptr[0].type);
+ len = TYPE_NFN_FIELDS (domain);
+ /* NOTE: dan/2000-03-10: This stuff is for STABS, which won't
+ give us the info we need directly in the types. We have to
+ use the method stub conversion to get it. Be aware that this
+ is by no means perfect, and if you use STABS, please move to
+ DWARF-2, or something like it, because trying to improve
+ overloading using STABS is really a waste of time. */
+ for (i = 0; i < len; i++)
+ {
+ int j;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (domain, i);
+ int len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ if (TYPE_FN_FIELD_STUB (f, j) && (!strcmp_iw (TYPE_FN_FIELDLIST_NAME (domain,i),name)))
+ check_stub_method (domain, i, j);
+ }
+ }
+ }
+ else
+ {
+ int i = -1;
+ func_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_NO_OPTS);
+
+ /* If the name is NULL this must be a C-style function.
+ Just return the same symbol. */
+ if (!func_name)
+ {
+ *symp = fsym;
+ return 0;
+ }
+
+ oload_syms = make_symbol_overload_list (fsym);
+ while (oload_syms[++i])
+ num_fns++;
+ if (!num_fns)
+ error ("Couldn't find function %s", func_name);
+ }
+
+ oload_champ_bv = NULL;
+
+ /* Consider each candidate in turn */
+ for (ix = 0; ix < num_fns; ix++)
+ {
+ if (method)
+ {
+ /* For static member functions, we won't have a this pointer, but nothing
+ else seems to handle them right now, so we just pretend ourselves */
+ nparms=0;
+
+ if (TYPE_FN_FIELD_ARGS(fns_ptr,ix))
+ {
+ while (TYPE_CODE(TYPE_FN_FIELD_ARGS(fns_ptr,ix)[nparms]) != TYPE_CODE_VOID)
+ nparms++;
+ }
+ }
+ else
+ {
+ /* If it's not a method, this is the proper place */
+ nparms=TYPE_NFIELDS(SYMBOL_TYPE(oload_syms[ix]));
+ }
+
+ /* Prepare array of parameter types */
+ parm_types = (struct type **) xmalloc (nparms * (sizeof (struct type *)));
+ for (jj = 0; jj < nparms; jj++)
+ parm_types[jj] = (method
+ ? (TYPE_FN_FIELD_ARGS (fns_ptr, ix)[jj])
+ : TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), jj));
+
+ /* Compare parameter types to supplied argument types */
+ bv = rank_function (parm_types, nparms, arg_types, nargs);
+
+ if (!oload_champ_bv)
+ {
+ oload_champ_bv = bv;
+ oload_champ = 0;
+ champ_nparms = nparms;
+ }
+ else
+ /* See whether current candidate is better or worse than previous best */
+ switch (compare_badness (bv, oload_champ_bv))
+ {
+ case 0:
+ oload_ambiguous = 1; /* top two contenders are equally good */
+ oload_ambig_champ = ix;
+ break;
+ case 1:
+ oload_ambiguous = 2; /* incomparable top contenders */
+ oload_ambig_champ = ix;
+ break;
+ case 2:
+ oload_champ_bv = bv; /* new champion, record details */
+ oload_ambiguous = 0;
+ oload_champ = ix;
+ oload_ambig_champ = -1;
+ champ_nparms = nparms;
+ break;
+ case 3:
+ default:
+ break;
+ }
+ xfree (parm_types);
+ if (overload_debug)
+ {
+ if (method)
+ fprintf_filtered (gdb_stderr,"Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
+ else
+ fprintf_filtered (gdb_stderr,"Overloaded function instance %s # of parms %d\n", SYMBOL_DEMANGLED_NAME (oload_syms[ix]), nparms);
+ for (jj = 0; jj < nargs; jj++)
+ fprintf_filtered (gdb_stderr,"...Badness @ %d : %d\n", jj, bv->rank[jj]);
+ fprintf_filtered (gdb_stderr,"Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
+ }
+ } /* end loop over all candidates */
+ /* NOTE: dan/2000-03-10: Seems to be a better idea to just pick one
+ if they have the exact same goodness. This is because there is no
+ way to differentiate based on return type, which we need to in
+ cases like overloads of .begin() <It's both const and non-const> */
+#if 0
+ if (oload_ambiguous)
+ {
+ if (method)
+ error ("Cannot resolve overloaded method %s%s%s to unique instance; disambiguate by specifying function signature",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ else
+ error ("Cannot resolve overloaded function %s to unique instance; disambiguate by specifying function signature",
+ func_name);
+ }
+#endif
+
+ /* Check how bad the best match is */
+ for (ix = 1; ix <= nargs; ix++)
+ {
+ if (oload_champ_bv->rank[ix] >= 100)
+ oload_incompatible = 1; /* truly mismatched types */
+
+ else if (oload_champ_bv->rank[ix] >= 10)
+ oload_non_standard = 1; /* non-standard type conversions needed */
+ }
+ if (oload_incompatible)
+ {
+ if (method)
+ error ("Cannot resolve method %s%s%s to any overloaded instance",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ else
+ error ("Cannot resolve function %s to any overloaded instance",
+ func_name);
+ }
+ else if (oload_non_standard)
+ {
+ if (method)
+ warning ("Using non-standard conversion to match method %s%s%s to supplied arguments",
+ obj_type_name,
+ (obj_type_name && *obj_type_name) ? "::" : "",
+ name);
+ else
+ warning ("Using non-standard conversion to match function %s to supplied arguments",
+ func_name);
+ }
+
+ if (method)
+ {
+ if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
+ *valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
+ else
+ *valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
+ }
+ else
+ {
+ *symp = oload_syms[oload_champ];
+ xfree (func_name);
+ }
+
+ return oload_incompatible ? 100 : (oload_non_standard ? 10 : 0);
+}
+