A bunch of changes mostly to improve debugging of C++ programs.
authorJohn Gilmore <gnu@cygnus>
Tue, 6 Oct 1992 09:22:43 +0000 (09:22 +0000)
committerJohn Gilmore <gnu@cygnus>
Tue, 6 Oct 1992 09:22:43 +0000 (09:22 +0000)
Specifically, the calling of inferiors methods is improved.

* value.h:  New macros METHOD_PTR_IS_VIRTUAL,
METHOD_PTR_FROM_VOFFSET, METHOD_PTR_TO_VOFFSET to partially
hide the implementation details of pointer-to-method objects.
How to tell if the pointer points to a virtual method is
still very dependent on the particular compiler, but this
should make it easier to find the places to change.
* eval.c (evaluate_subexp [case OP_FUNCALL]), valprint.c
(val_print [case TYPE_CODE_PTR]):  Use the new METHOD_PTR_*
macros, instead of a hard-wired-in code that incorrectly
assumed a no-longerused representation of pointer-to-method
values.  And otherwise fix the relevant bit-rotted code.

* valprint.c (type_print_base [case TYPE_CODE_STRUCT]):
If there are both fields and methods, put a space between.

* stabsread.c (read_struct_type):  Fix bug in handling of
GNU C++ anonymous type (indicated by CPLUS_MARKER followed
by '_').  (It used to prematurely exit the loop reading in
the fields, so it would think it should start reading
methods while still in the fields.  This could crash gdb
given a gcc that can emit nested type information.)

* valops.c (search_struct_method):  Pass 'this' value by
reference instead of by value.  This provides a more
consistent interface through a recursive search where the
"bottom" functions may need to adjust offsets (due to multiple
inheritance).
* valops.c, value.h, values.c:  Pass extra parameters to
value_fn_field and value_virtual_fn_field so we can
correctly adjust offset for multiple inheritance.
* eval.c (evaluate_subexp [case OP_FUNCALL]):  Simplify
virtual function calls by using value_virtual_fn_field().
* values.c: New function baseclass_offset, derived from
baseclass_addr (which perhaps can be made obsolete?).
It returns an offset rather than an address.  This is a
cleaner interface since it doesn't mess around allocating
new values.
* valops.c (search_struct_method):  Use baseclass_offset
rather than baseclass_addr.

gdb/ChangeLog
gdb/stabsread.c
gdb/values.c

index c22a4aa9e138d216bf70b4e9c272af68c38f0583..4a08c2d31cacdc4f5d8b7a4ce600dfc0e4f7f2d5 100644 (file)
@@ -1,3 +1,48 @@
+Fri Sep  4 00:34:30 1992  Per Bothner  (bothner@rtl.cygnus.com)
+
+       A bunch of changes mostly to improve debugging of C++ programs.
+       Specifically, the calling of inferiors methods is improved.
+
+       * value.h:  New macros METHOD_PTR_IS_VIRTUAL,
+       METHOD_PTR_FROM_VOFFSET, METHOD_PTR_TO_VOFFSET to partially
+       hide the implementation details of pointer-to-method objects.
+       How to tell if the pointer points to a virtual method is
+       still very dependent on the particular compiler, but this
+       should make it easier to find the places to change.
+       * eval.c (evaluate_subexp [case OP_FUNCALL]), valprint.c
+       (val_print [case TYPE_CODE_PTR]):  Use the new METHOD_PTR_*
+       macros, instead of a hard-wired-in code that incorrectly
+       assumed a no-longerused representation of pointer-to-method
+       values.  And otherwise fix the relevant bit-rotted code.
+
+       * valprint.c (type_print_base [case TYPE_CODE_STRUCT]):
+       If there are both fields and methods, put a space between.
+
+       * stabsread.c (read_struct_type):  Fix bug in handling of
+       GNU C++ anonymous type (indicated by CPLUS_MARKER followed
+       by '_').  (It used to prematurely exit the loop reading in
+       the fields, so it would think it should start reading
+       methods while still in the fields.  This could crash gdb
+       given a gcc that can emit nested type information.)
+
+       * valops.c (search_struct_method):  Pass 'this' value by
+       reference instead of by value.  This provides a more
+       consistent interface through a recursive search where the
+       "bottom" functions may need to adjust offsets (due to multiple
+       inheritance).
+       * valops.c, value.h, values.c:  Pass extra parameters to
+       value_fn_field and value_virtual_fn_field so we can
+       correctly adjust offset for multiple inheritance.
+       * eval.c (evaluate_subexp [case OP_FUNCALL]):  Simplify
+       virtual function calls by using value_virtual_fn_field().
+       * values.c: New function baseclass_offset, derived from
+       baseclass_addr (which perhaps can be made obsolete?).
+       It returns an offset rather than an address.  This is a
+       cleaner interface since it doesn't mess around allocating
+       new values.
+       * valops.c (search_struct_method):  Use baseclass_offset
+       rather than baseclass_addr.
+
 Mon Oct  5 16:02:04 1992  Stu Grossman  (grossman at cygnus.com)
 
        * Makefile.in:  Re-install 29K/UDI stuff.
index 6bf29f4e9e20fbca880dfd1cd48c414f20c1dba8..532154ef1077502ed94070c825b34b0810628c04 100644 (file)
@@ -1430,8 +1430,10 @@ read_struct_type (pp, type, objfile)
       p = *pp;
       if (*p == CPLUS_MARKER)
        {
+         if (*p == '_')    /* GNU C++ anonymous type.  */
+           ;
          /* Special GNU C++ name.  */
-         if (*++p == 'v')
+         else if (*++p == 'v')
            {
              const char *prefix;
              char *name = 0;
@@ -1470,15 +1472,12 @@ read_struct_type (pp, type, objfile)
              list->field.bitsize = 0;
              list->visibility = 0;     /* private */
              non_public_fields++;
+
+             nfields++;
+             continue;
            }
-         /* GNU C++ anonymous type.  */
-         else if (*p == '_')
-           break;
          else
            complain (&invalid_cpp_abbrev_complaint, *pp);
-
-         nfields++;
-         continue;
        }
 
       while (*p != ':') p++;
index 8c299ccb25c1d53c85dba72b4e22dadd4324ca3d..aaff412690fc27e4a6ec1b69efa18898bcc9fa8d 100644 (file)
@@ -903,12 +903,15 @@ value_field (arg1, fieldno)
    J is an index into F which provides the desired method. */
 
 value
-value_fn_field (f, j)
+value_fn_field (arg1p, f, j, type, offset)
+     value *arg1p;
      struct fn_field *f;
      int j;
+     struct type *type;
+     int offset;
 {
   register value v;
-  register struct type *type = TYPE_FN_FIELD_TYPE (f, j);
+  register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
   struct symbol *sym;
 
   sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
@@ -916,27 +919,40 @@ value_fn_field (f, j)
   if (! sym) error ("Internal error: could not find physical method named %s",
                    TYPE_FN_FIELD_PHYSNAME (f, j));
   
-  v = allocate_value (type);
+  v = allocate_value (ftype);
   VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-  VALUE_TYPE (v) = type;
+  VALUE_TYPE (v) = ftype;
+
+  if (arg1p)
+   {
+    if (type != VALUE_TYPE (*arg1p))
+      *arg1p = value_ind (value_cast (lookup_pointer_type (type),
+                                     value_addr (*arg1p)));
+
+    /* Move the `this' pointer according to the offset. */
+    VALUE_OFFSET (*arg1p) += offset;
+    }
+
   return v;
 }
 
 /* Return a virtual function as a value.
    ARG1 is the object which provides the virtual function
-   table pointer.  ARG1 is side-effected in calling this function.
+   table pointer.  *ARG1P is side-effected in calling this function.
    F is the list of member functions which contains the desired virtual
    function.
    J is an index into F which provides the desired virtual function.
 
    TYPE is the type in which F is located.  */
 value
-value_virtual_fn_field (arg1, f, j, type)
-     value arg1;
+value_virtual_fn_field (arg1p, f, j, type, offset)
+     value *arg1p;
      struct fn_field *f;
      int j;
      struct type *type;
+     int offset;
 {
+  value arg1 = *arg1p;
   /* First, get the virtual function table pointer.  That comes
      with a strange type, so cast it to type `pointer to long' (which
      should serve just fine as a function type).  Then, index into
@@ -968,7 +984,9 @@ value_virtual_fn_field (arg1, f, j, type)
 
   /* The virtual function table is now an array of structures
      which have the form { int16 offset, delta; void *pfn; }.  */
-  vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (context)));
+  vtbl = value_ind (value_primitive_field (arg1, 0, 
+                                          TYPE_VPTR_FIELDNO (context),
+                                          TYPE_VPTR_BASETYPE (context)));
 
   /* Index into the virtual function table.  This is hard-coded because
      looking up a field is not cheap, and it may be important to save
@@ -977,7 +995,7 @@ value_virtual_fn_field (arg1, f, j, type)
   entry = value_subscript (vtbl, vi);
 
   /* Move the `this' pointer according to the virtual function table.  */
-  VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+  VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)) + offset;
   if (! VALUE_LAZY (arg1))
     {
       VALUE_LAZY (arg1) = 1;
@@ -988,6 +1006,7 @@ value_virtual_fn_field (arg1, f, j, type)
   /* Reinstantiate the function pointer with the correct type.  */
   VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
 
+  *arg1p = arg1;
   return vfn;
 }
 
@@ -1103,6 +1122,67 @@ value_from_vtable_info (arg, type)
   return value_headof (arg, 0, type);
 }
 
+/* Compute the offset of the baseclass which is
+   the INDEXth baseclass of class TYPE, for a value ARG,
+   wih extra offset of OFFSET.
+   The result is the offste of the baseclass value relative
+   to (the address of)(ARG) + OFFSET.
+
+   -1 is returned on error. */
+
+int
+baseclass_offset (type, index, arg, offset)
+     struct type *type;
+     int index;
+     value arg;
+     int offset;
+{
+  struct type *basetype = TYPE_BASECLASS (type, index);
+
+  if (BASETYPE_VIA_VIRTUAL (type, index))
+    {
+      /* Must hunt for the pointer to this virtual baseclass.  */
+      register int i, len = TYPE_NFIELDS (type);
+      register int n_baseclasses = TYPE_N_BASECLASSES (type);
+      char *vbase_name, *type_name = type_name_no_tag (basetype);
+
+      vbase_name = (char *)alloca (strlen (type_name) + 8);
+      sprintf (vbase_name, "_vb%c%s", CPLUS_MARKER, type_name);
+      /* First look for the virtual baseclass pointer
+        in the fields.  */
+      for (i = n_baseclasses; i < len; i++)
+       {
+         if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
+           {
+             CORE_ADDR addr
+               = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+                                 VALUE_CONTENTS (arg) + VALUE_OFFSET (arg)
+                                 + offset
+                                 + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+             if (VALUE_LVAL (arg) != lval_memory)
+                 return -1;
+
+             return addr -
+                 (LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset);
+           }
+       }
+      /* Not in the fields, so try looking through the baseclasses.  */
+      for (i = index+1; i < n_baseclasses; i++)
+       {
+         int boffset =
+             baseclass_offset (type, i, arg, offset);
+         if (boffset)
+           return boffset;
+       }
+      /* Not found.  */
+      return -1;
+    }
+
+  /* Baseclass is easily computed.  */
+  return TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
+
 /* Compute the address of the baseclass which is
    the INDEXth baseclass of class TYPE.  The TYPE base
    of the object is at VALADDR.
@@ -1112,6 +1192,8 @@ value_from_vtable_info (arg, type)
    of the baseclasss, but the address which could not be read
    successfully.  */
 
+/* FIXME Fix remaining uses of baseclass_addr to use baseclass_offset */
+
 char *
 baseclass_addr (type, index, valaddr, valuep, errp)
      struct type *type;