* values.c (check_stub_method): Do lookup_method_type and stuff
authorJim Kingdon <jkingdon@engr.sgi.com>
Fri, 26 Apr 1991 23:04:10 +0000 (23:04 +0000)
committerJim Kingdon <jkingdon@engr.sgi.com>
Fri, 26 Apr 1991 23:04:10 +0000 (23:04 +0000)
rather than smash_to_method_type.
* values.c (check_stub_method): Deal with operator names.
* values.c: Move declaration of cplus_demangle to top of file.
* values.c (baseclass_addr): If can't read memory, set *ERRP
rather than calling error().
* values.c (value_static_field): Recursively check all baseclasses.
Return NULL if not found.
* values.c, value.h: New functions value_{headof,from_vtable_info}.
values.c (value_virtual_fn_field):
Don't bother to do anything with
return value from fill_in_vptr_fieldno.CVS: Modified Files:

gdb/values.c

index 88ceb3d92e4f11d18cff0b74e32077e039bf87c0..e4578a0cd5f64aac1e17695148eb40666fde8ee5 100644 (file)
@@ -28,6 +28,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "command.h"
 #include "gdbcmd.h"
 
+extern char *cplus_demangle ();
+extern char *cplus_mangle_opname ();
+
 /* The value-history records all the values printed
    by print commands during this session.  Each chunk
    records 60 consecutive values.  The first chunk on
@@ -876,8 +879,7 @@ value_virtual_fn_field (arg1, f, j, type)
      was.  If so, fill in the virtual function table entry for the
      type now.  */
   if (TYPE_VPTR_FIELDNO (context) < 0)
-    TYPE_VPTR_FIELDNO (context)
-      = fill_in_vptr_fieldno (context);
+    fill_in_vptr_fieldno (context);
 
   /* The virtual function table is now an array of structures
      which have the form { int16 offset, delta; void *pfn; }.  */
@@ -904,13 +906,109 @@ value_virtual_fn_field (arg1, f, j, type)
   return vfn;
 }
 
+/* ARG is a pointer to an object we know to be at least
+   a DTYPE.  BTYPE is the most derived basetype that has
+   already been searched (and need not be searched again).
+   After looking at the vtables between BTYPE and DTYPE,
+   return the most derived type we find.  The caller must
+   be satisfied when the return value == DTYPE.
+
+   FIXME-tiemann: should work with dossier entries as well.  */
+
+static value
+value_headof (arg, btype, dtype)
+     value arg;
+     struct type *btype, *dtype;
+{
+  /* First collect the vtables we must look at for this object.  */
+  /* FIXME-tiemann: right now, just look at top-most vtable.  */
+  value vtbl, entry, best_entry = 0;
+  struct type *entry_type;
+  int i, nelems;
+  int offset, best_offset = 0;
+  struct symbol *sym;
+  CORE_ADDR pc_for_sym;
+  char *demangled_name;
+
+  vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (dtype)));
+
+  /* Check that VTBL looks like it points to a virtual function table.  */
+  i = find_pc_misc_function (VALUE_ADDRESS (vtbl));
+  if (i < 0 || ! VTBL_PREFIX_P (misc_function_vector[i].name))
+    {
+      /* If we expected to find a vtable, but did not, let the user
+        know that we aren't happy, but don't throw an error.
+        FIXME: there has to be a better way to do this.  */
+      struct type *error_type = (struct type *)xmalloc (sizeof (struct type));
+      bcopy (VALUE_TYPE (arg), error_type, sizeof (struct type));
+      TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
+      VALUE_TYPE (arg) = error_type;
+      return arg;
+    }
+
+  /* Now search through the virtual function table.  */
+  entry = value_ind (vtbl);
+  entry_type = VALUE_TYPE (entry);
+  nelems = value_as_long (value_field (entry, 2));
+  for (i = 1; i <= nelems; i++)
+    {
+      entry = value_subscript (vtbl, value_from_long (builtin_type_int, i));
+      offset = value_as_long (value_field (entry, 0));
+      if (offset < best_offset)
+       {
+         best_offset = offset;
+         best_entry = entry;
+       }
+    }
+  if (best_entry == 0)
+    return arg;
+
+  /* Move the pointer according to BEST_ENTRY's offset, and figure
+     out what type we should return as the new pointer.  */
+  pc_for_sym = value_as_long (value_field (best_entry, 2));
+  sym = find_pc_function (pc_for_sym);
+  demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1);
+  *(strchr (demangled_name, ':')) = '\0';
+  sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
+  if (sym == 0)
+    error ("could not find type declaration for `%s'", SYMBOL_NAME (sym));
+  free (demangled_name);
+  arg = value_add (value_cast (builtin_type_int, arg),
+                  value_field (best_entry, 0));
+  VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
+  return arg;
+}
+
+/* ARG is a pointer object of type TYPE.  If TYPE has virtual
+   function tables, probe ARG's tables (including the vtables
+   of its baseclasses) to figure out the most derived type that ARG
+   could actually be a pointer to.  */
+
+value
+value_from_vtable_info (arg, type)
+     value arg;
+     struct type *type;
+{
+  /* Take care of preliminaries.  */
+  if (TYPE_VPTR_FIELDNO (type) < 0)
+    fill_in_vptr_fieldno (type);
+  if (TYPE_VPTR_FIELDNO (type) < 0 || VALUE_REPEATED (arg))
+    return 0;
+
+  return value_headof (arg, 0, type);
+}
+
 /* The value of a static class member does not depend
    on its instance, only on its type.  If FIELDNO >= 0,
    then fieldno is a valid field number and is used directly.
    Otherwise, FIELDNAME is the name of the field we are
    searching for.  If it is not a static field name, an
    error is signaled.  TYPE is the type in which we look for the
-   static field member.  */
+   static field member.
+
+   Return zero if we couldn't find anything; the caller may signal
+   an error in that case.  */
+
 value
 value_static_field (type, fieldname, fieldno)
      register struct type *type;
@@ -925,41 +1023,32 @@ value_static_field (type, fieldname, fieldno)
     {
       register struct type *t = type;
       /* Look for static field.  */
-      while (t)
-       {
-         int i;
-         for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
-           if (! strcmp (TYPE_FIELD_NAME (t, i), fieldname))
+      int i;
+      for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+       if (! strcmp (TYPE_FIELD_NAME (type, i), fieldname))
+         {
+           if (TYPE_FIELD_STATIC (type, i))
              {
-               if (TYPE_FIELD_STATIC (t, i))
-                 {
-                   fieldno = i;
-                   goto found;
-                 }
-               else
-                 error ("field `%s' is not static");
+               fieldno = i;
+               goto found;
              }
-         /* FIXME: this does not recursively check multiple baseclasses.  */
-         t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0;
+           else
+             error ("field `%s' is not static", fieldname);
+         }
+      for (; i > 0; i--)
+       {
+         v = value_static_field (TYPE_BASECLASS (type, i), fieldname, -1);
+         if (v != 0)
+           return v;
        }
 
-      t = type;
-
-      if (destructor_name_p (fieldname, t))
+      if (destructor_name_p (fieldname, type))
        error ("Cannot get value of destructor");
 
-      while (t)
+      for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
        {
-         int i;
-
-         for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
-           {
-             if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
-               {
-                 error ("Cannot get value of method \"%s\"", fieldname);
-               }
-           }
-         t = TYPE_N_BASECLASSES (t) ? TYPE_BASECLASS (t, 0) : 0;
+         if (! strcmp (TYPE_FN_FIELDLIST_NAME (type, i), fieldname))
+           error ("Cannot get value of method \"%s\"", fieldname);
        }
       error("there is no field named %s", fieldname);
     }
@@ -976,17 +1065,26 @@ value_static_field (type, fieldname, fieldno)
 
 /* Compute the address of the baseclass which is
    the INDEXth baseclass of TYPE.  The TYPE base
-   of the object is at VALADDR.  */
+   of the object is at VALADDR.
+
+   If ERRP is non-NULL, set *ERRP to be the errno code of any error,
+   or 0 if no error.  In that case the return value is not the address
+   of the baseclasss, but the address which could not be read
+   successfully.  */
 
 char *
-baseclass_addr (type, index, valaddr, valuep)
+baseclass_addr (type, index, valaddr, valuep, errp)
      struct type *type;
      int index;
      char *valaddr;
      value *valuep;
+     int *errp;
 {
   struct type *basetype = TYPE_BASECLASS (type, index);
 
+  if (errp)
+    *errp = 0;
+  
   if (BASETYPE_VIA_VIRTUAL (type, index))
     {
       /* Must hunt for the pointer to this virtual baseclass.  */
@@ -1005,12 +1103,35 @@ baseclass_addr (type, index, valaddr, valuep)
        {
          if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
            {
-             value v = value_at (basetype,
-                                 unpack_long (TYPE_FIELD_TYPE (type, i),
-                                              valaddr + (TYPE_FIELD_BITPOS (type, i) / 8)));
-             if (valuep)
-               *valuep = v;
-             return (char *) VALUE_CONTENTS (v);
+             value val = allocate_value (basetype);
+             CORE_ADDR addr;
+             int status;
+
+             addr = unpack_long (TYPE_FIELD_TYPE (type, i),
+                                 valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+             status = target_read_memory (addr,
+                                          VALUE_CONTENTS_RAW (val),
+                                          TYPE_LENGTH (type));
+             VALUE_LVAL (val) = lval_memory;
+             VALUE_ADDRESS (val) = addr;
+
+             if (status != 0)
+               {
+                 if (valuep)
+                   *valuep = NULL;
+                 release_value (val);
+                 value_free (val);
+                 if (errp)
+                   *errp = status;
+                 return (char *)addr;
+               }
+             else
+               {
+                 if (valuep)
+                   *valuep = val;
+                 return (char *) VALUE_CONTENTS (val);
+               }
            }
        }
       /* Not in the fields, so try looking through the baseclasses.  */
@@ -1050,18 +1171,33 @@ check_stub_method (type, i, j)
 {
   extern char *gdb_mangle_typename (), *strchr ();
   struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+  char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
   char *inner_name = gdb_mangle_typename (type);
-  char *mangled_name
-    = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i))
-                      + strlen (inner_name)
-                      + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
-                      + 1);
-  char *demangled_name, *cplus_demangle ();
+  int mangled_name_len = (strlen (field_name)
+                         + strlen (inner_name)
+                         + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
+                         + 1);
+  char *mangled_name;
+  char *demangled_name;
   char *argtypetext, *p;
   int depth = 0, argcount = 1;
   struct type **argtypes;
 
-  strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
+  if (OPNAME_PREFIX_P (field_name))
+    {
+      char *opname = cplus_mangle_opname (field_name + 3);
+      mangled_name_len += strlen (opname);
+      mangled_name = (char *)xmalloc (mangled_name_len);
+
+      strncpy (mangled_name, field_name, 3);
+      mangled_name[3] = '\0';
+      strcat (mangled_name, opname);
+    }
+  else
+    {
+      mangled_name = (char *)xmalloc (mangled_name_len);
+      strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
+    }
   strcat (mangled_name, inner_name);
   strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
   demangled_name = cplus_demangle (mangled_name, 0);
@@ -1119,11 +1255,12 @@ check_stub_method (type, i, j)
     argtypes[argcount] = NULL;         /* List terminator */
 
   free (demangled_name);
-  smash_to_method_type (TYPE_FN_FIELD_TYPE (f, j), type,
-                       TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
-                       argtypes);
+  
+  type = lookup_method_type (type, TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), argtypes);
+  /* Free the stub type...it's no longer needed.  */
+  free (TYPE_FN_FIELD_TYPE (f, j));
   TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
-  TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) &= ~TYPE_FLAG_STUB;
+  TYPE_FN_FIELD_TYPE (f, j) = type;
 }
 \f
 long