From Daniel Berlin:

Fix C++ overloading, add support for seeing through references.
This commit is contained in:
Andrew Cagney 2000-03-13 10:01:23 +00:00
parent 7b83ea04b2
commit db577aea67
4 changed files with 113 additions and 24 deletions

View File

@ -1,3 +1,31 @@
Mon Mar 13 18:54:42 2000 Andrew Cagney <cagney@b1.cygnus.com>
From 2000-03-10 Daniel Berlin <dan@cgsoftware.com> Fix C++
overloading, add support for seeing through references:
* valops.c (find_overload_match): Handle STABS overloading for
C++.
(find_overload_match): Look in right place for function arguments
in the debug info.
(find_overload_match): Rather than giving up when we have >1
perfect match, just choose one, especially since the
recommendation GDB gives ("disambiguate it by specifying function
signature"), is basically impossible.
(check_field_in): STREQ->strcmp_iw
(search_struct_field): STREQ->strcmp_iw
(find_method_list): STREQ->strcmp_iw
* gdbtypes.c (rank_one_type): Add ability to see through
references.
(rank_one_type): strcmp->strcmp_iw, because the whitespace could
be different.
(rank_function): Rank function properly (was doing it wrong
before, comparing the wrong parts of the arrays)
(rank_one_type): Change #if 0 to #ifdef DEBUG_OLOAD.
* gdbtypes.h: Add REFERENCE_CONVERSION_BADNESS for "badness"
associated with converting a non-reference to a reference.
* gdbtypes.c (rank_one_type): Add comment on how to eliminate the
#ifdef DEBUG_OLOAD.
2000-03-11 Mark Kettenis <kettenis@gnu.org>
* gnu-nat.c: Fix the formatting where indent misinterpreted `&' as

View File

@ -994,7 +994,7 @@ lookup_struct_elt_type (type, name, noerr)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
if (t_field_name && STREQ (t_field_name, name))
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
{
return TYPE_FIELD_TYPE (type, i);
}
@ -2136,8 +2136,8 @@ rank_function (parms, nparms, args, nargs)
LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0;
/* Now rank all the parameters of the candidate function */
for (i = 1; i <= min_len; i++)
bv->rank[i] = rank_one_type (parms[i - 1], args[i - 1]);
for (i = 1; i < min_len; i++)
bv->rank[i] = rank_one_type (parms[i], args[i]);
/* If more arguments than parameters, add dummy entries */
for (i = min_len + 1; i <= nargs; i++)
@ -2178,8 +2178,21 @@ rank_one_type (parm, arg)
if (parm == arg)
return 0;
#if 0
/* Debugging only */
/* See through references, since we can almost make non-references
references. */
if (TYPE_CODE (arg) == TYPE_CODE_REF)
return (rank_one_type (TYPE_TARGET_TYPE (arg), parm)
+ REFERENCE_CONVERSION_BADNESS);
if (TYPE_CODE (parm) == TYPE_CODE_REF)
return (rank_one_type (arg, TYPE_TARGET_TYPE (parm))
+ REFERENCE_CONVERSION_BADNESS);
#ifdef DEBUG_OLOAD
/* Debugging only. */
/* FIXME/FYI: cagney/2000-03-13: No need to #ifdef this sort of
thing. Instead add a command like ``set debug gdbtypes <int>''.
(A predicate to this is the addition of the ``set debug''). Also,
send the output to gdb_stderr and don't use printf. */
printf ("------ Arg is %s [%d], parm is %s [%d]\n",
TYPE_NAME (arg), TYPE_CODE (arg), TYPE_NAME (parm), TYPE_CODE (parm));
#endif
@ -2246,16 +2259,16 @@ rank_one_type (parm, arg)
{
if (TYPE_UNSIGNED (arg))
{
if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg)))
if (!strcmp_iw (TYPE_NAME (parm), TYPE_NAME (arg)))
return 0; /* unsigned int -> unsigned int, or unsigned long -> unsigned long */
else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long"))
else if (!strcmp_iw (TYPE_NAME (arg), "int") && !strcmp_iw (TYPE_NAME (parm), "long"))
return INTEGER_PROMOTION_BADNESS; /* unsigned int -> unsigned long */
else
return INTEGER_COERCION_BADNESS; /* unsigned long -> unsigned int */
}
else
{
if (!strcmp (TYPE_NAME (arg), "long") && !strcmp (TYPE_NAME (parm), "int"))
if (!strcmp_iw (TYPE_NAME (arg), "long") && !strcmp_iw (TYPE_NAME (parm), "int"))
return INTEGER_COERCION_BADNESS; /* signed long -> unsigned int */
else
return INTEGER_CONVERSION_BADNESS; /* signed int/long -> unsigned int/long */
@ -2263,9 +2276,9 @@ rank_one_type (parm, arg)
}
else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
{
if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg)))
if (!strcmp_iw (TYPE_NAME (parm), TYPE_NAME (arg)))
return 0;
else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long"))
else if (!strcmp_iw (TYPE_NAME (arg), "int") && !strcmp_iw (TYPE_NAME (parm), "long"))
return INTEGER_PROMOTION_BADNESS;
else
return INTEGER_COERCION_BADNESS;

View File

@ -1129,8 +1129,10 @@ count_virtual_fns PARAMS ((struct type *));
#define POINTER_CONVERSION_BADNESS 2
/* Badness of conversion of pointer to void pointer */
#define VOID_PTR_CONVERSION_BADNESS 2
/* Badness of convering derived to base class */
/* Badness of converting derived to base class */
#define BASE_CONVERSION_BADNESS 2
/* Badness of converting from non-reference to reference */
#define REFERENCE_CONVERSION_BADNESS 2
/* Non-standard conversions allowed by the debugger */
/* Converting a pointer to an int is usually OK */

View File

@ -2068,7 +2068,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
if (t_field_name && STREQ (t_field_name, name))
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
{
value_ptr v;
if (TYPE_FIELD_STATIC (type, i))
@ -2083,7 +2083,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
if (t_field_name
&& (t_field_name[0] == '\0'
|| (TYPE_CODE (type) == TYPE_CODE_UNION
&& STREQ (t_field_name, "else"))))
&& (strcmp_iw (t_field_name, "else") == 0))))
{
struct type *field_type = TYPE_FIELD_TYPE (type, i);
if (TYPE_CODE (field_type) == TYPE_CODE_UNION
@ -2128,7 +2128,7 @@ search_struct_field (name, arg1, offset, type, looking_for_baseclass)
is not yet filled in. */
int found_baseclass = (looking_for_baseclass
&& TYPE_BASECLASS_NAME (type, i) != NULL
&& STREQ (name, TYPE_BASECLASS_NAME (type, i)));
&& (strcmp_iw (name, TYPE_BASECLASS_NAME (type, i)) == 0));
if (BASETYPE_VIA_VIRTUAL (type, i))
{
@ -2314,7 +2314,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
else if (cplus_demangle_opname (t_field_name, dem_opname, 0))
t_field_name = dem_opname;
}
if (t_field_name && STREQ (t_field_name, name))
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
{
int j = TYPE_FN_FIELDLIST_LENGTH (type, i) - 1;
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
@ -2570,7 +2570,7 @@ find_method_list (argp, method, offset, static_memfuncp, type, num_fns, basetype
{
/* pai: FIXME What about operators and type conversions? */
char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
if (fn_field_name && STREQ (fn_field_name, method))
if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
{
*num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i);
*basetype = type;
@ -2740,6 +2740,9 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
/* 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 */
@ -2756,6 +2759,26 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
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))
check_stub_method (domain, i, j);
}
}
}
else
{
@ -2782,15 +2805,30 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
/* Consider each candidate in turn */
for (ix = 0; ix < num_fns; ix++)
{
/* Number of parameters for current candidate */
nparms = method ? TYPE_NFIELDS (fns_ptr[ix].type)
: TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[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_FIELD_TYPE (fns_ptr[ix].type, jj)
: TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), 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);
@ -2826,16 +2864,23 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
}
free (parm_types);
#ifdef DEBUG_OLOAD
/* FIXME: cagney/2000-03-12: Send the output to gdb_stderr. See
comments above about adding a ``set debug'' command. */
if (method)
printf ("Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
else
printf ("Overloaded function instance %s # of parms %d\n", SYMBOL_DEMANGLED_NAME (oload_syms[ix]), nparms);
for (jj = 0; jj <= nargs; jj++)
for (jj = 0; jj < nargs; jj++)
printf ("...Badness @ %d : %d\n", jj, bv->rank[jj]);
printf ("Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
#endif
} /* 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)
@ -2847,6 +2892,7 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
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++)
@ -2943,7 +2989,7 @@ check_field_in (type, name)
for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
if (t_field_name && STREQ (t_field_name, name))
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
return 1;
}
@ -2960,7 +3006,7 @@ check_field_in (type, name)
for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
{
if (STREQ (TYPE_FN_FIELDLIST_NAME (type, i), name))
if (strcmp_iw (TYPE_FN_FIELDLIST_NAME (type, i), name) == 0)
return 1;
}