From d65ba3f9b7440642823bb634356a860c2e5db0c5 Mon Sep 17 00:00:00 2001 From: cagney Date: Mon, 13 Mar 2000 10:01:22 +0000 Subject: [PATCH] From Daniel Berlin: Fix C++ overloading, add support for seeing through references. --- gdb/ChangeLog | 28 +++++++++++++++++++++++ gdb/gdbtypes.c | 33 +++++++++++++++++++-------- gdb/gdbtypes.h | 4 +++- gdb/valops.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 113 insertions(+), 24 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f108af151e..afee75fa10 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,31 @@ +Mon Mar 13 18:54:42 2000 Andrew Cagney + + From 2000-03-10 Daniel Berlin 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 * gnu-nat.c: Fix the formatting where indent misinterpreted `&' as diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 20166722d3..d361d154d4 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -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 ''. + (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; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 3c124f0609..36f775a247 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -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 */ diff --git a/gdb/valops.c b/gdb/valops.c index 5dc6b1e7fe..7ead578be1 100644 --- a/gdb/valops.c +++ b/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 && (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() */ +#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; } -- 2.11.0