From Daniel Berlin:
authorAndrew Cagney <cagney@redhat.com>
Mon, 13 Mar 2000 10:01:23 +0000 (10:01 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 13 Mar 2000 10:01:23 +0000 (10:01 +0000)
Fix C++ overloading, add support for seeing through references.

gdb/ChangeLog
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/valops.c

index f108af1..afee75f 100644 (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
index 2016672..d361d15 100644 (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;
index 3c124f0..36f775a 100644 (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 */
index 5dc6b1e..7ead578 100644 (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;
     }