* debug.h (enum debug_type_kind): Add DEBUG_KIND_ILLEGAL.
authorIan Lance Taylor <ian@airs.com>
Fri, 19 Jan 1996 18:03:04 +0000 (18:03 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 19 Jan 1996 18:03:04 +0000 (18:03 +0000)
(struct debug_write_fns): Add field ellipsis_type.  Add id
parameter to start_struct_type, start_class_type, and tag_type.
(debug_make_ellipsis_type): Declare.
(debug_find_named_type): Declare.
(debug_get_type_kind): Declare.
(debug_get_return_type): Declare.
(debug_get_parameter_types): Declare.
(debug_get_fields): Declare.
(debug_get_field_type): Declare.
* debug.c (struct debug_handle): Add fields class_id and base_id.
(struct debug_class_type): Add field id.
(struct debug_method_variant): Rename argtypes to physname.
Change all uses.
(debug_ellipsis_type): New static variable.
(ELLIPSIS_P): New macro.
(debug_make_ellipsis_type): New function.
(debug_make_method_variant): Rename argtypes to physname.
(debug_make_static_method_variant): Likewise.
(debug_name_type): Always put types in the global namespace.
(debug_find_named_type): New function.
(debug_find_tagged_type): Treat DEBUG_KIND_ILLEGAL specially,
rather than DEBUG_KIND_VOID.
(debug_get_real_type): New static function.
(debug_get_type_kind): New function.
(debug_get_return_type): New function.
(debug_get_parameter_types): New function.
(debug_get_fields): New function.
(debug_get_field_type): New function.
(debug_write): Initialize base_id.
(debug_write_type): Pass new id argument to tag_type.  Handle
DEBUG_KIND_ILLEGAL.  Use id for DEBUG_KIND_STRUCT and
DEBUG_KIND_UNION.  Handle ellipsis for method arguments.
(debug_write_class_type): Don't dereference kclass if it is NULL.
Use id.
* prdbg.c (pr_fns): Add pr_ellipsis_type.
(pr_ellipsis_type): New static function.
(pr_pointer_type): If this is a pointer to an array, parenthesize
it correctly.
(pr_start_struct_type): Add id parameter.
(pr_start_class_type): Likewise.
(pr_tag_type): Likewise.
(pr_fix_visibility): Add the visibility to the top of the stack,
not the second element on the stack.
(pr_struct_field): Pop the stack before calling pr_fix_visibility.
(pr_class_static_member): Likewise.
(pr_class_start_method): Don't push a type, just set the method
name in the type on the top of the stack.
(pr_class_end_method): Don't pop the stack.
(pr_class_method_variant): Rename argtypes parameter to physname.
Append const and volatile rather than prepending them.  Add a
space after the physname.
(pr_class_static_method_variant): Likewise.
* ieee.c (ieee_fns): Add ieee_ellipsis_type.
(ieee_define_named_type): Use DEBUG_KIND_ILLEGAL rather than
DEBUG_KIND_VOID.
(write_ieee_debugging_info): Likewise.
(ieee_typdef): Likewise.
(ieee_ellipsis_type): New static function.
(ieee_start_struct_type): Add id parameter.
(ieee_start_class_type): Likewise.
(ieee_tag_type): Likewise.
(ieee_class_method_variant): Rename name to physname.
(ieee_class_static_method_variant): Likewise.

binutils/debug.c
binutils/debug.h
binutils/ieee.c
binutils/prdbg.c

index 02a80ae..edb5835 100644 (file)
@@ -54,6 +54,10 @@ struct debug_handle
   unsigned int mark;
   /* Another mark used by debug_write.  */
   unsigned int class_mark;
+  /* A struct/class ID used by debug_write.  */
+  unsigned int class_id;
+  /* The base for class_id for this call to debug_write.  */
+  unsigned int base_id;
 };
 
 /* Information we keep for a single compilation unit.  */
@@ -150,6 +154,8 @@ struct debug_class_type
   debug_field *fields;
   /* A mark field used to avoid recursively printing out structs.  */
   unsigned int mark;
+  /* This is used to uniquely identify unnamed structs when printing.  */
+  unsigned int id;
   /* The remaining fields are only used for DEBUG_KIND_CLASS and
      DEBUG_KIND_UNION_CLASS.  */
   /* NULL terminated array of base classes.  */
@@ -309,8 +315,8 @@ struct debug_method
 
 struct debug_method_variant
 {
-  /* The argument types of the function.  */
-  const char *argtypes;
+  /* The physical name of the function.  */
+  const char *physname;
   /* The type of the function.  */
   struct debug_type *type;
   /* The visibility of the function.  */
@@ -497,6 +503,17 @@ struct debug_name
     } u;
 };
 
+/* This variable is an ellipsis type.  The contents are not used; its
+   address is returned by debug_make_ellipsis_type, and anything which
+   needs to know whether it is dealing with an ellipsis compares
+   addresses.  */
+
+static const struct debug_type debug_ellipsis_type;
+
+#define ELLIPSIS_P(t) ((t) == &debug_ellipsis_type)
+
+/* Local functions.  */
+
 static void debug_error PARAMS ((const char *));
 static struct debug_name *debug_add_to_namespace
   PARAMS ((struct debug_handle *, struct debug_namespace **, const char *,
@@ -506,6 +523,7 @@ static struct debug_name *debug_add_to_current_namespace
           enum debug_object_linkage));
 static struct debug_type *debug_make_type
   PARAMS ((struct debug_handle *, enum debug_type_kind, unsigned int));
+static struct debug_type *debug_get_real_type PARAMS ((PTR, debug_type));
 static boolean debug_write_name
   PARAMS ((struct debug_handle *, const struct debug_write_fns *, PTR,
           struct debug_name *));
@@ -1223,6 +1241,18 @@ debug_make_indirect_type (handle, slot, tag)
   return t;
 }
 
+/* Make an ellipsis type.  This is not a type at all, but is a marker
+   suitable for appearing in the list of argument types passed to
+   debug_make_method_type.  It should be used to indicate a method
+   which takes a variable number of arguments.  */
+
+debug_type
+debug_make_ellipsis_type (handle)
+     PTR handle;
+{
+  return (debug_type) &debug_ellipsis_type;
+}
+
 /* Make a void type.  There is only one of these.  */
 
 debug_type
@@ -1847,10 +1877,10 @@ debug_make_method (handle, name, variants)
 
 /*ARGSUSED*/
 debug_method_variant
-debug_make_method_variant (handle, argtypes, type, visibility, constp,
+debug_make_method_variant (handle, physname, type, visibility, constp,
                           volatilep, voffset, context)
      PTR handle;
-     const char *argtypes;
+     const char *physname;
      debug_type type;
      enum debug_visibility visibility;
      boolean constp;
@@ -1863,7 +1893,7 @@ debug_make_method_variant (handle, argtypes, type, visibility, constp,
   m = (struct debug_method_variant *) xmalloc (sizeof *m);
   memset (m, 0, sizeof *m);
 
-  m->argtypes = argtypes;
+  m->physname = physname;
   m->type = type;
   m->visibility = visibility;
   m->constp = constp;
@@ -1879,10 +1909,10 @@ debug_make_method_variant (handle, argtypes, type, visibility, constp,
    since a static method can not also be virtual.  */
 
 debug_method_variant
-debug_make_static_method_variant (handle, argtypes, type, visibility,
+debug_make_static_method_variant (handle, physname, type, visibility,
                                  constp, volatilep)
      PTR handle;
-     const char *argtypes;
+     const char *physname;
      debug_type type;
      enum debug_visibility visibility;
      boolean constp;
@@ -1893,7 +1923,7 @@ debug_make_static_method_variant (handle, argtypes, type, visibility,
   m = (struct debug_method_variant *) xmalloc (sizeof *m);
   memset (m, 0, sizeof *m);
 
-  m->argtypes = argtypes;
+  m->physname = physname;
   m->type = type;
   m->visibility = visibility;
   m->constp = constp;
@@ -1919,6 +1949,13 @@ debug_name_type (handle, name, type)
   if (name == NULL || type == NULL)
     return DEBUG_TYPE_NULL;
 
+  if (info->current_unit == NULL
+      || info->current_file == NULL)
+    {
+      debug_error ("debug_record_variable: no current file");
+      return false;
+    }
+
   t = debug_make_type (info, DEBUG_KIND_NAMED, 0);
   if (t == NULL)
     return DEBUG_TYPE_NULL;
@@ -1930,10 +1967,11 @@ debug_name_type (handle, name, type)
 
   t->u.knamed = n;
 
-  /* We also need to add the name to the current namespace.  */
+  /* We always add the name to the global namespace.  This is probably
+     wrong in some cases, but it seems to be right for stabs.  FIXME.  */
 
-  nm = debug_add_to_current_namespace (info, name, DEBUG_OBJECT_TYPE,
-                                      DEBUG_LINKAGE_NONE);
+  nm = debug_add_to_namespace (info, &info->current_file->globals, name,
+                              DEBUG_OBJECT_TYPE, DEBUG_LINKAGE_NONE);
   if (nm == NULL)
     return false;
 
@@ -2018,6 +2056,61 @@ debug_record_type_size (handle, type, size)
   return true;
 }
 
+/* Find a named type.  */
+
+debug_type
+debug_find_named_type (handle, name)
+     PTR handle;
+     const char *name;
+{
+  struct debug_handle *info = (struct debug_handle *) handle;
+  struct debug_block *b;
+  struct debug_file *f;
+
+  /* We only search the current compilation unit.  I don't know if
+     this is right or not.  */
+
+  if (info->current_unit == NULL)
+    {
+      debug_error ("debug_find_named_type: no current compilation unit");
+      return DEBUG_TYPE_NULL;
+    }
+
+  for (b = info->current_block; b != NULL; b = b->parent)
+    {
+      if (b->locals != NULL)
+       {
+         struct debug_name *n;
+
+         for (n = b->locals->list; n != NULL; n = n->next)
+           {
+             if (n->kind == DEBUG_OBJECT_TYPE
+                 && n->name[0] == name[0]
+                 && strcmp (n->name, name) == 0)
+               return n->u.type;
+           }
+       }
+    }
+
+  for (f = info->current_unit->files; f != NULL; f = f->next)
+    {
+      if (f->globals != NULL)
+       {
+         struct debug_name *n;
+
+         for (n = f->globals->list; n != NULL; n = n->next)
+           {
+             if (n->kind == DEBUG_OBJECT_TYPE
+                 && n->name[0] == name[0]
+                 && strcmp (n->name, name) == 0)
+               return n->u.type;
+           }
+       }
+    }
+
+  return DEBUG_TYPE_NULL;        
+}
+
 /* Find a tagged type.  */
 
 debug_type
@@ -2045,7 +2138,7 @@ debug_find_tagged_type (handle, name, kind)
              for (n = f->globals->list; n != NULL; n = n->next)
                {
                  if (n->kind == DEBUG_OBJECT_TAG
-                     && (kind == DEBUG_KIND_VOID
+                     && (kind == DEBUG_KIND_ILLEGAL
                          || n->u.tag->kind == kind)
                      && n->name[0] == name[0]
                      && strcmp (n->name, name) == 0)
@@ -2058,9 +2151,42 @@ debug_find_tagged_type (handle, name, kind)
   return DEBUG_TYPE_NULL;
 }
 
+/* Get a base type.  */
+
+static struct debug_type *
+debug_get_real_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  switch (type->kind)
+    {
+    default:
+      return type;
+    case DEBUG_KIND_INDIRECT:
+      if (*type->u.kindirect->slot != NULL)
+       return debug_get_real_type (handle, *type->u.kindirect->slot);
+      return type;
+    case DEBUG_KIND_NAMED:
+      return debug_get_real_type (handle, type->u.knamed->type);
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the kind of a type.  */
+
+enum debug_type_kind
+debug_get_type_kind (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return DEBUG_KIND_ILLEGAL;
+  type = debug_get_real_type (handle, type);
+  return type->kind;
+}
+
 /* Get the name of a type.  */
 
-/*ARGSUSED*/
 const char *
 debug_get_type_name (handle, type)
      PTR handle;
@@ -2077,6 +2203,86 @@ debug_get_type_name (handle, type)
     return type->u.knamed->name->name;
   return NULL;
 }
+
+/* Get the return type of a function or method type.  */
+
+debug_type
+debug_get_return_type (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return DEBUG_TYPE_NULL;
+  type = debug_get_real_type (handle, type);
+  switch (type->kind)
+    {
+    default:
+      return DEBUG_TYPE_NULL;
+    case DEBUG_KIND_FUNCTION:
+      return type->u.kfunction->return_type;
+    case DEBUG_KIND_METHOD:
+      return type->u.kmethod->return_type;
+    }
+  /*NOTREACHED*/      
+}
+
+/* Get the parameter types of a function or method type (except that
+   we don't currently store the parameter types of a function).  */
+
+const debug_type *
+debug_get_parameter_types (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return NULL;
+  type = debug_get_real_type (handle, type);
+  switch (type->kind)
+    {
+    default:
+      return NULL;
+    case DEBUG_KIND_METHOD:
+      return type->u.kmethod->arg_types;
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the NULL terminated array of fields for a struct, union, or
+   class.  */
+
+const debug_field *
+debug_get_fields (handle, type)
+     PTR handle;
+     debug_type type;
+{
+  if (type == NULL)
+    return NULL;
+  type = debug_get_real_type (handle, type);
+  switch (type->kind)
+    {
+    default:
+      return NULL;
+    case DEBUG_KIND_STRUCT:
+    case DEBUG_KIND_UNION:
+    case DEBUG_KIND_CLASS:
+    case DEBUG_KIND_UNION_CLASS:
+      return type->u.kclass->fields;
+    }
+  /*NOTREACHED*/
+}
+
+/* Get the type of a field.  */
+
+/*ARGSUSED*/
+debug_type
+debug_get_field_type (handle, field)
+     PTR handle;
+     debug_field field;
+{
+  if (field == NULL)
+    return NULL;
+  return field->type;
+}
 \f
 /* Write out the debugging information.  This is given a handle to
    debugging information, and a set of function pointers to call.  */
@@ -2096,6 +2302,11 @@ debug_write (handle, fns, fhandle)
      information more than once.  */
   ++info->mark;
 
+  /* The base_id field holds an ID value which will never be used, so
+     that we can tell whether we have assigned an ID during this call
+     to debug_write.  */
+  info->base_id = info->class_id;
+
   for (u = info->units; u != NULL; u = u->next)
     {
       struct debug_file *f;
@@ -2225,7 +2436,7 @@ debug_write_type (info, fns, fhandle, type, name)
       if (type->kind == DEBUG_KIND_NAMED)
        return (*fns->typedef_type) (fhandle, type->u.knamed->name->name);
       else
-       return (*fns->tag_type) (fhandle, type->u.knamed->name->name,
+       return (*fns->tag_type) (fhandle, type->u.knamed->name->name, 0,
                                 type->u.knamed->type->kind);
     }
 
@@ -2247,6 +2458,9 @@ debug_write_type (info, fns, fhandle, type, name)
 
   switch (type->kind)
     {
+    case DEBUG_KIND_ILLEGAL:
+      debug_error ("debug_write_type: illegal type encountered");
+      return false;
     case DEBUG_KIND_INDIRECT:
       if (*type->u.kindirect->slot == DEBUG_TYPE_NULL)
        return (*fns->empty_type) (fhandle);
@@ -2266,17 +2480,25 @@ debug_write_type (info, fns, fhandle, type, name)
     case DEBUG_KIND_UNION:
       if (type->u.kclass != NULL)
        {
-         if (info->class_mark == type->u.kclass->mark)
+         if (info->class_mark == type->u.kclass->mark
+             || type->u.kclass->id > info->base_id)
            {
-             /* We are currently outputting this struct.  I don't
-                know if this can happen, but it can happen for a
-                class.  */
-             return (*fns->tag_type) (fhandle, "?defining?", type->kind);
+             /* We are currently outputting this struct, or we have
+                already output it.  I don't know if this can happen,
+                but it can happen for a class.  */
+             assert (type->u.kclass->id > info->base_id);
+             return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+                                      type->kind);
            }
          type->u.kclass->mark = info->class_mark;
+         ++info->class_id;
+         type->u.kclass->id = info->class_id;
        }
 
       if (! (*fns->start_struct_type) (fhandle, tag,
+                                      (type->u.kclass != NULL
+                                       ? type->u.kclass->id
+                                       : 0),
                                       type->kind == DEBUG_KIND_STRUCT,
                                       type->size))
        return false;
@@ -2361,10 +2583,18 @@ debug_write_type (info, fns, fhandle, type, name)
        {
          for (i = 0; type->u.kmethod->arg_types[i] != NULL; i++)
            {
-             if (! debug_write_type (info, fns, fhandle,
-                                     type->u.kmethod->arg_types[i],
-                                     (struct debug_name *) NULL))
-               return false;
+             if (ELLIPSIS_P (type->u.kmethod->arg_types[i]))
+               {
+                 if (! (*fns->ellipsis_type) (fhandle))
+                   return false;
+               }
+             else
+               {
+                 if (! debug_write_type (info, fns, fhandle,
+                                         type->u.kmethod->arg_types[i],
+                                         (struct debug_name *) NULL))
+                   return false;
+               }
            }
        }
       if (type->u.kmethod->domain_type != NULL)
@@ -2410,32 +2640,45 @@ debug_write_class_type (info, fns, fhandle, type, tag)
      const char *tag;
 {
   unsigned int i;
+  unsigned int id;
+  struct debug_type *vptrbase;
 
-  if (type->u.kclass != NULL)
+  if (type->u.kclass == NULL)
     {
-      if (info->class_mark == type->u.kclass->mark)
+      id = 0;
+      vptrbase = NULL;
+    }
+  else
+    {
+      if (info->class_mark == type->u.kclass->mark
+         || type->u.kclass->id > info->base_id)
        {
-         /* We are currently outputting this class.  This can happen
-            when there are methods for an anonymous class.  */
-         return (*fns->tag_type) (fhandle, "?defining?", type->kind);
+         /* We are currently outputting this class, or we have
+            already output it.  This can happen when there are
+            methods for an anonymous class.  */
+         assert (type->u.kclass->id > info->base_id);
+         return (*fns->tag_type) (fhandle, tag, type->u.kclass->id,
+                                  type->kind);
        }
       type->u.kclass->mark = info->class_mark;
+      ++info->class_id;
+      id = info->class_id;
+      type->u.kclass->id = id;
 
-      if (type->u.kclass->vptrbase != NULL
-         && type->u.kclass->vptrbase != type)
+      vptrbase = type->u.kclass->vptrbase;
+      if (vptrbase != NULL && vptrbase != type)
        {
-         if (! debug_write_type (info, fns, fhandle,
-                                 type->u.kclass->vptrbase,
+         if (! debug_write_type (info, fns, fhandle, vptrbase,
                                  (struct debug_name *) NULL))
            return false;
        }
     }
 
-  if (! (*fns->start_class_type) (fhandle, tag,
+  if (! (*fns->start_class_type) (fhandle, tag, id,
                                  type->kind == DEBUG_KIND_CLASS,
                                  type->size,
-                                 type->u.kclass->vptrbase != NULL,
-                                 type->u.kclass->vptrbase == type))
+                                 vptrbase != NULL,
+                                 vptrbase == type))
     return false;
 
   if (type->u.kclass != NULL)
@@ -2508,7 +2751,7 @@ debug_write_class_type (info, fns, fhandle, type, tag)
                    return false;
                  if (v->voffset != VOFFSET_STATIC_METHOD)
                    {
-                     if (! (*fns->class_method_variant) (fhandle, v->argtypes,
+                     if (! (*fns->class_method_variant) (fhandle, v->physname,
                                                          v->visibility,
                                                          v->constp,
                                                          v->volatilep,
@@ -2519,7 +2762,7 @@ debug_write_class_type (info, fns, fhandle, type, tag)
                  else
                    {
                      if (! (*fns->class_static_method_variant) (fhandle,
-                                                                v->argtypes,
+                                                                v->physname,
                                                                 v->visibility,
                                                                 v->constp,
                                                                 v->volatilep))
index 0c3a692..d40679b 100644 (file)
@@ -32,6 +32,8 @@
 
 enum debug_type_kind
 {
+  /* Not used.  */
+  DEBUG_KIND_ILLEGAL,
   /* Indirect via a pointer.  */
   DEBUG_KIND_INDIRECT,
   /* Void.  */
@@ -172,6 +174,11 @@ struct debug_write_fns
 
   /* Each writer must keep a stack of types.  */
 
+  /* Push an ellipsis type onto the type stack.  This is not a real
+     type, but is used when a method takes a variable number of
+     arguments.  */
+  boolean (*ellipsis_type) PARAMS ((PTR));
+
   /* Push an empty type onto the type stack.  This type can appear if
      there is a reference to a type which is never defined.  */
   boolean (*empty_type) PARAMS ((PTR));
@@ -258,13 +265,14 @@ struct debug_write_fns
   /* Start building a struct.  This is followed by calls to the
      struct_field function, and finished by a call to the
      end_struct_type function.  The second argument is the tag; this
-     will be NULL if there isn't one.  The boolean argument is true
-     for a struct, false for a union.  The unsigned int argument is
-     the size.  If this is an undefined struct or union, the size will
-     be 0 and struct_field will not be called before end_struct_type
-     is called.  */
-  boolean (*start_struct_type) PARAMS ((PTR, const char *, boolean,
-                                       unsigned int));
+     will be NULL if there isn't one.  If the second argument is NULL,
+     the third argument is a constant identifying this struct for use
+     with tag_type.  The fourth argument is true for a struct, false
+     for a union.  The fifth argument is the size.  If this is an
+     undefined struct or union, the size will be 0 and struct_field
+     will not be called before end_struct_type is called.  */
+  boolean (*start_struct_type) PARAMS ((PTR, const char *, unsigned int,
+                                       boolean, unsigned int));
 
   /* Add a field to the struct type currently being built.  The type
      of the field should be popped off the type stack.  The arguments
@@ -280,16 +288,16 @@ struct debug_write_fns
      functions: struct_field, class_static_member, class_baseclass,
      class_start_method, class_method_variant,
      class_static_method_variant, and class_end_method.  The class is
-     finished by a call to end_class_type.  The second argument is the
-     tag; this will be NULL if there isn't one.  The boolean argument
-     is true for a struct, false for a union.  The next argument is
-     the size.  The next argument is true if there is a virtual
-     function table; if there is, the next argument is true if the
-     virtual function table can be found in the type itself, and is
-     false if the type of the object holding the virtual function
-     table should be popped from the type stack.  */
-  boolean (*start_class_type) PARAMS ((PTR, const char *, boolean,
-                                      unsigned int, boolean, boolean));
+     finished by a call to end_class_type.  The first five arguments
+     are the same as for start_struct_type.  The sixth argument is
+     true if there is a virtual function table; if there is, the
+     seventh argument is true if the virtual function table can be
+     found in the type itself, and is false if the type of the object
+     holding the virtual function table should be popped from the type
+     stack.  */
+  boolean (*start_class_type) PARAMS ((PTR, const char *, unsigned int,
+                                      boolean, unsigned int, boolean,
+                                      boolean));
 
   /* Add a static member to the class currently being built.  The
      arguments are the field name, the physical name, and the
@@ -314,12 +322,11 @@ struct debug_write_fns
 
   /* Describe a variant to the class method currently being built.
      The type of the variant must be popped off the type stack.  The
-     second argument is a string which is either the physical name of
-     the function or describes the argument types; see the comment for
-     debug_make_method variant.  The following arguments are the
-     visibility, whether the variant is const, whether the variant is
-     volatile, the offset in the virtual function table, and whether
-     the context is on the type stack (below the variant type).  */
+     second argument is the physical name of the function.  The
+     following arguments are the visibility, whether the variant is
+     const, whether the variant is volatile, the offset in the virtual
+     function table, and whether the context is on the type stack
+     (below the variant type).  */
   boolean (*class_method_variant) PARAMS ((PTR, const char *,
                                           enum debug_visibility,
                                           boolean, boolean,
@@ -343,9 +350,17 @@ struct debug_write_fns
      call to typdef.  */
   boolean (*typedef_type) PARAMS ((PTR, const char *));
 
-  /* Push a type on the stack which was given a name by an earlier
-     call to tag.  */
-  boolean (*tag_type) PARAMS ((PTR, const char *, enum debug_type_kind));
+  /* Push a tagged type on the stack which was defined earlier.  If
+     the second argument is not NULL, the type was defined by a call
+     to tag.  If the second argument is NULL, the type was defined by
+     a call to start_struct_type or start_class_type with a tag of
+     NULL and the number of the third argument.  Either way, the
+     fourth argument is the tag kind.  Note that this may be called
+     for a struct (class) being defined, in between the call to
+     start_struct_type (start_class_type) and the call to
+     end_struct_type (end_class_type).  */
+  boolean (*tag_type) PARAMS ((PTR, const char *, unsigned int,
+                              enum debug_type_kind));
 
   /* Pop the type stack, and typedef it to the given name.  */
   boolean (*typdef) PARAMS ((PTR, const char *));
@@ -504,6 +519,13 @@ extern boolean debug_record_variable
 extern debug_type debug_make_indirect_type
   PARAMS ((PTR, debug_type *, const char *));
 
+/* Make an ellipsis type.  This is not a type at all, but is a marker
+   suitable for appearing in the list of argument types passed to
+   debug_make_method_type.  It should be used to indicate a method
+   which takes a variable number of arguments.  */
+
+extern debug_type debug_make_ellipsis_type PARAMS ((PTR));
+
 /* Make a void type.  */
 
 extern debug_type debug_make_void_type PARAMS ((PTR));
@@ -656,10 +678,9 @@ extern debug_field debug_make_static_member
 extern debug_method debug_make_method
   PARAMS ((PTR, const char *, debug_method_variant *));
 
-/* Make a method variant.  The second argument is either the physical
-   name of the function, or the encoded argument types, depending upon
-   whether the third argument specifies the argument types or not.
-   The third argument is the type of the function.  The fourth
+/* Make a method variant.  The second argument is the physical name of
+   the function.  The third argument is the type of the function,
+   probably constructed by debug_make_method_type.  The fourth
    argument is the visibility.  The fifth argument is whether this is
    a const function.  The sixth argument is whether this is a volatile
    function.  The seventh argument is the offset in the virtual
@@ -693,15 +714,43 @@ extern debug_type debug_tag_type PARAMS ((PTR, const char *, debug_type));
 
 extern boolean debug_record_type_size PARAMS ((PTR, debug_type, unsigned int));
 
+/* Find a named type.  */
+
+extern debug_type debug_find_named_type PARAMS ((PTR, const char *));
+
 /* Find a tagged type.  */
 
 extern debug_type debug_find_tagged_type
   PARAMS ((PTR, const char *, enum debug_type_kind));
 
+/* Get the kind of a type.  */
+
+extern enum debug_type_kind debug_get_type_kind PARAMS ((PTR, debug_type));
+
 /* Get the name of a type.  */
 
 extern const char *debug_get_type_name PARAMS ((PTR, debug_type));
 
+/* Get the return type of a function or method type.  */
+
+extern debug_type debug_get_return_type PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of parameter types for a function or
+   method type (actually, parameter types are not currently stored for
+   function types).  This may be used to determine whether a method
+   type is a stub method or not.  */
+
+extern const debug_type *debug_get_parameter_types PARAMS ((PTR, debug_type));
+
+/* Get the NULL terminated array of fields for a struct, union, or
+   class.  */
+
+extern const debug_field *debug_get_fields PARAMS ((PTR, debug_type));
+
+/* Get the type of a field.  */
+
+extern debug_type debug_get_field_type PARAMS ((PTR, debug_field));
+
 /* Write out the recorded debugging information.  This takes a set of
    function pointers which are called to do the actual writing.  The
    first PTR is the debugging handle.  The second PTR is a handle
index ac85f73..0006460 100644 (file)
@@ -2267,7 +2267,7 @@ struct ieee_name_type
   /* Type.  */
   struct ieee_write_type type;
   /* If this is a tag which has not yet been defined, this is the
-     kind.  If the tag has been defined, this is DEBUG_KIND_VOID.  */
+     kind.  If the tag has been defined, this is DEBUG_KIND_ILLEGAL.  */
   enum debug_type_kind kind;
 };
 
@@ -2357,6 +2357,7 @@ static boolean ieee_output_pending_parms PARAMS ((struct ieee_handle *));
 
 static boolean ieee_start_compilation_unit PARAMS ((PTR, const char *));
 static boolean ieee_start_source PARAMS ((PTR, const char *));
+static boolean ieee_ellipsis_type PARAMS ((PTR));
 static boolean ieee_empty_type PARAMS ((PTR));
 static boolean ieee_void_type PARAMS ((PTR));
 static boolean ieee_int_type PARAMS ((PTR, unsigned int, boolean));
@@ -2377,12 +2378,13 @@ static boolean ieee_method_type PARAMS ((PTR, boolean, int));
 static boolean ieee_const_type PARAMS ((PTR));
 static boolean ieee_volatile_type PARAMS ((PTR));
 static boolean ieee_start_struct_type
-  PARAMS ((PTR, const char *, boolean, unsigned int));
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
 static boolean ieee_struct_field
   PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
 static boolean ieee_end_struct_type PARAMS ((PTR));
 static boolean ieee_start_class_type
-  PARAMS ((PTR, const char *, boolean, unsigned int, boolean, boolean));
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+          boolean));
 static boolean ieee_class_static_member
   PARAMS ((PTR, const char *, const char *, enum debug_visibility));
 static boolean ieee_class_baseclass
@@ -2397,7 +2399,7 @@ static boolean ieee_class_end_method PARAMS ((PTR));
 static boolean ieee_end_class_type PARAMS ((PTR));
 static boolean ieee_typedef_type PARAMS ((PTR, const char *));
 static boolean ieee_tag_type
-  PARAMS ((PTR, const char *, enum debug_type_kind));
+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
 static boolean ieee_typdef PARAMS ((PTR, const char *));
 static boolean ieee_tag PARAMS ((PTR, const char *));
 static boolean ieee_int_constant PARAMS ((PTR, const char *, bfd_vma));
@@ -2418,6 +2420,7 @@ static const struct debug_write_fns ieee_fns =
 {
   ieee_start_compilation_unit,
   ieee_start_source,
+  ieee_ellipsis_type,
   ieee_empty_type,
   ieee_void_type,
   ieee_int_type,
@@ -2797,7 +2800,7 @@ ieee_define_named_type (info, name, tagp, size, unsignedp, ppbuf)
 
       nt->type.size = size;
       nt->type.unsignedp = unsignedp;
-      nt->kind = DEBUG_KIND_VOID;
+      nt->kind = DEBUG_KIND_ILLEGAL;
 
       type_indx = nt->type.indx;
     }
@@ -2878,7 +2881,7 @@ write_ieee_debugging_info (abfd, dhandle)
       unsigned int name_indx;
       char code;
 
-      if (nt->kind == DEBUG_KIND_VOID)
+      if (nt->kind == DEBUG_KIND_ILLEGAL)
        continue;
       if (tags == NULL)
        {
@@ -3158,6 +3161,15 @@ ieee_start_source (p, filename)
   return true;
 }
 
+/* Make an ellipsis type.  */
+
+static boolean
+ieee_ellipsis_type (p)
+     PTR p;
+{
+  abort ();
+}
+
 /* Make an empty type.  */
 
 static boolean
@@ -3598,9 +3610,10 @@ ieee_volatile_type (p)
    fields with the struct type itself.  */
 
 static boolean
-ieee_start_struct_type (p, tag, structp, size)
+ieee_start_struct_type (p, tag, id, structp, size)
      PTR p;
      const char *tag;
+     unsigned int id;
      boolean structp;
      unsigned int size;
 {
@@ -3699,9 +3712,10 @@ ieee_end_struct_type (p)
 /* Start a class type.  */
 
 static boolean
-ieee_start_class_type (p, tag, structp, size, vptr, ownvptr)
+ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
      PTR p;
      const char *tag;
+     unsigned int id;
      boolean structp;
      unsigned int size;
      boolean vptr;
@@ -3712,7 +3726,7 @@ ieee_start_class_type (p, tag, structp, size, vptr, ownvptr)
   /* FIXME.  */
   if (vptr && ! ownvptr)
     (void) ieee_pop_type (info);
-  return ieee_start_struct_type (p, tag, structp, size);
+  return ieee_start_struct_type (p, tag, id, structp, size);
 }
 
 /* Add a static member to a class.  */
@@ -3761,10 +3775,10 @@ ieee_class_start_method (p, name)
 /* Define a new method variant.  */
 
 static boolean
-ieee_class_method_variant (p, name, visibility, constp, volatilep,
+ieee_class_method_variant (p, physname, visibility, constp, volatilep,
                           voffset, context)
      PTR p;
-     const char *name;
+     const char *physname;
      enum debug_visibility visibility;
      boolean constp;
      boolean volatilep;
@@ -3783,9 +3797,9 @@ ieee_class_method_variant (p, name, visibility, constp, volatilep,
 /* Define a new static method variant.  */
 
 static boolean
-ieee_class_static_method_variant (p, name, visibility, constp, volatilep)
+ieee_class_static_method_variant (p, physname, visibility, constp, volatilep)
      PTR p;
-     const char *name;
+     const char *physname;
      enum debug_visibility visibility;
      boolean constp;
      boolean volatilep;
@@ -3846,14 +3860,18 @@ ieee_typedef_type (p, name)
 /* Push a tagged type onto the type stack.  */
 
 static boolean
-ieee_tag_type (p, name, kind)
+ieee_tag_type (p, name, id, kind)
      PTR p;
      const char *name;
+     unsigned int id;
      enum debug_type_kind kind;
 {
   struct ieee_handle *info = (struct ieee_handle *) p;
   register struct ieee_name_type *nt;
 
+  if (name == NULL)
+    return true;
+
   for (nt = info->tags; nt != NULL; nt = nt->next)
     {
       if (nt->name[0] == name[0]
@@ -3899,7 +3917,7 @@ ieee_typdef (p, name)
   memset (nt, 0, sizeof *nt);
   nt->name = name;
   nt->type = info->type_stack->type;
-  nt->kind = DEBUG_KIND_VOID;
+  nt->kind = DEBUG_KIND_ILLEGAL;
 
   nt->next = info->typedefs;
   info->typedefs = nt;
index 133973c..f7383bb 100644 (file)
@@ -72,6 +72,7 @@ static boolean pr_fix_visibility
 
 static boolean pr_start_compilation_unit PARAMS ((PTR, const char *));
 static boolean pr_start_source PARAMS ((PTR, const char *));
+static boolean pr_ellipsis_type PARAMS ((PTR));
 static boolean pr_empty_type PARAMS ((PTR));
 static boolean pr_void_type PARAMS ((PTR));
 static boolean pr_int_type PARAMS ((PTR, unsigned int, boolean));
@@ -92,12 +93,13 @@ static boolean pr_method_type PARAMS ((PTR, boolean, int));
 static boolean pr_const_type PARAMS ((PTR));
 static boolean pr_volatile_type PARAMS ((PTR));
 static boolean pr_start_struct_type
-  PARAMS ((PTR, const char *, boolean, unsigned int));
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int));
 static boolean pr_struct_field
   PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility));
 static boolean pr_end_struct_type PARAMS ((PTR));
 static boolean pr_start_class_type
-  PARAMS ((PTR, const char *, boolean, unsigned int, boolean, boolean));
+  PARAMS ((PTR, const char *, unsigned int, boolean, unsigned int, boolean,
+          boolean));
 static boolean pr_class_static_member
   PARAMS ((PTR, const char *, const char *, enum debug_visibility));
 static boolean pr_class_baseclass
@@ -111,7 +113,8 @@ static boolean pr_class_static_method_variant
 static boolean pr_class_end_method PARAMS ((PTR));
 static boolean pr_end_class_type PARAMS ((PTR));
 static boolean pr_typedef_type PARAMS ((PTR, const char *));
-static boolean pr_tag_type PARAMS ((PTR, const char *, enum debug_type_kind));
+static boolean pr_tag_type
+  PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind));
 static boolean pr_typdef PARAMS ((PTR, const char *));
 static boolean pr_tag PARAMS ((PTR, const char *));
 static boolean pr_int_constant PARAMS ((PTR, const char *, bfd_vma));
@@ -131,6 +134,7 @@ static const struct debug_write_fns pr_fns =
 {
   pr_start_compilation_unit,
   pr_start_source,
+  pr_ellipsis_type,
   pr_empty_type,
   pr_void_type,
   pr_int_type,
@@ -409,6 +413,17 @@ pr_start_source (p, filename)
   return true;
 }
 
+/* Push an ellipsis type onto the type stack.  */
+
+static boolean
+pr_ellipsis_type (p)
+     PTR p;
+{
+  struct pr_handle *info = (struct pr_handle *) p;
+
+  return push_type (info, "...");
+}
+
 /* Push an empty type onto the type stack.  */
 
 static boolean
@@ -563,9 +578,13 @@ pr_pointer_type (p)
      PTR p;
 {
   struct pr_handle *info = (struct pr_handle *) p;
+  char *s;
 
   assert (info->stack != NULL);
 
+  s = strchr (info->stack->type, '|');
+  if (s != NULL && s[1] == '[')
+    return substitute_type (info, "(*|)");
   return substitute_type (info, "*|");
 }
 
@@ -838,9 +857,10 @@ pr_volatile_type (p)
 /* Start accumulating a struct type.  */
 
 static boolean
-pr_start_struct_type (p, tag, structp, size)
+pr_start_struct_type (p, tag, id, structp, size)
      PTR p;
      const char *tag;
+     unsigned int id;
      boolean structp;
      unsigned int size;
 {
@@ -853,14 +873,22 @@ pr_start_struct_type (p, tag, structp, size)
     return false;
   if (tag != NULL)
     {
-      if (! append_type (info, tag)
-         || ! append_type (info, " "))
+      if (! append_type (info, tag))
+       return false;
+    }
+  else
+    {
+      char idbuf[20];
+
+      sprintf (idbuf, "%%anon%u", id);
+      if (! append_type (info, idbuf))
        return false;
     }
+
   if (size != 0)
-    sprintf (ab, "{ /* size %u */\n", size);
+    sprintf (ab, " { /* size %u */\n", size);
   else
-    strcpy (ab, "{\n");
+    strcpy (ab, " {\n");
   if (! append_type (info, ab))
     return false;
   info->stack->visibility = DEBUG_VISIBILITY_PUBLIC;
@@ -875,16 +903,15 @@ pr_fix_visibility (info, visibility)
      enum debug_visibility visibility;
 {
   const char *s;
-  struct pr_stack *top;
   char *t;
   unsigned int len;
 
-  assert (info->stack != NULL && info->stack->next != NULL);
+  assert (info->stack != NULL);
 
-  if (info->stack->next->visibility == visibility)
+  if (info->stack->visibility == visibility)
     return true;
 
-  assert (info->stack->next->visibility != DEBUG_VISIBILITY_IGNORE);
+  assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE);
 
   switch (visibility)
     {
@@ -903,12 +930,7 @@ pr_fix_visibility (info, visibility)
     }
 
   /* Trim off a trailing space in the struct string, to make the
-     output look a bit better, then stick on the visibility string.
-     Pop the stack temporarily to make the string manipulation
-     simpler.  */
-
-  top = info->stack;
-  info->stack = top->next;
+     output look a bit better, then stick on the visibility string.  */
 
   t = info->stack->type;
   len = strlen (t);
@@ -922,8 +944,6 @@ pr_fix_visibility (info, visibility)
 
   info->stack->visibility = visibility;
 
-  info->stack = top;
-
   return true;
 }
 
@@ -939,9 +959,7 @@ pr_struct_field (p, name, bitpos, bitsize, visibility)
 {
   struct pr_handle *info = (struct pr_handle *) p;
   char ab[20];
-
-  if (! pr_fix_visibility (info, visibility))
-    return false;
+  char *t;
 
   if (! substitute_type (info, name))
     return false;
@@ -965,7 +983,14 @@ pr_struct_field (p, name, bitpos, bitsize, visibility)
       || ! indent_type (info))
     return false;
 
-  return append_type (info, pop_type (info));
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  if (! pr_fix_visibility (info, visibility))
+    return false;
+
+  return append_type (info, t);
 }
 
 /* Finish a struct type.  */
@@ -995,9 +1020,10 @@ pr_end_struct_type (p)
 /* Start a class type.  */
 
 static boolean
-pr_start_class_type (p, tag, structp, size, vptr, ownvptr)
+pr_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
      PTR p;
      const char *tag;
+     unsigned int id;
      boolean structp;
      unsigned int size;
      boolean vptr;
@@ -1019,11 +1045,19 @@ pr_start_class_type (p, tag, structp, size, vptr, ownvptr)
     return false;
   if (tag != NULL)
     {
-      if (! append_type (info, tag)
-         || ! append_type (info, " "))
+      if (! append_type (info, tag))
        return false;
     }
-  if (! append_type (info, "{"))
+  else
+    {
+      char idbuf[20];
+
+      sprintf (idbuf, "%%anon%u", id);
+      if (! append_type (info, idbuf))
+       return false;
+    }
+
+  if (! append_type (info, " {"))
     return false;
   if (size != 0 || vptr || ownvptr)
     {
@@ -1077,19 +1111,26 @@ pr_class_static_member (p, name, physname, visibility)
      enum debug_visibility visibility;
 {
   struct pr_handle *info = (struct pr_handle *) p;
+  char *t;
 
-  if (! pr_fix_visibility (info, visibility))
+  if (! substitute_type (info, name))
     return false;
 
-  if (! substitute_type (info, name))
+  if (! prepend_type (info, "static ")
+      || ! append_type (info, "; /* ")
+      || ! append_type (info, physname)
+      || ! append_type (info, " */\n")
+      || ! indent_type (info))
     return false;
 
-  return (prepend_type (info, "static ")
-         && append_type (info, "; /* physname ")
-         && append_type (info, physname)
-         && append_type (info, " */\n")
-         && indent_type (info)
-         && append_type (info, pop_type (info)));
+  t = pop_type (info);
+  if (t == NULL)
+    return false;
+
+  if (! pr_fix_visibility (info, visibility))
+    return false;
+
+  return append_type (info, t);
 }
 
 /* Add a base class to a class.  */
@@ -1200,8 +1241,7 @@ pr_class_start_method (p, name)
 {
   struct pr_handle *info = (struct pr_handle *) p;
 
-  if (! push_type (info, ""))
-    return false;
+  assert (info->stack != NULL);
   info->stack->method = name;
   return true;
 }
@@ -1209,10 +1249,10 @@ pr_class_start_method (p, name)
 /* Add a variant to a method.  */
 
 static boolean
-pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset,
+pr_class_method_variant (p, physname, visibility, constp, volatilep, voffset,
                         context)
      PTR p;
-     const char *argtypes;
+     const char *physname;
      enum debug_visibility visibility;
      boolean constp;
      boolean volatilep;
@@ -1229,12 +1269,12 @@ pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset,
   /* Put the const and volatile qualifiers on the type.  */
   if (volatilep)
     {
-      if (! prepend_type (info, "volatile "))
+      if (! append_type (info, " volatile"))
        return false;
     }
   if (constp)
     {
-      if (! prepend_type (info, "const "))
+      if (! append_type (info, " const"))
        return false;
     }
 
@@ -1260,15 +1300,15 @@ pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset,
        return false;
     }
 
-  /* Now the top of the stack is the holder for the method, and the
-     second element on the stack is the class.  */
+  /* Now the top of the stack is the class.  */
 
   if (! pr_fix_visibility (info, visibility))
     return false;
 
   if (! append_type (info, method_type)
       || ! append_type (info, " /* ")
-      || ! append_type (info, argtypes))
+      || ! append_type (info, physname)
+      || ! append_type (info, " "))
     return false;
   if (context || voffset != 0)
     {
@@ -1294,9 +1334,9 @@ pr_class_method_variant (p, argtypes, visibility, constp, volatilep, voffset,
 /* Add a static variant to a method.  */
 
 static boolean
-pr_class_static_method_variant (p, argtypes, visibility, constp, volatilep)
+pr_class_static_method_variant (p, physname, visibility, constp, volatilep)
      PTR p;
-     const char *argtypes;
+     const char *physname;
      enum debug_visibility visibility;
      boolean constp;
      boolean volatilep;
@@ -1311,12 +1351,12 @@ pr_class_static_method_variant (p, argtypes, visibility, constp, volatilep)
   /* Put the const and volatile qualifiers on the type.  */
   if (volatilep)
     {
-      if (! prepend_type (info, "volatile "))
+      if (! append_type (info, " volatile"))
        return false;
     }
   if (constp)
     {
-      if (! prepend_type (info, "const "))
+      if (! append_type (info, " const"))
        return false;
     }
 
@@ -1333,15 +1373,14 @@ pr_class_static_method_variant (p, argtypes, visibility, constp, volatilep)
   if (method_type == NULL)
     return false;
 
-  /* Now the top of the stack is the holder for the method, and the
-     second element on the stack is the class.  */
+  /* Now the top of the stack is the class.  */
 
   if (! pr_fix_visibility (info, visibility))
     return false;
 
   return (append_type (info, method_type)
          && append_type (info, " /* ")
-         && append_type (info, argtypes)
+         && append_type (info, physname)
          && append_type (info, " */;\n")
          && indent_type (info));
 }
@@ -1354,11 +1393,8 @@ pr_class_end_method (p)
 {
   struct pr_handle *info = (struct pr_handle *) p;
 
-  /* The method variants have been appended to the string on top of
-     the stack with the correct indentation.  We just need the append
-     the string on top of the stack to the class string that is second
-     on the stack.  */
-  return append_type (info, pop_type (info));
+  info->stack->method = NULL;
+  return true;
 }
 
 /* Finish up a class.  */
@@ -1385,13 +1421,15 @@ pr_typedef_type (p, name)
 /* Push a type on the stack using a tag name.  */
 
 static boolean
-pr_tag_type (p, name, kind)
+pr_tag_type (p, name, id, kind)
      PTR p;
      const char *name;
+     unsigned int id;
      enum debug_type_kind kind;
 {
   struct pr_handle *info = (struct pr_handle *) p;
-  const char *t;
+  const char *t, *tag;
+  char idbuf[20];
 
   switch (kind)
     {
@@ -1415,8 +1453,17 @@ pr_tag_type (p, name, kind)
       return false;
     }
 
-  return (push_type (info, t)
-         && append_type (info, name));
+  if (! push_type (info, t))
+    return false;
+  if (name != NULL)
+    tag = name;
+  else
+    {
+      sprintf (idbuf, "%%anon%u", id);
+      tag = idbuf;
+    }
+
+  return append_type (info, tag);
 }
 
 /* Output a typedef.  */