Not part of the sources
[deliverable/binutils-gdb.git] / gdb / gdbtypes.c
index 233cb7f77d4a37bf3a93a6df67d385056e7ad0bf..03934623d19a6b42b9c6910eb88cf3e4763117ca 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for manipulating internal types for GDB.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc.
    Contributed by Cygnus Support, using pieces from other GDB modules.
 
 This file is part of GDB.
@@ -16,10 +16,10 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
 #include "bfd.h"
 #include "symtab.h"
 #include "symfile.h"
@@ -31,6 +31,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "value.h"
 #include "demangle.h"
 #include "complaints.h"
+#include "gdbcmd.h"
 
 /* These variables point to the objects
    representing the predefined C data types.  */
@@ -53,6 +54,30 @@ struct type *builtin_type_long_double;
 struct type *builtin_type_complex;
 struct type *builtin_type_double_complex;
 struct type *builtin_type_string;
+struct type *builtin_type_int8;
+struct type *builtin_type_uint8;
+struct type *builtin_type_int16;
+struct type *builtin_type_uint16;
+struct type *builtin_type_int32;
+struct type *builtin_type_uint32;
+struct type *builtin_type_int64;
+struct type *builtin_type_uint64;
+struct type *builtin_type_bool;
+
+int opaque_type_resolution = 1;
+
+
+struct extra { char str[128]; int len; }; /* maximum extention is 128! FIXME */
+
+static void add_name PARAMS ((struct extra *, char *));
+static void add_mangled_type PARAMS ((struct extra *, struct type *));
+#if 0
+static void cfront_mangle_name PARAMS ((struct type *, int, int));
+#endif
+static void print_bit_vector PARAMS ((B_TYPE *, int));
+static void print_arg_types PARAMS ((struct type **, int));
+static void dump_fn_fieldlists PARAMS ((struct type *, int));
+static void print_cplus_stuff PARAMS ((struct type *, int));
 
 /* Alloc a new type structure and fill it with some defaults.  If
    OBJFILE is non-NULL, then allocate the space for the type structure
@@ -74,6 +99,7 @@ alloc_type (objfile)
     {
       type  = (struct type *) obstack_alloc (&objfile -> type_obstack,
                                             sizeof (struct type));
+      OBJSTAT (objfile, n_types++);
     }
   memset ((char *) type, 0, sizeof (struct type));
 
@@ -82,6 +108,7 @@ alloc_type (objfile)
   TYPE_CODE (type) = TYPE_CODE_UNDEF;
   TYPE_OBJFILE (type) = objfile;
   TYPE_VPTR_FIELDNO (type) = -1;
+  TYPE_CV_TYPE (type) = type;  /* chain back to itself */ 
 
   return (type);
 }
@@ -102,13 +129,15 @@ make_pointer_type (type, typeptr)
   ntype = TYPE_POINTER_TYPE (type);
 
   if (ntype) 
-    if (typeptr == 0)          
-      return ntype;    /* Don't care about alloc, and have new type.  */
-    else if (*typeptr == 0)
-      {
-       *typeptr = ntype;       /* Tracking alloc, and we have new type.  */
-       return ntype;
-      }
+    {
+      if (typeptr == 0)                
+        return ntype;  /* Don't care about alloc, and have new type.  */
+      else if (*typeptr == 0)
+        {
+         *typeptr = ntype;     /* Tracking alloc, and we have new type.  */
+         return ntype;
+        }
+    }
 
   if (typeptr == 0 || *typeptr == 0)   /* We'll need to allocate one.  */
     {
@@ -167,13 +196,15 @@ make_reference_type (type, typeptr)
   ntype = TYPE_REFERENCE_TYPE (type);
 
   if (ntype) 
-    if (typeptr == 0)          
-      return ntype;    /* Don't care about alloc, and have new type.  */
-    else if (*typeptr == 0)
-      {
-       *typeptr = ntype;       /* Tracking alloc, and we have new type.  */
-       return ntype;
-      }
+    {
+      if (typeptr == 0)                
+        return ntype;  /* Don't care about alloc, and have new type.  */
+      else if (*typeptr == 0)
+        {
+         *typeptr = ntype;     /* Tracking alloc, and we have new type.  */
+         return ntype;
+        }
+    }
 
   if (typeptr == 0 || *typeptr == 0)   /* We'll need to allocate one.  */
     {
@@ -226,17 +257,6 @@ make_function_type (type, typeptr)
   register struct type *ntype;         /* New type */
   struct objfile *objfile;
 
-  ntype = TYPE_FUNCTION_TYPE (type);
-
-  if (ntype) 
-    if (typeptr == 0)          
-      return ntype;    /* Don't care about alloc, and have new type.  */
-    else if (*typeptr == 0)
-      {
-       *typeptr = ntype;       /* Tracking alloc, and we have new type.  */
-       return ntype;
-      }
-
   if (typeptr == 0 || *typeptr == 0)   /* We'll need to allocate one.  */
     {
       ntype = alloc_type (TYPE_OBJFILE (type));
@@ -252,14 +272,10 @@ make_function_type (type, typeptr)
     }
 
   TYPE_TARGET_TYPE (ntype) = type;
-  TYPE_FUNCTION_TYPE (type) = ntype;
 
   TYPE_LENGTH (ntype) = 1;
   TYPE_CODE (ntype) = TYPE_CODE_FUNC;
   
-  if (!TYPE_FUNCTION_TYPE (type))      /* Remember it, if don't have one.  */
-    TYPE_FUNCTION_TYPE (type) = ntype;
-
   return ntype;
 }
 
@@ -274,6 +290,89 @@ lookup_function_type (type)
   return make_function_type (type, (struct type **)0);
 }
 
+
+/* Make a "c-v" variant of a type -- a type that is identical to the
+   one supplied except that it may have const or volatile attributes
+   CNST is a flag for setting the const attribute
+   VOLTL is a flag for setting the volatile attribute
+   TYPE is the base type whose variant we are creating.
+   TYPEPTR, if nonzero, points
+   to a pointer to memory where the reference type should be stored.
+   If *TYPEPTR is zero, update it to point to the reference type we return.
+   We allocate new memory if needed.  */
+
+struct type *
+make_cv_type (cnst, voltl, type, typeptr)
+     int cnst;
+     int voltl;
+     struct type *type;
+     struct type **typeptr;
+{
+  register struct type *ntype;          /* New type */
+  register struct type *tmp_type = type; /* tmp type */
+  struct objfile *objfile;
+
+  ntype = TYPE_CV_TYPE (type);
+
+  while (ntype != type)
+    {
+      if ((TYPE_CONST (ntype) == cnst) &&
+          (TYPE_VOLATILE (ntype) == voltl))
+          {
+            if (typeptr == 0)
+              return ntype;
+            else if (*typeptr == 0)
+              {
+                *typeptr = ntype;      /* Tracking alloc, and we have new type.  */
+                return ntype;
+              }
+          }
+      tmp_type = ntype;
+      ntype = TYPE_CV_TYPE (ntype);
+    }
+
+  if (typeptr == 0 || *typeptr == 0)   /* We'll need to allocate one.  */
+    {
+      ntype = alloc_type (TYPE_OBJFILE (type));
+      if (typeptr)
+       *typeptr = ntype;
+    }
+  else                         /* We have storage, but need to reset it.  */
+    {
+      ntype = *typeptr;
+      objfile = TYPE_OBJFILE (ntype);
+      /* memset ((char *) ntype, 0, sizeof (struct type)); */
+      TYPE_OBJFILE (ntype) = objfile;
+    }
+
+  /* Copy original type */ 
+  memcpy ((char *) ntype, (char *) type, sizeof (struct type));
+  /* But zero out fields that shouldn't be copied */
+  TYPE_POINTER_TYPE (ntype) = (struct type *) 0;    /* Need new pointer kind */
+  TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0;  /* Need new referene kind */
+  /* Note: TYPE_TARGET_TYPE can be left as is */
+
+  /* Set flags appropriately */
+  if (cnst)
+    TYPE_FLAGS (ntype) |=  TYPE_FLAG_CONST;
+  else
+    TYPE_FLAGS (ntype) &=  ~TYPE_FLAG_CONST;
+
+  if (voltl)
+    TYPE_FLAGS (ntype) |=  TYPE_FLAG_VOLATILE;
+  else
+    TYPE_FLAGS (ntype) &=  ~TYPE_FLAG_VOLATILE;
+
+  /* Fix the chain of cv variants */
+  TYPE_CV_TYPE (ntype) = type;
+  TYPE_CV_TYPE (tmp_type) = ntype;
+
+  return ntype;
+}
+
+
+
+
 /* Implement direct support for MEMBER_TYPE in GNU C++.
    May need to construct such a type if this is the first use.
    The TYPE is the type of the member.  The DOMAIN is the type
@@ -335,7 +434,10 @@ create_range_type (result_type, index_type, low_bound, high_bound)
     }
   TYPE_CODE (result_type) = TYPE_CODE_RANGE;
   TYPE_TARGET_TYPE (result_type) = index_type;
-  TYPE_LENGTH (result_type) = TYPE_LENGTH (index_type);
+  if (TYPE_FLAGS (index_type) & TYPE_FLAG_STUB)
+    TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
+  else
+    TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type));
   TYPE_NFIELDS (result_type) = 2;
   TYPE_FIELDS (result_type) = (struct field *)
     TYPE_ALLOC (result_type, 2 * sizeof (struct field));
@@ -345,9 +447,82 @@ create_range_type (result_type, index_type, low_bound, high_bound)
   TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int;         /* FIXME */
   TYPE_FIELD_TYPE (result_type, 1) = builtin_type_int;         /* FIXME */
 
+  if(low_bound >= 0)
+    TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
+
   return (result_type);
 }
 
+/* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type TYPE.
+   Return 1 of type is a range type, 0 if it is discrete (and bounds
+   will fit in LONGEST), or -1 otherwise. */
+
+int
+get_discrete_bounds (type, lowp, highp)
+     struct type *type;
+     LONGEST *lowp, *highp;
+{
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_RANGE:
+      *lowp = TYPE_LOW_BOUND (type);
+      *highp = TYPE_HIGH_BOUND (type);
+      return 1;
+    case TYPE_CODE_ENUM:
+      if (TYPE_NFIELDS (type) > 0)
+       {
+         /* The enums may not be sorted by value, so search all
+            entries */
+         int i;
+
+         *lowp = *highp = TYPE_FIELD_BITPOS (type, 0);
+         for (i = 0; i < TYPE_NFIELDS (type); i++)
+           {
+             if (TYPE_FIELD_BITPOS (type, i) < *lowp)
+               *lowp = TYPE_FIELD_BITPOS (type, i);
+             if (TYPE_FIELD_BITPOS (type, i) > *highp)
+               *highp = TYPE_FIELD_BITPOS (type, i);
+           }
+
+         /* Set unsigned indicator if warranted. */
+         if(*lowp >= 0)
+           {
+             TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+           }
+       }
+      else
+       {
+         *lowp = 0;
+         *highp = -1;
+       }
+      return 0;
+    case TYPE_CODE_BOOL:
+      *lowp = 0;
+      *highp = 1;
+      return 0;
+    case TYPE_CODE_INT:
+      if (TYPE_LENGTH (type) > sizeof (LONGEST))  /* Too big */
+       return -1;
+      if (!TYPE_UNSIGNED (type))
+       {
+         *lowp = - (1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1));
+         *highp = -*lowp - 1;
+         return 0;
+       }
+      /* ... fall through for unsigned ints ... */
+    case TYPE_CODE_CHAR:
+      *lowp = 0;
+      /* This round-about calculation is to avoid shifting by
+        TYPE_LENGTH (type) * TARGET_CHAR_BIT, which will not work
+        if TYPE_LENGTH (type) == sizeof (LONGEST). */
+      *highp = 1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1);
+      *highp = (*highp - 1) | *highp;
+      return 0;
+    default:
+      return -1;
+    }
+}
 
 /* Create an array type using either a blank type supplied in RESULT_TYPE,
    or creating a new type, inheriting the objfile from RANGE_TYPE.
@@ -364,26 +539,17 @@ create_array_type (result_type, element_type, range_type)
      struct type *element_type;
      struct type *range_type;
 {
-  int low_bound;
-  int high_bound;
+  LONGEST low_bound, high_bound;
 
-  if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
-    {
-      /* FIXME:  We only handle range types at the moment.  Complain and
-        create a dummy range type to use. */
-      warning ("internal error:  array index type must be a range type");
-      range_type = lookup_fundamental_type (TYPE_OBJFILE (range_type),
-                                           FT_INTEGER);
-      range_type = create_range_type ((struct type *) NULL, range_type, 0, 0);
-    }
   if (result_type == NULL)
     {
       result_type = alloc_type (TYPE_OBJFILE (range_type));
     }
   TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
   TYPE_TARGET_TYPE (result_type) = element_type;
-  low_bound = TYPE_FIELD_BITPOS (range_type, 0);
-  high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+    low_bound = high_bound = 0;
+  CHECK_TYPEDEF (element_type);
   TYPE_LENGTH (result_type) =
     TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
   TYPE_NFIELDS (result_type) = 1;
@@ -393,6 +559,10 @@ create_array_type (result_type, element_type, range_type)
   TYPE_FIELD_TYPE (result_type, 0) = range_type;
   TYPE_VPTR_FIELDNO (result_type) = -1;
 
+  /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */
+  if (TYPE_LENGTH (result_type) == 0)
+    TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
+
   return (result_type);
 }
 
@@ -412,11 +582,45 @@ create_string_type (result_type, range_type)
      struct type *result_type;
      struct type *range_type;
 {
-  result_type = create_array_type (result_type, builtin_type_char, range_type);
+  result_type = create_array_type (result_type,
+                                  *current_language->string_char_type,
+                                  range_type);
   TYPE_CODE (result_type) = TYPE_CODE_STRING;
   return (result_type);
 }
 
+struct type *
+create_set_type (result_type, domain_type)
+     struct type *result_type;
+     struct type *domain_type;
+{
+  LONGEST low_bound, high_bound, bit_length;
+  if (result_type == NULL)
+    {
+      result_type = alloc_type (TYPE_OBJFILE (domain_type));
+    }
+  TYPE_CODE (result_type) = TYPE_CODE_SET;
+  TYPE_NFIELDS (result_type) = 1;
+  TYPE_FIELDS (result_type) = (struct field *)
+    TYPE_ALLOC (result_type, 1 * sizeof (struct field));
+  memset (TYPE_FIELDS (result_type), 0, sizeof (struct field));
+
+  if (! (TYPE_FLAGS (domain_type) & TYPE_FLAG_STUB))
+    {
+      if (get_discrete_bounds (domain_type, &low_bound, &high_bound) < 0)
+       low_bound = high_bound = 0;
+      bit_length = high_bound - low_bound + 1;
+      TYPE_LENGTH (result_type)
+       = (bit_length + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
+    }
+  TYPE_FIELD_TYPE (result_type, 0) = domain_type;
+
+  if(low_bound >= 0)
+    TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
+
+  return (result_type);
+}
+
 /* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. 
    A MEMBER is a wierd thing -- it amounts to a typed offset into
    a struct, e.g. "an int at offset 8".  A MEMBER TYPE doesn't
@@ -600,21 +804,31 @@ lookup_union (name, block)
      struct block *block;
 {
   register struct symbol *sym;
+  struct type * t;
 
   sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
                       (struct symtab **) NULL);
 
   if (sym == NULL)
-    {
-      error ("No union type named %s.", name);
-    }
-  if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
-    {
-      error ("This context has class, struct or enum %s, not a union.", name);
-    }
-  return (SYMBOL_TYPE (sym));
+    error ("No union type named %s.", name);
+
+  t = SYMBOL_TYPE(sym);
+
+  if (TYPE_CODE (t) == TYPE_CODE_UNION)
+    return (t);
+
+  /* C++ unions may come out with TYPE_CODE_CLASS, but we look at
+   * a further "declared_type" field to discover it is really a union.
+   */
+  if (HAVE_CPLUS_STRUCT (t)) 
+    if (TYPE_DECLARED_TYPE(t) == DECLARED_TYPE_UNION) 
+      return (t);
+
+  /* If we get here, it's not a union */
+  error ("This context has class, struct or enum %s, not a union.", name);
 }
 
+
 /* Lookup an enum type named "enum NAME",
    visible in lexical block BLOCK.  */
 
@@ -685,9 +899,14 @@ lookup_struct_elt_type (type, name, noerr)
 {
   int i;
 
-  if (TYPE_CODE (type) == TYPE_CODE_PTR ||
-      TYPE_CODE (type) == TYPE_CODE_REF)
+  for (;;)
+    {
+      CHECK_TYPEDEF (type);
+      if (TYPE_CODE (type) != TYPE_CODE_PTR
+         && TYPE_CODE (type) != TYPE_CODE_REF)
+       break;
       type = TYPE_TARGET_TYPE (type);
+    }
 
   if (TYPE_CODE (type) != TYPE_CODE_STRUCT &&
       TYPE_CODE (type) != TYPE_CODE_UNION)
@@ -699,8 +918,6 @@ lookup_struct_elt_type (type, name, noerr)
       error (" is not a structure or union type.");
     }
 
-  check_stub_type (type);
-
 #if 0
   /* FIXME:  This change put in by Michael seems incorrect for the case where
      the structure tag name is the same as the member name.  I.E. when doing
@@ -763,7 +980,7 @@ void
 fill_in_vptr_fieldno (type)
      struct type *type;
 {
-  check_stub_type (type);
+  CHECK_TYPEDEF (type);
 
   if (TYPE_VPTR_FIELDNO (type) < 0)
     {
@@ -786,26 +1003,110 @@ fill_in_vptr_fieldno (type)
     }
 }
 
+/* Find the method and field indices for the destructor in class type T.
+   Return 1 if the destructor was found, otherwise, return 0.  */
+
+int
+get_destructor_fn_field (t, method_indexp, field_indexp)
+     struct type *t;
+     int *method_indexp;
+     int *field_indexp;
+{
+  int i;
+
+  for (i = 0; i < TYPE_NFN_FIELDS (t); i++)
+    {
+      int j;
+      struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
+
+      for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (t, i); j++)
+       {
+         if (DESTRUCTOR_PREFIX_P (TYPE_FN_FIELD_PHYSNAME (f, j)))
+           {
+             *method_indexp = i;
+             *field_indexp = j;
+             return 1;
+           }
+       }
+    }
+  return 0;
+}
+
 /* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
 
    If this is a stubbed struct (i.e. declared as struct foo *), see if
    we can find a full definition in some other file. If so, copy this
-   definition, so we can use it in future.  If not, set a flag so we 
-   don't waste too much time in future.  (FIXME, this doesn't seem
-   to be happening...)
+   definition, so we can use it in future.  There used to be a comment (but
+   not any code) that if we don't find a full definition, we'd set a flag
+   so we don't spend time in the future checking the same type.  That would
+   be a mistake, though--we might load in more symbols which contain a
+   full definition for the type.
 
    This used to be coded as a macro, but I don't think it is called 
-   often enough to merit such treatment.
-*/
+   often enough to merit such treatment.  */
 
 struct complaint stub_noname_complaint =
   {"stub type has NULL name", 0, 0};
 
-void 
-check_stub_type (type)
-     struct type *type;
+struct type *
+check_typedef (type)
+     register struct type *type;
 {
-  if (TYPE_FLAGS(type) & TYPE_FLAG_STUB)
+  struct type *orig_type = type;
+  while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    {
+      if (!TYPE_TARGET_TYPE (type))
+       {
+         char* name;
+         struct symbol *sym;
+
+         /* It is dangerous to call lookup_symbol if we are currently
+            reading a symtab.  Infinite recursion is one danger. */
+         if (currently_reading_symtab)
+           return type;
+
+         name = type_name_no_tag (type);
+         /* FIXME: shouldn't we separately check the TYPE_NAME and the
+            TYPE_TAG_NAME, and look in STRUCT_NAMESPACE and/or VAR_NAMESPACE
+            as appropriate?  (this code was written before TYPE_NAME and
+            TYPE_TAG_NAME were separate).  */
+         if (name == NULL)
+           {
+             complain (&stub_noname_complaint);
+             return type;
+           }
+         sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, 
+                              (struct symtab **) NULL);
+         if (sym)
+           TYPE_TARGET_TYPE (type) = SYMBOL_TYPE (sym);
+         else
+           TYPE_TARGET_TYPE (type) = alloc_type (NULL);  /* TYPE_CODE_UNDEF */
+       }
+      type = TYPE_TARGET_TYPE (type);
+    }
+
+  /* If this is a struct/class/union with no fields, then check whether a
+     full definition exists somewhere else.  This is for systems where a
+     type definition with no fields is issued for such types, instead of
+     identifying them as stub types in the first place */ 
+     
+  if (TYPE_IS_OPAQUE (type) && opaque_type_resolution && !currently_reading_symtab)
+    {
+      char * name = type_name_no_tag (type);
+      struct type * newtype;
+      if (name == NULL)
+       {
+         complain (&stub_noname_complaint);
+         return type;
+       }
+      newtype = lookup_transparent_type (name);
+      if (newtype)
+       {
+         memcpy ((char *) type, (char *) newtype, sizeof (struct type));
+       }
+    }
+  /* Otherwise, rely on the stub flag being set for opaque/stubbed types */
+  else if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab)
     {
       char* name = type_name_no_tag (type);
       /* FIXME: shouldn't we separately check the TYPE_NAME and the
@@ -816,17 +1117,243 @@ check_stub_type (type)
       if (name == NULL)
        {
          complain (&stub_noname_complaint);
-         return;
+         return type;
        }
-      sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, 
-                          (struct symtab **) NULL);
+      sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, (struct symtab **) NULL);
       if (sym)
        {
          memcpy ((char *)type, (char *)SYMBOL_TYPE(sym), sizeof (struct type));
        }
     }
+
+  if (TYPE_FLAGS (type) & TYPE_FLAG_TARGET_STUB)
+    {
+      struct type *range_type;
+      struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+      if (TYPE_FLAGS (target_type) & (TYPE_FLAG_STUB | TYPE_FLAG_TARGET_STUB))
+       { }
+      else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+              && TYPE_NFIELDS (type) == 1
+              && (TYPE_CODE (range_type = TYPE_FIELD_TYPE (type, 0))
+                  == TYPE_CODE_RANGE))
+       {
+         /* Now recompute the length of the array type, based on its
+            number of elements and the target type's length.  */
+         TYPE_LENGTH (type) =
+           ((TYPE_FIELD_BITPOS (range_type, 1)
+             - TYPE_FIELD_BITPOS (range_type, 0)
+             + 1)
+            * TYPE_LENGTH (target_type));
+         TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
+       }
+      else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+       {
+         TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
+         TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
+       }
+    }
+  /* Cache TYPE_LENGTH for future use. */
+  TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
+  return type;
 }
 
+/* New code added to support parsing of Cfront stabs strings */
+#include <ctype.h>
+#define INIT_EXTRA { pextras->len=0; pextras->str[0]='\0'; }
+#define ADD_EXTRA(c) { pextras->str[pextras->len++]=c; }
+
+static void 
+add_name(pextras,n) 
+  struct extra * pextras;
+  char * n; 
+{
+  int nlen;
+
+  if ((nlen = (n ? strlen(n) : 0))==0) 
+    return;
+  sprintf(pextras->str+pextras->len,"%d%s",nlen,n);
+  pextras->len=strlen(pextras->str);
+}
+
+static void 
+add_mangled_type(pextras,t) 
+  struct extra * pextras;
+  struct type * t;
+{
+  enum type_code tcode;
+  int tlen, tflags;
+  char * tname;
+
+  tcode = TYPE_CODE(t);
+  tlen = TYPE_LENGTH(t);
+  tflags = TYPE_FLAGS(t);
+  tname = TYPE_NAME(t);
+  /* args of "..." seem to get mangled as "e" */
+
+  switch (tcode) 
+    {
+      case TYPE_CODE_INT: 
+        if (tflags==1)
+          ADD_EXTRA('U');
+        switch (tlen) 
+          {
+            case 1:
+              ADD_EXTRA('c');
+              break;
+            case 2:
+              ADD_EXTRA('s');
+              break;
+            case 4: 
+              {
+              char* pname;
+              if ((pname=strrchr(tname,'l'),pname) && !strcmp(pname,"long"))
+                ADD_EXTRA('l')
+              else
+                ADD_EXTRA('i')
+              }
+              break;
+            default: 
+              {
+          
+                static struct complaint msg = {"Bad int type code length x%x\n",0,0};
+          
+                complain (&msg, tlen);
+          
+              }
+          }
+        break;
+      case TYPE_CODE_FLT: 
+          switch (tlen) 
+            {
+              case 4:
+                ADD_EXTRA('f');
+                break;
+              case 8:
+                ADD_EXTRA('d');
+                break;
+              case 16:
+                ADD_EXTRA('r');
+                break;
+              default: 
+               {
+                  static struct complaint msg = {"Bad float type code length x%x\n",0,0};
+                 complain (&msg, tlen);
+               }
+             }
+            break;
+      case TYPE_CODE_REF:
+        ADD_EXTRA('R');
+        /* followed by what it's a ref to */
+        break;
+      case TYPE_CODE_PTR:
+        ADD_EXTRA('P');
+        /* followed by what it's a ptr to */
+        break;
+      case TYPE_CODE_TYPEDEF: 
+        {
+          static struct complaint msg = {"Typedefs in overloaded functions not yet supported\n",0,0};
+          complain (&msg);
+        }
+      /* followed by type bytes & name */
+      break;
+    case TYPE_CODE_FUNC:
+      ADD_EXTRA('F');
+      /* followed by func's arg '_' & ret types */
+      break;
+    case TYPE_CODE_VOID:
+      ADD_EXTRA('v');
+      break;
+    case TYPE_CODE_METHOD:
+      ADD_EXTRA('M');
+      /* followed by name of class and func's arg '_' & ret types */
+      add_name(pextras,tname);
+      ADD_EXTRA('F');  /* then mangle function */
+      break;
+    case TYPE_CODE_STRUCT: /* C struct */
+    case TYPE_CODE_UNION:  /* C union */
+    case TYPE_CODE_ENUM:   /* Enumeration type */
+      /* followed by name of type */
+      add_name(pextras,tname);
+      break;
+
+    /* errors possible types/not supported */
+    case TYPE_CODE_CHAR:              
+    case TYPE_CODE_ARRAY:  /* Array type */
+    case TYPE_CODE_MEMBER: /* Member type */
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_COMPLEX:            /* Complex float */
+    case TYPE_CODE_UNDEF:
+    case TYPE_CODE_SET:                /* Pascal sets */
+    case TYPE_CODE_RANGE:  
+    case TYPE_CODE_STRING:
+    case TYPE_CODE_BITSTRING:
+    case TYPE_CODE_ERROR:
+    default: 
+      {
+        static struct complaint msg = {"Unknown type code x%x\n",0,0};
+        complain (&msg, tcode);
+      }
+    }
+  if (t->target_type)
+    add_mangled_type(pextras,t->target_type);
+}
+
+#if 0
+void
+cfront_mangle_name(type, i, j)
+     struct type *type;
+     int i;
+     int j;
+{
+   struct fn_field *f;
+   char *mangled_name = gdb_mangle_name (type, i, j);
+
+   f = TYPE_FN_FIELDLIST1 (type, i);   /* moved from below */
+
+   /* kludge to support cfront methods - gdb expects to find "F" for 
+      ARM_mangled names, so when we mangle, we have to add it here */
+   if (ARM_DEMANGLING) 
+     {
+       int k;
+       char * arm_mangled_name;
+       struct fn_field *method = &f[j];
+       char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
+        char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
+        char *newname = type_name_no_tag (type);
+
+        struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
+       int nargs = TYPE_NFIELDS(ftype);        /* number of args */
+       struct extra extras, * pextras = &extras;       
+       INIT_EXTRA
+
+       if (TYPE_FN_FIELD_STATIC_P (f, j))      /* j for sublist within this list */
+         ADD_EXTRA('S')
+       ADD_EXTRA('F')
+       /* add args here! */
+       if (nargs <= 1)                         /* no args besides this */
+               ADD_EXTRA('v')
+       else {
+         for (k=1; k<nargs; k++) 
+           {
+             struct type * t;
+             t = TYPE_FIELD_TYPE(ftype,k);
+             add_mangled_type(pextras,t);
+           }
+       }
+       ADD_EXTRA('\0')
+       printf("add_mangled_type: %s\n",extras.str); /* FIXME */
+       arm_mangled_name = malloc(strlen(mangled_name)+extras.len);
+        sprintf(arm_mangled_name,"%s%s",mangled_name,extras.str);
+       free(mangled_name);
+       mangled_name = arm_mangled_name;
+     }
+}
+#endif /* 0 */
+
+#undef ADD_EXTRA
+/* End of new code added to support parsing of Cfront stabs strings */
+
 /* Ugly hack to convert method stubs into method types.
 
    He ain't kiddin'.  This demangles the name of the method into a string
@@ -838,13 +1365,13 @@ check_stub_type (type)
    the space required for them.  */
 
 void
-check_stub_method (type, i, j)
+check_stub_method (type, method_id, signature_id)
      struct type *type;
-     int i;
-     int j;
+     int method_id;
+     int signature_id;
 {
   struct fn_field *f;
-  char *mangled_name = gdb_mangle_name (type, i, j);
+  char *mangled_name = gdb_mangle_name (type, method_id, signature_id);
   char *demangled_name = cplus_demangle (mangled_name,
                                         DMGL_PARAMS | DMGL_ANSI);
   char *argtypetext, *p;
@@ -852,14 +1379,16 @@ check_stub_method (type, i, j)
   struct type **argtypes;
   struct type *mtype;
 
-  if (demangled_name == NULL)
-    {
-      error ("Internal: Cannot demangle mangled name `%s'.", mangled_name);
-    }
+  /* Make sure we got back a function string that we can use.  */
+  if (demangled_name)
+    p = strchr (demangled_name, '(');
+
+  if (demangled_name == NULL || p == NULL)
+    error ("Internal: Cannot demangle mangled name `%s'.", mangled_name);
 
   /* Now, read in the parameters that define this type.  */
-  argtypetext = strchr (demangled_name, '(') + 1;
-  p = argtypetext;
+  p += 1;
+  argtypetext = p;
   while (*p)
     {
       if (*p == '(')
@@ -884,6 +1413,7 @@ check_stub_method (type, i, j)
   argtypes = (struct type **)
     TYPE_ALLOC (type, (argcount + 2) * sizeof (struct type *));
   p = argtypetext;
+  /* FIXME: This is wrong for static member functions.  */
   argtypes[0] = lookup_pointer_type (type);
   argcount = 1;
 
@@ -894,9 +1424,13 @@ check_stub_method (type, i, j)
        {
          if (depth <= 0 && (*p == ',' || *p == ')'))
            {
-             argtypes[argcount] =
-                 parse_and_eval_type (argtypetext, p - argtypetext);
-             argcount += 1;
+             /* Avoid parsing of ellipsis, they will be handled below.  */
+             if (strncmp (argtypetext, "...", p - argtypetext) != 0)
+               {
+                 argtypes[argcount] =
+                     parse_and_eval_type (argtypetext, p - argtypetext);
+                 argcount += 1;
+               }
              argtypetext = p + 1;
            }
 
@@ -924,15 +1458,16 @@ check_stub_method (type, i, j)
 
   free (demangled_name);
 
-  f = TYPE_FN_FIELDLIST1 (type, i);
-  TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
+  f = TYPE_FN_FIELDLIST1 (type, method_id);    
+
+  TYPE_FN_FIELD_PHYSNAME (f, signature_id) = mangled_name;
 
   /* Now update the old "stub" type into a real type.  */
-  mtype = TYPE_FN_FIELD_TYPE (f, j);
+  mtype = TYPE_FN_FIELD_TYPE (f, signature_id);
   TYPE_DOMAIN_TYPE (mtype) = type;
   TYPE_ARG_TYPES (mtype) = argtypes;
   TYPE_FLAGS (mtype) &= ~TYPE_FLAG_STUB;
-  TYPE_FN_FIELD_STUB (f, j) = 0;
+  TYPE_FN_FIELD_STUB (f, signature_id) = 0;
 }
 
 const struct cplus_struct_type cplus_struct_default;
@@ -1032,6 +1567,7 @@ lookup_fundamental_type (objfile, typeid)
       objfile -> fundamental_types = (struct type **)
        obstack_alloc (&objfile -> type_obstack, nbytes);
       memset ((char *) objfile -> fundamental_types, 0, nbytes);
+      OBJSTAT (objfile, n_types += FT_NUM_MEMBERS);
     }
 
   /* Look for this particular type in the fundamental type vector.  If one is
@@ -1046,6 +1582,816 @@ lookup_fundamental_type (objfile, typeid)
   return (*typep);
 }
 
+int
+can_dereference (t)
+     struct type *t;
+{
+  /* FIXME: Should we return true for references as well as pointers?  */
+  CHECK_TYPEDEF (t);
+  return
+    (t != NULL
+     && TYPE_CODE (t) == TYPE_CODE_PTR
+     && TYPE_CODE (TYPE_TARGET_TYPE (t)) != TYPE_CODE_VOID);
+}
+
+/* Chill varying string and arrays are represented as follows:
+
+   struct { int __var_length; ELEMENT_TYPE[MAX_SIZE] __var_data};
+
+   Return true if TYPE is such a Chill varying type. */
+
+int
+chill_varying_type (type)
+     struct type *type;
+{
+  if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+      || TYPE_NFIELDS (type) != 2
+      || strcmp (TYPE_FIELD_NAME (type, 0), "__var_length") != 0)
+    return 0;
+  return 1;
+}
+
+/* Check whether BASE is an ancestor or base class or DCLASS 
+   Return 1 if so, and 0 if not.
+   Note: callers may want to check for identity of the types before
+   calling this function -- identical types are considered to satisfy
+   the ancestor relationship even if they're identical */
+
+int
+is_ancestor (base, dclass)
+  struct type * base;
+  struct type * dclass;
+{
+  int i;
+  
+  CHECK_TYPEDEF (base);
+  CHECK_TYPEDEF (dclass);
+
+  if (base == dclass)
+    return 1;
+
+  for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+    if (is_ancestor (base, TYPE_BASECLASS (dclass, i)))
+      return 1;
+
+  return 0;
+}
+
+
+
+/* See whether DCLASS has a virtual table.  This routine is aimed at
+   the HP/Taligent ANSI C++ runtime model, and may not work with other
+   runtime models.  Return 1 => Yes, 0 => No.  */
+
+int
+has_vtable (dclass)
+  struct type * dclass;
+{
+  /* In the HP ANSI C++ runtime model, a class has a vtable only if it
+     has virtual functions or virtual bases.  */
+
+  register int i;
+
+  if (TYPE_CODE(dclass) != TYPE_CODE_CLASS)
+    return 0;
+  
+  /* First check for the presence of virtual bases */
+  if (TYPE_FIELD_VIRTUAL_BITS(dclass))
+    for (i=0; i < TYPE_N_BASECLASSES(dclass); i++)
+      if (B_TST(TYPE_FIELD_VIRTUAL_BITS(dclass), i))
+        return 1;
+  
+  /* Next check for virtual functions */
+  if (TYPE_FN_FIELDLISTS(dclass))
+    for (i=0; i < TYPE_NFN_FIELDS(dclass); i++)
+      if (TYPE_FN_FIELD_VIRTUAL_P(TYPE_FN_FIELDLIST1(dclass, i), 0))
+        return 1;
+
+  /* Recurse on non-virtual bases to see if any of them needs a vtable */ 
+  if (TYPE_FIELD_VIRTUAL_BITS(dclass))
+    for (i=0; i < TYPE_N_BASECLASSES(dclass); i++)
+      if ((!B_TST (TYPE_FIELD_VIRTUAL_BITS(dclass), i)) &&
+         (has_vtable (TYPE_FIELD_TYPE(dclass, i))))
+       return 1;
+  
+  /* Well, maybe we don't need a virtual table */ 
+  return 0;
+}
+
+/* Return a pointer to the "primary base class" of DCLASS.
+   A NULL return indicates that DCLASS has no primary base, or that it
+   couldn't be found (insufficient information).
+  
+   This routine is aimed at the HP/Taligent ANSI C++ runtime model,
+   and may not work with other runtime models.  */
+
+struct type *
+primary_base_class (dclass)
+  struct type * dclass;
+{
+  /* In HP ANSI C++'s runtime model, a "primary base class" of a class
+     is the first directly inherited, non-virtual base class that
+     requires a virtual table */
+
+  register int i;
+
+  if (TYPE_CODE(dclass) != TYPE_CODE_CLASS)
+    return NULL;
+
+  for (i=0; i < TYPE_N_BASECLASSES(dclass); i++)
+    if (!TYPE_FIELD_VIRTUAL(dclass, i) &&
+        has_vtable(TYPE_FIELD_TYPE(dclass, i)))
+      return TYPE_FIELD_TYPE(dclass, i);
+
+  return NULL;
+}
+
+/* Global manipulated by virtual_base_list[_aux]() */
+
+static struct vbase * current_vbase_list = NULL;
+
+/* Return a pointer to a null-terminated list of struct vbase
+   items. The vbasetype pointer of each item in the list points to the
+   type information for a virtual base of the argument DCLASS.
+  
+   Helper function for virtual_base_list(). 
+   Note: the list goes backward, right-to-left. virtual_base_list()
+   copies the items out in reverse order.  */
+
+struct vbase *
+virtual_base_list_aux (dclass)
+  struct type * dclass;
+{
+  struct vbase * tmp_vbase;
+  register int i;
+
+  if (TYPE_CODE(dclass) != TYPE_CODE_CLASS)
+    return NULL;
+
+  for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+    {
+      /* Recurse on this ancestor, first */
+      virtual_base_list_aux(TYPE_FIELD_TYPE(dclass, i));
+
+      /* If this current base is itself virtual, add it to the list */
+      if (BASETYPE_VIA_VIRTUAL(dclass, i))
+        {
+          struct type * basetype = TYPE_FIELD_TYPE (dclass, i);
+          
+          /* Check if base already recorded */
+          tmp_vbase = current_vbase_list;
+          while (tmp_vbase)
+            {
+              if (tmp_vbase->vbasetype == basetype)
+                break; /* found it */
+              tmp_vbase = tmp_vbase->next;
+            }
+
+          if (!tmp_vbase) /* normal exit from loop */
+            {
+              /* Allocate new item for this virtual base */
+              tmp_vbase = (struct vbase *) xmalloc (sizeof (struct vbase));
+
+              /* Stick it on at the end of the list */
+              tmp_vbase->vbasetype = basetype;
+              tmp_vbase->next = current_vbase_list;
+              current_vbase_list = tmp_vbase;
+            }
+        } /* if virtual */
+    } /* for loop over bases */
+}
+
+
+/* Compute the list of virtual bases in the right order.  Virtual
+   bases are laid out in the object's memory area in order of their
+   occurrence in a depth-first, left-to-right search through the
+   ancestors.
+  
+   Argument DCLASS is the type whose virtual bases are required.
+   Return value is the address of a null-terminated array of pointers
+   to struct type items.
+   
+   This routine is aimed at the HP/Taligent ANSI C++ runtime model,
+   and may not work with other runtime models.
+  
+   This routine merely hands off the argument to virtual_base_list_aux()
+   and then copies the result into an array to save space.  */
+
+struct type **
+virtual_base_list (dclass)
+  struct type * dclass;
+{
+  register struct vbase * tmp_vbase;
+  register struct vbase * tmp_vbase_2;
+  register int i;
+  int count;
+  struct type ** vbase_array;
+
+  current_vbase_list = NULL;
+  virtual_base_list_aux(dclass);
+
+  for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next)
+    /* no body */ ;
+
+  count = i;
+
+  vbase_array = (struct type **) xmalloc((count + 1) * sizeof (struct type *));
+
+  for (i=count -1, tmp_vbase = current_vbase_list; i >= 0; i--, tmp_vbase = tmp_vbase->next)
+    vbase_array[i] = tmp_vbase->vbasetype;
+
+  /* Get rid of constructed chain */
+  tmp_vbase_2 = tmp_vbase = current_vbase_list;
+  while (tmp_vbase)
+    {
+      tmp_vbase = tmp_vbase->next;
+      free(tmp_vbase_2);
+      tmp_vbase_2 = tmp_vbase;
+    }
+  
+  vbase_array[count] = NULL;
+  return vbase_array;
+}
+
+/* Return the length of the virtual base list of the type DCLASS.  */
+
+int
+virtual_base_list_length (dclass)
+  struct type * dclass;
+{
+  register int i;
+  register struct vbase * tmp_vbase;
+  
+  current_vbase_list = NULL;
+  virtual_base_list_aux(dclass);
+
+  for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next)
+    /* no body */ ;
+  return i;
+}
+
+/* Return the number of elements of the virtual base list of the type
+   DCLASS, ignoring those appearing in the primary base (and its
+   primary base, recursively).  */
+
+int
+virtual_base_list_length_skip_primaries (dclass)
+  struct type * dclass;
+{
+  register int i;
+  register struct vbase * tmp_vbase;
+  struct type * primary;
+
+  primary = TYPE_RUNTIME_PTR (dclass) ? TYPE_PRIMARY_BASE (dclass) : NULL;
+
+  if (!primary)
+    return virtual_base_list_length (dclass);
+
+  current_vbase_list = NULL;
+  virtual_base_list_aux(dclass);
+
+  for (i=0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; tmp_vbase = tmp_vbase->next)
+    {
+      if (virtual_base_index (tmp_vbase->vbasetype, primary) >= 0)
+        continue;
+      i++;
+    }
+  return i;
+}
+
+
+/* Return the index (position) of type BASE, which is a virtual base
+   class of DCLASS, in the latter's virtual base list.  A return of -1
+   indicates "not found" or a problem.  */
+
+int
+virtual_base_index(base, dclass)
+  struct type * base;
+  struct type * dclass;
+{
+  register struct type * vbase;
+  register int i;
+
+  if ((TYPE_CODE(dclass) != TYPE_CODE_CLASS) ||
+      (TYPE_CODE(base) != TYPE_CODE_CLASS))
+    return -1;
+
+  i = 0;
+  vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[0];
+  while (vbase)
+    {
+      if (vbase == base)
+        break;
+      vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[++i];
+    }
+
+  return vbase ? i : -1;
+}
+
+
+
+/* Return the index (position) of type BASE, which is a virtual base
+   class of DCLASS, in the latter's virtual base list. Skip over all
+   bases that may appear in the virtual base list of the primary base
+   class of DCLASS (recursively).  A return of -1 indicates "not
+   found" or a problem.  */
+
+int
+virtual_base_index_skip_primaries(base, dclass)
+  struct type * base;
+  struct type * dclass;
+{
+  register struct type * vbase;
+  register int i, j;
+  struct type * primary;
+
+  if ((TYPE_CODE(dclass) != TYPE_CODE_CLASS) ||
+      (TYPE_CODE(base) != TYPE_CODE_CLASS))
+    return -1;
+
+  primary = TYPE_RUNTIME_PTR(dclass) ? TYPE_PRIMARY_BASE(dclass) : NULL;
+
+  j = -1;
+  i = 0;
+  vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[0];
+  while (vbase)
+    {
+      if (!primary || (virtual_base_index_skip_primaries(vbase, primary) < 0))
+        j++;
+      if (vbase == base)
+        break;
+      vbase = TYPE_VIRTUAL_BASE_LIST(dclass)[++i];
+    }
+
+  return vbase ? j : -1;
+}
+
+/* Return position of a derived class DCLASS in the list of
+ * primary bases starting with the remotest ancestor.
+ * Position returned is 0-based. */
+
+int
+class_index_in_primary_list (dclass)
+  struct type * dclass;
+{
+  struct type * pbc; /* primary base class */
+
+  /* Simply recurse on primary base */ 
+  pbc = TYPE_PRIMARY_BASE (dclass);
+  if (pbc)
+    return 1 + class_index_in_primary_list (pbc);
+  else
+    return 0;
+}
+
+/* Return a count of the number of virtual functions a type has.
+ * This includes all the virtual functions it inherits from its
+ * base classes too.
+ */
+
+/* pai: FIXME This doesn't do the right thing: count redefined virtual
+ * functions only once (latest redefinition)
+ */
+
+int
+count_virtual_fns (dclass)
+  struct type * dclass;
+{
+  int base;     /* index for base classes */
+  int fn, oi;   /* function and overloaded instance indices */
+  
+  int vfuncs;   /* count to return */ 
+
+  /* recurse on bases that can share virtual table */ 
+  struct type * pbc = primary_base_class (dclass);
+  if (pbc)
+    vfuncs = count_virtual_fns (pbc);
+  
+  for (fn = 0; fn < TYPE_NFN_FIELDS (dclass); fn++)
+    for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (dclass, fn); oi++)
+      if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (dclass, fn), oi))
+        vfuncs++;
+
+  return vfuncs;
+}
+
+\f
+
+/* Functions for overload resolution begin here */
+
+/* Compare two badness vectors A and B and return the result.
+ * 0 => A and B are identical
+ * 1 => A and B are incomparable
+ * 2 => A is better than B
+ * 3 => A is worse than B */
+
+int
+compare_badness (a, b)
+  struct badness_vector * a;
+  struct badness_vector * b;
+{
+  int i;
+  int tmp;
+  short found_pos = 0;      /* any positives in c? */
+  short found_neg = 0;      /* any negatives in c? */
+  
+  /* differing lengths => incomparable */ 
+  if (a->length != b->length)
+    return 1;
+
+  /* Subtract b from a */ 
+  for (i=0; i < a->length; i++)
+    {
+      tmp = a->rank[i] - b->rank[i];
+      if (tmp > 0)
+        found_pos = 1;
+      else if (tmp < 0)
+        found_neg = 1;
+    }
+
+  if (found_pos)
+    {
+      if (found_neg)
+        return 1; /* incomparable */ 
+      else
+        return 3; /* A > B */ 
+    }
+  else /* no positives */ 
+    {
+      if (found_neg)
+        return 2; /* A < B */
+      else
+        return 0; /* A == B */
+    }
+}
+
+/* Rank a function by comparing its parameter types (PARMS, length NPARMS),
+ * to the types of an argument list (ARGS, length NARGS).
+ * Return a pointer to a badness vector. This has NARGS + 1 entries. */
+
+struct badness_vector *
+rank_function (parms, nparms, args, nargs)
+  struct type ** parms;
+  int nparms;
+  struct type ** args;
+  int nargs;
+{
+  int i;
+  struct badness_vector * bv;
+  int min_len = nparms < nargs ? nparms : nargs;
+
+  bv = xmalloc (sizeof (struct badness_vector));
+  bv->length = nargs + 1; /* add 1 for the length-match rank */ 
+  bv->rank = xmalloc ((nargs + 1) * sizeof (int));
+
+  /* First compare the lengths of the supplied lists.
+   * If there is a mismatch, set it to a high value. */
+   
+  /* pai/1997-06-03 FIXME: when we have debug info about default
+   * arguments and ellipsis parameter lists, we should consider those
+   * and rank the length-match more finely. */
+
+  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]);
+
+  /* If more arguments than parameters, add dummy entries */ 
+  for (i = min_len +1; i <= nargs; i++)
+    bv->rank[i] = TOO_FEW_PARAMS_BADNESS;
+
+  return bv;
+}
+
+/* Compare one type (PARM) for compatibility with another (ARG).
+ * PARM is intended to be the parameter type of a function; and
+ * ARG is the supplied argument's type.  This function tests if
+ * the latter can be converted to the former.
+ *
+ * Return 0 if they are identical types;
+ * Otherwise, return an integer which corresponds to how compatible
+ * PARM is to ARG. The higher the return value, the worse the match.
+ * Generally the "bad" conversions are all uniformly assigned a 100 */
+
+int
+rank_one_type (parm, arg)
+  struct type * parm;
+  struct type * arg;
+{
+  /* Identical type pointers */
+  /* However, this still doesn't catch all cases of same type for arg
+   * and param. The reason is that builtin types are different from
+   * the same ones constructed from the object. */
+  if (parm == arg)
+    return 0;
+
+  /* Resolve typedefs */
+  if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
+    parm = check_typedef (parm);
+  if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
+    arg = check_typedef (arg);
+
+  /* Check if identical after resolving typedefs */
+  if (parm == arg)
+    return 0;
+
+#if 0
+  /* Debugging only */ 
+  printf("------ Arg is %s [%d], parm is %s [%d]\n",
+         TYPE_NAME (arg), TYPE_CODE (arg), TYPE_NAME (parm), TYPE_CODE (parm));
+#endif
+
+  /* x -> y means arg of type x being supplied for parameter of type y */
+
+  switch (TYPE_CODE (parm))
+    {
+      case TYPE_CODE_PTR:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_PTR: 
+              if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID)
+                return VOID_PTR_CONVERSION_BADNESS;
+              else
+                return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg));
+            case TYPE_CODE_ARRAY:
+              return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg));
+            case TYPE_CODE_FUNC:
+              return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
+            case TYPE_CODE_INT:
+            case TYPE_CODE_ENUM:
+            case TYPE_CODE_CHAR:
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_BOOL:
+              return POINTER_CONVERSION_BADNESS;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+      case TYPE_CODE_ARRAY:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_PTR:
+            case TYPE_CODE_ARRAY:
+              return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg));
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+      case TYPE_CODE_FUNC:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_PTR: /* funcptr -> func */
+              return rank_one_type (parm, TYPE_TARGET_TYPE (arg));
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+      case TYPE_CODE_INT:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_INT:
+              if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
+                {
+                  /* Deal with signed, unsigned, and plain chars and
+                     signed and unsigned ints */
+                  if (TYPE_NOSIGN (parm))
+                    {
+                      /* This case only for character types */
+                      if (TYPE_NOSIGN (arg))  /* plain char -> plain char */
+                        return 0;
+                      else
+                        return INTEGER_COERCION_BADNESS; /* signed/unsigned char -> plain char */
+                    }
+                  else if (TYPE_UNSIGNED (parm))
+                    {
+                      if (TYPE_UNSIGNED (arg))
+                        {
+                          if (!strcmp (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"))
+                            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"))
+                            return INTEGER_COERCION_BADNESS; /* signed long -> unsigned int */
+                          else 
+                            return INTEGER_CONVERSION_BADNESS; /* signed int/long -> unsigned int/long */ 
+                        }
+                    }
+                  else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
+                    {
+                      if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg)))
+                        return 0;
+                      else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long"))
+                        return INTEGER_PROMOTION_BADNESS;
+                      else
+                        return INTEGER_COERCION_BADNESS;
+                    }
+                  else
+                    return INTEGER_COERCION_BADNESS;
+                }
+              else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+                return INTEGER_PROMOTION_BADNESS;
+              else
+                return INTEGER_COERCION_BADNESS;
+            case TYPE_CODE_ENUM:
+            case TYPE_CODE_CHAR:
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_BOOL:
+              return INTEGER_PROMOTION_BADNESS;
+            case TYPE_CODE_FLT:
+              return INT_FLOAT_CONVERSION_BADNESS;
+            case TYPE_CODE_PTR:
+              return NS_POINTER_CONVERSION_BADNESS;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_ENUM:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_INT:
+            case TYPE_CODE_CHAR:
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_BOOL:
+            case TYPE_CODE_ENUM:
+              return INTEGER_COERCION_BADNESS;
+            case TYPE_CODE_FLT:
+              return INT_FLOAT_CONVERSION_BADNESS;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_CHAR:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_BOOL:
+            case TYPE_CODE_ENUM:
+              return INTEGER_COERCION_BADNESS;
+            case TYPE_CODE_FLT:
+              return INT_FLOAT_CONVERSION_BADNESS;
+            case TYPE_CODE_INT: 
+              if (TYPE_LENGTH (arg) > TYPE_LENGTH (parm))
+                return INTEGER_COERCION_BADNESS;
+              else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+                return INTEGER_PROMOTION_BADNESS;
+              /* >>> !! else fall through !! <<< */ 
+            case TYPE_CODE_CHAR:
+              /* Deal with signed, unsigned, and plain chars for C++
+                 and with int cases falling through from previous case */
+              if (TYPE_NOSIGN (parm))
+                {
+                  if (TYPE_NOSIGN (arg))
+                    return 0;
+                  else
+                    return INTEGER_COERCION_BADNESS;
+                }
+              else if (TYPE_UNSIGNED (parm))
+                {
+                  if (TYPE_UNSIGNED (arg))
+                    return 0;
+                  else
+                    return INTEGER_PROMOTION_BADNESS;
+                }
+              else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
+                return 0;
+              else
+                return INTEGER_COERCION_BADNESS;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_RANGE:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_INT:
+            case TYPE_CODE_CHAR:
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_BOOL:
+            case TYPE_CODE_ENUM:
+              return INTEGER_COERCION_BADNESS;
+            case TYPE_CODE_FLT:
+              return INT_FLOAT_CONVERSION_BADNESS;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_BOOL:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_INT:
+            case TYPE_CODE_CHAR:
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_ENUM:
+            case TYPE_CODE_FLT:
+            case TYPE_CODE_PTR:
+              return BOOLEAN_CONVERSION_BADNESS;
+            case TYPE_CODE_BOOL:
+              return 0;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_FLT:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_FLT:
+              if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+                return FLOAT_PROMOTION_BADNESS;
+              else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
+                return 0;
+              else
+                return FLOAT_CONVERSION_BADNESS;
+            case TYPE_CODE_INT:
+            case TYPE_CODE_BOOL:
+            case TYPE_CODE_ENUM:
+            case TYPE_CODE_RANGE:
+            case TYPE_CODE_CHAR:
+              return INT_FLOAT_CONVERSION_BADNESS;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_COMPLEX:
+        switch (TYPE_CODE (arg))
+          { /* Strictly not needed for C++, but... */
+            case TYPE_CODE_FLT:
+              return FLOAT_PROMOTION_BADNESS;
+            case TYPE_CODE_COMPLEX:
+              return 0;
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_STRUCT:
+      /* currently same as TYPE_CODE_CLASS */
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_STRUCT:
+              /* Check for derivation */
+              if (is_ancestor (parm, arg))
+                return BASE_CONVERSION_BADNESS;
+              /* else fall through */
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_UNION:
+        switch (TYPE_CODE (arg))
+          {
+            case TYPE_CODE_UNION:
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_MEMBER:
+        switch (TYPE_CODE (arg))
+          {
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_METHOD:
+        switch (TYPE_CODE (arg))
+          {
+            
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_REF:
+        switch (TYPE_CODE (arg))
+          {
+            
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+
+        break;
+      case TYPE_CODE_SET:
+        switch (TYPE_CODE (arg))
+          {
+            /* Not in C++ */
+            case TYPE_CODE_SET:
+              return rank_one_type (TYPE_FIELD_TYPE (parm, 0), TYPE_FIELD_TYPE (arg, 0));
+            default:
+              return INCOMPATIBLE_TYPE_BADNESS;
+          }
+        break;
+      case TYPE_CODE_VOID:
+      default:  
+        return INCOMPATIBLE_TYPE_BADNESS;
+    } /* switch (TYPE_CODE (arg)) */
+}
+
+/* End of functions for overload resolution */ 
+
+
+
 #if MAINTENANCE_CMDS
 
 static void
@@ -1105,33 +2451,46 @@ dump_fn_fieldlists (type, spaces)
   int overload_idx;
   struct fn_field *f;
 
-  printfi_filtered (spaces, "fn_fieldlists 0x%lx\n",
-                   (unsigned long) TYPE_FN_FIELDLISTS (type));
+  printfi_filtered (spaces, "fn_fieldlists ");
+  gdb_print_address (TYPE_FN_FIELDLISTS (type), gdb_stdout);
+  printf_filtered ("\n");
   for (method_idx = 0; method_idx < TYPE_NFN_FIELDS (type); method_idx++)
     {
       f = TYPE_FN_FIELDLIST1 (type, method_idx);
-      printfi_filtered (spaces + 2, "[%d] name '%s' (0x%lx) length %d\n",
+      printfi_filtered (spaces + 2, "[%d] name '%s' (",
                        method_idx,
-                       TYPE_FN_FIELDLIST_NAME (type, method_idx),
-                       (unsigned long) TYPE_FN_FIELDLIST_NAME (type, method_idx),
-                       TYPE_FN_FIELDLIST_LENGTH (type, method_idx));
+                       TYPE_FN_FIELDLIST_NAME (type, method_idx));
+      gdb_print_address (TYPE_FN_FIELDLIST_NAME (type, method_idx),
+                        gdb_stdout);
+      printf_filtered (") length %d\n",
+                      TYPE_FN_FIELDLIST_LENGTH (type, method_idx));
       for (overload_idx = 0;
           overload_idx < TYPE_FN_FIELDLIST_LENGTH (type, method_idx);
           overload_idx++)
        {
-         printfi_filtered (spaces + 4, "[%d] physname '%s' (0x%lx)\n",
+         printfi_filtered (spaces + 4, "[%d] physname '%s' (",
                            overload_idx,
-                           TYPE_FN_FIELD_PHYSNAME (f, overload_idx),
-                           (unsigned long) TYPE_FN_FIELD_PHYSNAME (f, overload_idx));
-         printfi_filtered (spaces + 8, "type 0x%lx\n",
-                           (unsigned long) TYPE_FN_FIELD_TYPE (f, overload_idx));
+                           TYPE_FN_FIELD_PHYSNAME (f, overload_idx));
+         gdb_print_address (TYPE_FN_FIELD_PHYSNAME (f, overload_idx),
+                            gdb_stdout);
+         printf_filtered (")\n");
+         printfi_filtered (spaces + 8, "type ");
+         gdb_print_address (TYPE_FN_FIELD_TYPE (f, overload_idx), gdb_stdout);
+         printf_filtered ("\n");
+
          recursive_dump_type (TYPE_FN_FIELD_TYPE (f, overload_idx),
                               spaces + 8 + 2);
-         printfi_filtered (spaces + 8, "args 0x%lx\n",
-                           (unsigned long) TYPE_FN_FIELD_ARGS (f, overload_idx));
+
+         printfi_filtered (spaces + 8, "args ");
+         gdb_print_address (TYPE_FN_FIELD_ARGS (f, overload_idx), gdb_stdout);
+         printf_filtered ("\n");
+
          print_arg_types (TYPE_FN_FIELD_ARGS (f, overload_idx), spaces);
-         printfi_filtered (spaces + 8, "fcontext 0x%lx\n",
-                           (unsigned long) TYPE_FN_FIELD_FCONTEXT (f, overload_idx));
+         printfi_filtered (spaces + 8, "fcontext ");
+         gdb_print_address (TYPE_FN_FIELD_FCONTEXT (f, overload_idx),
+                            gdb_stdout);
+         printf_filtered ("\n");
+
          printfi_filtered (spaces + 8, "is_const %d\n",
                            TYPE_FN_FIELD_CONST (f, overload_idx));
          printfi_filtered (spaces + 8, "is_volatile %d\n",
@@ -1161,9 +2520,11 @@ print_cplus_stuff (type, spaces)
                    TYPE_NFN_FIELDS_TOTAL (type));
   if (TYPE_N_BASECLASSES (type) > 0)
     {
-      printfi_filtered (spaces, "virtual_field_bits (%d bits at *0x%lx)",
-                       TYPE_N_BASECLASSES (type),
-                       (unsigned long) TYPE_FIELD_VIRTUAL_BITS (type));
+      printfi_filtered (spaces, "virtual_field_bits (%d bits at *",
+                       TYPE_N_BASECLASSES (type));
+      gdb_print_address (TYPE_FIELD_VIRTUAL_BITS (type), gdb_stdout);
+      printf_filtered (")");
+
       print_bit_vector (TYPE_FIELD_VIRTUAL_BITS (type),
                        TYPE_N_BASECLASSES (type));
       puts_filtered ("\n");
@@ -1172,18 +2533,20 @@ print_cplus_stuff (type, spaces)
     {
       if (TYPE_FIELD_PRIVATE_BITS (type) != NULL)
        {
-         printfi_filtered (spaces, "private_field_bits (%d bits at *0x%lx)",
-                           TYPE_NFIELDS (type),
-                           (unsigned long) TYPE_FIELD_PRIVATE_BITS (type));
+         printfi_filtered (spaces, "private_field_bits (%d bits at *",
+                           TYPE_NFIELDS (type));
+         gdb_print_address (TYPE_FIELD_PRIVATE_BITS (type), gdb_stdout);
+         printf_filtered (")");
          print_bit_vector (TYPE_FIELD_PRIVATE_BITS (type),
                            TYPE_NFIELDS (type));
          puts_filtered ("\n");
        }
       if (TYPE_FIELD_PROTECTED_BITS (type) != NULL)
        {
-         printfi_filtered (spaces, "protected_field_bits (%d bits at *0x%lx)",
-                           TYPE_NFIELDS (type),
-                           (unsigned long) TYPE_FIELD_PROTECTED_BITS (type));
+         printfi_filtered (spaces, "protected_field_bits (%d bits at *",
+                           TYPE_NFIELDS (type));
+         gdb_print_address (TYPE_FIELD_PROTECTED_BITS (type), gdb_stdout);
+         printf_filtered (")");
          print_bit_vector (TYPE_FIELD_PROTECTED_BITS (type),
                            TYPE_NFIELDS (type));
          puts_filtered ("\n");
@@ -1195,6 +2558,8 @@ print_cplus_stuff (type, spaces)
     }
 }
 
+static struct obstack dont_print_type_obstack;
+
 void
 recursive_dump_type (type, spaces)
      struct type *type;
@@ -1202,14 +2567,46 @@ recursive_dump_type (type, spaces)
 {
   int idx;
 
-  printfi_filtered (spaces, "type node 0x%lx\n", (unsigned long)type);
-  printfi_filtered (spaces, "name '%s' (0x%lx)\n",
-                   TYPE_NAME (type) ? TYPE_NAME (type) : "<NULL>",
-                   (unsigned long)TYPE_NAME (type));
+  if (spaces == 0)
+    obstack_begin (&dont_print_type_obstack, 0);
+
+  if (TYPE_NFIELDS (type) > 0
+      || (TYPE_CPLUS_SPECIFIC (type) && TYPE_NFN_FIELDS (type) > 0))
+    {
+      struct type **first_dont_print
+       = (struct type **)obstack_base (&dont_print_type_obstack);
+
+      int i = (struct type **)obstack_next_free (&dont_print_type_obstack)
+       - first_dont_print;
+
+      while (--i >= 0)
+       {
+         if (type == first_dont_print[i])
+           {
+             printfi_filtered (spaces, "type node ");
+             gdb_print_address (type, gdb_stdout);
+             printf_filtered (" <same as already seen type>\n");
+             return;
+           }
+       }
+
+      obstack_ptr_grow (&dont_print_type_obstack, type);
+    }
+
+  printfi_filtered (spaces, "type node ");
+  gdb_print_address (type, gdb_stdout);
+  printf_filtered ("\n");
+  printfi_filtered (spaces, "name '%s' (",
+                   TYPE_NAME (type) ? TYPE_NAME (type) : "<NULL>");
+  gdb_print_address (TYPE_NAME (type), gdb_stdout);
+  printf_filtered (")\n");
   if (TYPE_TAG_NAME (type) != NULL)
-    printfi_filtered (spaces, "tagname '%s' (0x%lx)\n",
-                     TYPE_TAG_NAME (type),
-                     (unsigned long)TYPE_TAG_NAME (type));
+    {
+      printfi_filtered (spaces, "tagname '%s' (",
+                       TYPE_TAG_NAME (type));
+      gdb_print_address (TYPE_TAG_NAME (type), gdb_stdout);
+      printf_filtered (")\n");
+    }
   printfi_filtered (spaces, "code 0x%x ", TYPE_CODE (type));
   switch (TYPE_CODE (type))
     {
@@ -1270,60 +2667,65 @@ recursive_dump_type (type, spaces)
       case TYPE_CODE_BOOL:
        printf_filtered ("(TYPE_CODE_BOOL)");
        break;
+      case TYPE_CODE_TYPEDEF:
+       printf_filtered ("(TYPE_CODE_TYPEDEF)");
+       break;
       default:
        printf_filtered ("(UNKNOWN TYPE CODE)");
        break;
     }
   puts_filtered ("\n");
   printfi_filtered (spaces, "length %d\n", TYPE_LENGTH (type));
-  printfi_filtered (spaces, "objfile 0x%lx\n",
-                   (unsigned long) TYPE_OBJFILE (type));
-  printfi_filtered (spaces, "target_type 0x%lx\n",
-                   (unsigned long) TYPE_TARGET_TYPE (type));
+  printfi_filtered (spaces, "objfile ");
+  gdb_print_address (TYPE_OBJFILE (type), gdb_stdout);
+  printf_filtered ("\n");
+  printfi_filtered (spaces, "target_type ");
+  gdb_print_address (TYPE_TARGET_TYPE (type), gdb_stdout);
+  printf_filtered ("\n");
   if (TYPE_TARGET_TYPE (type) != NULL)
     {
       recursive_dump_type (TYPE_TARGET_TYPE (type), spaces + 2);
     }
-  printfi_filtered (spaces, "pointer_type 0x%lx\n",
-                   (unsigned long) TYPE_POINTER_TYPE (type));
-  printfi_filtered (spaces, "reference_type 0x%lx\n",
-                   (unsigned long) TYPE_REFERENCE_TYPE (type));
-  printfi_filtered (spaces, "function_type 0x%lx\n",
-                   (unsigned long) TYPE_FUNCTION_TYPE (type));
+  printfi_filtered (spaces, "pointer_type ");
+  gdb_print_address (TYPE_POINTER_TYPE (type), gdb_stdout);
+  printf_filtered ("\n");
+  printfi_filtered (spaces, "reference_type ");
+  gdb_print_address (TYPE_REFERENCE_TYPE (type), gdb_stdout);
+  printf_filtered ("\n");
   printfi_filtered (spaces, "flags 0x%x", TYPE_FLAGS (type));
   if (TYPE_FLAGS (type) & TYPE_FLAG_UNSIGNED)
     {
       puts_filtered (" TYPE_FLAG_UNSIGNED");
     }
-  if (TYPE_FLAGS (type) & TYPE_FLAG_SIGNED)
-    {
-      puts_filtered (" TYPE_FLAG_SIGNED");
-    }
   if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
     {
       puts_filtered (" TYPE_FLAG_STUB");
     }
   puts_filtered ("\n");
-  printfi_filtered (spaces, "nfields %d 0x%lx\n", TYPE_NFIELDS (type),
-                   (unsigned long) TYPE_FIELDS (type));
+  printfi_filtered (spaces, "nfields %d ", TYPE_NFIELDS (type));
+  gdb_print_address (TYPE_FIELDS (type), gdb_stdout);
+  puts_filtered ("\n");
   for (idx = 0; idx < TYPE_NFIELDS (type); idx++)
     {
       printfi_filtered (spaces + 2,
-                       "[%d] bitpos %d bitsize %d type 0x%lx name '%s' (0x%lx)\n",
+                       "[%d] bitpos %d bitsize %d type ",
                        idx, TYPE_FIELD_BITPOS (type, idx),
-                       TYPE_FIELD_BITSIZE (type, idx),
-                       (unsigned long) TYPE_FIELD_TYPE (type, idx),
-                       TYPE_FIELD_NAME (type, idx) != NULL
-                         ? TYPE_FIELD_NAME (type, idx)
-                         : "<NULL>",
-                       (unsigned long) TYPE_FIELD_NAME (type, idx));
+                       TYPE_FIELD_BITSIZE (type, idx));
+      gdb_print_address (TYPE_FIELD_TYPE (type, idx), gdb_stdout);
+      printf_filtered (" name '%s' (",
+                      TYPE_FIELD_NAME (type, idx) != NULL
+                      ? TYPE_FIELD_NAME (type, idx)
+                      : "<NULL>");
+      gdb_print_address (TYPE_FIELD_NAME (type, idx), gdb_stdout);
+      printf_filtered (")\n");
       if (TYPE_FIELD_TYPE (type, idx) != NULL)
        {
          recursive_dump_type (TYPE_FIELD_TYPE (type, idx), spaces + 4);
        }
     }
-  printfi_filtered (spaces, "vptr_basetype 0x%lx\n",
-                   (unsigned long) TYPE_VPTR_BASETYPE (type));
+  printfi_filtered (spaces, "vptr_basetype ");
+  gdb_print_address (TYPE_VPTR_BASETYPE (type), gdb_stdout);
+  puts_filtered ("\n");
   if (TYPE_VPTR_BASETYPE (type) != NULL)
     {
       recursive_dump_type (TYPE_VPTR_BASETYPE (type), spaces + 2);
@@ -1333,14 +2735,16 @@ recursive_dump_type (type, spaces)
     {
       case TYPE_CODE_METHOD:
       case TYPE_CODE_FUNC:
-       printfi_filtered (spaces, "arg_types 0x%lx\n",
-                         (unsigned long) TYPE_ARG_TYPES (type));
+       printfi_filtered (spaces, "arg_types ");
+       gdb_print_address (TYPE_ARG_TYPES (type), gdb_stdout);
+       puts_filtered ("\n");
        print_arg_types (TYPE_ARG_TYPES (type), spaces);
        break;
 
       case TYPE_CODE_STRUCT:
-       printfi_filtered (spaces, "cplus_stuff 0x%lx\n",
-                         (unsigned long) TYPE_CPLUS_SPECIFIC (type));
+       printfi_filtered (spaces, "cplus_stuff ");
+       gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
+       puts_filtered ("\n");
        print_cplus_stuff (type, spaces);
        break;
 
@@ -1348,8 +2752,8 @@ recursive_dump_type (type, spaces)
        /* We have to pick one of the union types to be able print and test
           the value.  Pick cplus_struct_type, even though we know it isn't
           any particular one. */
-       printfi_filtered (spaces, "type_specific 0x%lx",
-                         (unsigned long) TYPE_CPLUS_SPECIFIC (type));
+       printfi_filtered (spaces, "type_specific ");
+       gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
        if (TYPE_CPLUS_SPECIFIC (type) != NULL)
          {
            printf_filtered (" (unknown data form)");
@@ -1358,12 +2762,16 @@ recursive_dump_type (type, spaces)
        break;
 
     }
+  if (spaces == 0)
+    obstack_free (&dont_print_type_obstack, NULL);
 }
 
 #endif /* MAINTENANCE_CMDS */
 
-void
-_initialize_gdbtypes ()
+
+static void build_gdbtypes PARAMS ((void));
+static void
+build_gdbtypes ()
 {
   builtin_type_void =
     init_type (TYPE_CODE_VOID, 1,
@@ -1373,9 +2781,11 @@ _initialize_gdbtypes ()
     init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
               0,
               "char", (struct objfile *) NULL);
+  TYPE_FLAGS (builtin_type_char) |= TYPE_FLAG_NOSIGN;
+  
   builtin_type_signed_char =
     init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
-              TYPE_FLAG_SIGNED,
+              0,
               "signed char", (struct objfile *) NULL);
   builtin_type_unsigned_char =
     init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
@@ -1426,15 +2836,70 @@ _initialize_gdbtypes ()
               0,
               "long double", (struct objfile *) NULL);
   builtin_type_complex =
-    init_type (TYPE_CODE_FLT, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
+    init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
               0,
               "complex", (struct objfile *) NULL);
+  TYPE_TARGET_TYPE (builtin_type_complex) = builtin_type_float;
   builtin_type_double_complex =
-    init_type (TYPE_CODE_FLT, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+    init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
               0,
               "double complex", (struct objfile *) NULL);
+  TYPE_TARGET_TYPE (builtin_type_double_complex) = builtin_type_double;
   builtin_type_string =
     init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
               0,
               "string", (struct objfile *) NULL);
+  builtin_type_int8 =
+    init_type (TYPE_CODE_INT, 8 / 8,
+              0,
+              "int8_t", (struct objfile *) NULL);
+  builtin_type_uint8 =
+    init_type (TYPE_CODE_INT, 8 / 8,
+              TYPE_FLAG_UNSIGNED,
+              "uint8_t", (struct objfile *) NULL);
+  builtin_type_int16 =
+    init_type (TYPE_CODE_INT, 16 / 8,
+              0,
+              "int16_t", (struct objfile *) NULL);
+  builtin_type_uint16 =
+    init_type (TYPE_CODE_INT, 16 / 8,
+              TYPE_FLAG_UNSIGNED,
+              "uint16_t", (struct objfile *) NULL);
+  builtin_type_int32 =
+    init_type (TYPE_CODE_INT, 32 / 8,
+              0,
+              "int32_t", (struct objfile *) NULL);
+  builtin_type_uint32 =
+    init_type (TYPE_CODE_INT, 32 / 8,
+              TYPE_FLAG_UNSIGNED,
+              "uint32_t", (struct objfile *) NULL);
+  builtin_type_int64 =
+    init_type (TYPE_CODE_INT, 64 / 8,
+              0,
+              "int64_t", (struct objfile *) NULL);
+  builtin_type_uint64 =
+    init_type (TYPE_CODE_INT, 64 / 8,
+              TYPE_FLAG_UNSIGNED,
+              "uint64_t", (struct objfile *) NULL);
+  builtin_type_bool =
+    init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+              0,
+              "bool", (struct objfile *) NULL);
+
+  /* Add user knob for controlling resolution of opaque types */ 
+  add_show_from_set
+    (add_set_cmd ("opaque-type-resolution", class_support, var_boolean, (char *)&opaque_type_resolution,
+                 "Set resolution of opaque struct/class/union types (if set before loading symbols).",
+                 &setlist),
+     &showlist);
+  opaque_type_resolution = 1;
+
+}
+
+
+extern void _initialize_gdbtypes PARAMS ((void));
+void
+_initialize_gdbtypes ()
+{
+  build_gdbtypes ();
 }
This page took 0.043866 seconds and 4 git commands to generate.