Fix C++ overload support, see through references
This commit is contained in:
parent
36c2118fc9
commit
09b59ee380
5 changed files with 411 additions and 331 deletions
|
@ -1,3 +1,33 @@
|
|||
2000-03-10 Daniel Berlin <dan@cgsoftware.com>
|
||||
Fix C++ overloading, add support for seeing through references.
|
||||
|
||||
* defs.h (STREQ_IW): add STREQ_IW, like STREQ, except it's
|
||||
whitespace insensitive
|
||||
|
||||
* 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->STREQ_IW
|
||||
(search_struct_field): STREQ->STREQ_IW
|
||||
(find_method_list): STREQ->STREQ_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.
|
||||
|
||||
|
||||
Fri Mar 10 11:44:55 2000 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* MAINTAINERS: Devolve responsibility for domain maintenance.
|
||||
|
|
|
@ -122,6 +122,7 @@ extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs);
|
|||
|
||||
#define STRCMP(a,b) (*(a) == *(b) ? strcmp ((a), (b)) : (int)*(a) - (int)*(b))
|
||||
#define STREQ(a,b) (*(a) == *(b) ? !strcmp ((a), (b)) : 0)
|
||||
#define STREQ_IW(a,b) (*(a) == *(b) ? !strcmp_iw ((a), (b)) : 0)
|
||||
#define STREQN(a,b,c) (*(a) == *(b) ? !strncmp ((a), (b), (c)) : 0)
|
||||
|
||||
/* The character GNU C++ uses to build identifiers that must be unique from
|
||||
|
|
|
@ -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 && STREQ_IW (t_field_name, name))
|
||||
{
|
||||
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,7 +2178,13 @@ rank_one_type (parm, arg)
|
|||
if (parm == arg)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
/* 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 */
|
||||
printf ("------ Arg is %s [%d], parm is %s [%d]\n",
|
||||
TYPE_NAME (arg), TYPE_CODE (arg), TYPE_NAME (parm), TYPE_CODE (parm));
|
||||
|
@ -2246,16 +2252,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 +2269,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;
|
||||
|
|
|
@ -1129,9 +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 */
|
||||
#define NS_POINTER_CONVERSION_BADNESS 10
|
||||
|
|
66
gdb/valops.c
66
gdb/valops.c
|
@ -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 && STREQ_IW (t_field_name, name))
|
||||
{
|
||||
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"))))
|
||||
&& STREQ_IW (t_field_name, "else"))))
|
||||
{
|
||||
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)));
|
||||
&& STREQ_IW (name, TYPE_BASECLASS_NAME (type, i)));
|
||||
|
||||
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))
|
||||
{
|
||||
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 && STREQ_IW (fn_field_name, method))
|
||||
{
|
||||
*num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i);
|
||||
*basetype = type;
|
||||
|
@ -2736,6 +2736,9 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
|
|||
|
||||
char *obj_type_name = NULL;
|
||||
char *func_name = NULL;
|
||||
int i,j,len,len2;
|
||||
struct type *domain;
|
||||
struct fn_field *f;
|
||||
|
||||
/* Get the list of overloaded methods or functions */
|
||||
if (method)
|
||||
|
@ -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);
|
||||
/*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++)
|
||||
{
|
||||
f = TYPE_FN_FIELDLIST1 (domain, i);
|
||||
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,14 +2805,28 @@ 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)
|
||||
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 */
|
||||
|
@ -2830,12 +2867,16 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp,
|
|||
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 */
|
||||
|
||||
/* 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 +2888,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 +2985,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 && STREQ_IW (t_field_name, name))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2960,7 +3002,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 (STREQ_IW (TYPE_FN_FIELDLIST_NAME (type, i), name))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue