gdb/ChangeLog:
authorJoel Brobecker <brobecker@gnat.com>
Tue, 12 Jan 2010 05:49:00 +0000 (05:49 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Tue, 12 Jan 2010 05:49:00 +0000 (05:49 +0000)
        Add support for DW_AT_GNAT_descriptive_type.
        * gdbtypes.h (enum type_specific_kind): New enum.
        (struct main_type) [type_specific_field]: New component.
        [type_specific]: Add new component "gnat_stuff".
        (struct gnat_aux_type): New type.
        (INIT_CPLUS_SPECIFIC): Also set TYPE_SPECIFIC_FIELD (type).
        (HAVE_CPLUS_STRUCT): Also check TYPE_SPECIFIC_FIELD (type).
        (gnat_aux_default, allocate_gnat_aux_type): Add declaration.
        (INIT_GNAT_SPECIFIC, ALLOCATE_GNAT_AUX_TYPE, HAVE_GNAT_AUX_INFO)
        (TYPE_SPECIFIC_FIELD): New macros.
        (TYPE_CPLUS_SPECIFIC): Return cplus_struct_default if the given
        type does not hold any cplus-specific data.
        (TYPE_RAW_CPLUS_SPECIFIC): New macro.
        (TYPE_GNAT_SPECIFIC, TYPE_DESCRIPTIVE_TYPE): New macros.
        (TYPE_IS_OPAQUE): Use HAVE_CPLUS_STRUCT to check if type has
        cplus-specific data.
        * gdbtypes.c (allocate_cplus_struct_type): Minor stylistic rewrite.
        Set new component TYPE_SPECIFIC_FIELD (type).
        (gnat_aux_default): New constant.
        (allocate_gnat_aux_type): New function.
        (init_type): Add initialization the type-specific stuff for
        TYPE_CODE_FLT and TYPE_CODE_FUNC types.
        (print_gnat_stuff): New function.
        (recursive_dump_type): Use HAVE_CPLUS_STRUCT to check for cplus-
        specific data.  Adjust code that prints the contents of the
        type-specific union using the TYPE_SPECIFIC_FIELD value.
        * dwarf2read.c (dwarf2_attach_fields_to_type): Do not allocate
        the type cplus stuff for Ada types.
        (dwarf2_add_member_fn, dwarf2_attach_fn_fields_to_type):
        Error out if these routines are called with an Ada type.
        (read_structure_type, read_array_type, read_subrange_type):
        Add call to set_descriptive_type.
        (set_die_type): Initialize the gnat-specific data if necessary.
        (need_gnat_info, die_descriptive_type, set_descriptive_type):
        New functions.
        * ada-lang.c (decode_constrained_packed_array_type): Use
        decode_constrained_packed_array_type instead of doing a standard
        lookup to locate a parallel type.
        (find_parallel_type_by_descriptive_type): New function.
        (ada_find_parallel_type_with_name): New function.
        (ada_find_parallel_type): Reimplement using
        ada_find_parallel_type_with_name.
        * ada-valprint.c (print_field_values): Use HAVE_CPLUS_STRUCT
        to check if type has a cplus stuff.
        * linespec.c (total_number_of_methods): Likewise.
        * mdebugread.c (new_type): Likewise.

gdb/testsuite/ChangeLog:

        * gdb.base/maint.exp: Adjust the expected output for the
        "maint print type" test. Use gdb_test_multiple instead of
        gdb_sent/gdb_expect.

gdb/ChangeLog
gdb/ada-lang.c
gdb/ada-valprint.c
gdb/dwarf2read.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/linespec.c
gdb/mdebugread.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/maint.exp

index 7eb239160ee4faa1852b5b757379175c97ba318a..55b3ea42a360db2e97c06510df0fcd26069c797f 100644 (file)
@@ -1,3 +1,52 @@
+2010-01-12  Joel Brobecker  <brobecker@adacore.com>
+
+       Add support for DW_AT_GNAT_descriptive_type.
+       * gdbtypes.h (enum type_specific_kind): New enum.
+       (struct main_type) [type_specific_field]: New component.
+       [type_specific]: Add new component "gnat_stuff".
+       (struct gnat_aux_type): New type.
+       (INIT_CPLUS_SPECIFIC): Also set TYPE_SPECIFIC_FIELD (type).
+       (HAVE_CPLUS_STRUCT): Also check TYPE_SPECIFIC_FIELD (type).
+       (gnat_aux_default, allocate_gnat_aux_type): Add declaration.
+       (INIT_GNAT_SPECIFIC, ALLOCATE_GNAT_AUX_TYPE, HAVE_GNAT_AUX_INFO)
+       (TYPE_SPECIFIC_FIELD): New macros.
+       (TYPE_CPLUS_SPECIFIC): Return cplus_struct_default if the given
+       type does not hold any cplus-specific data.
+       (TYPE_RAW_CPLUS_SPECIFIC): New macro.
+       (TYPE_GNAT_SPECIFIC, TYPE_DESCRIPTIVE_TYPE): New macros.
+       (TYPE_IS_OPAQUE): Use HAVE_CPLUS_STRUCT to check if type has
+       cplus-specific data.
+       * gdbtypes.c (allocate_cplus_struct_type): Minor stylistic rewrite.
+       Set new component TYPE_SPECIFIC_FIELD (type).
+       (gnat_aux_default): New constant.
+       (allocate_gnat_aux_type): New function.
+       (init_type): Add initialization the type-specific stuff for
+       TYPE_CODE_FLT and TYPE_CODE_FUNC types.
+       (print_gnat_stuff): New function.
+       (recursive_dump_type): Use HAVE_CPLUS_STRUCT to check for cplus-
+       specific data.  Adjust code that prints the contents of the
+       type-specific union using the TYPE_SPECIFIC_FIELD value.
+       * dwarf2read.c (dwarf2_attach_fields_to_type): Do not allocate
+       the type cplus stuff for Ada types.
+       (dwarf2_add_member_fn, dwarf2_attach_fn_fields_to_type):
+       Error out if these routines are called with an Ada type.
+       (read_structure_type, read_array_type, read_subrange_type):
+       Add call to set_descriptive_type.
+       (set_die_type): Initialize the gnat-specific data if necessary.
+       (need_gnat_info, die_descriptive_type, set_descriptive_type):
+       New functions.
+       * ada-lang.c (decode_constrained_packed_array_type): Use
+       decode_constrained_packed_array_type instead of doing a standard
+       lookup to locate a parallel type.
+       (find_parallel_type_by_descriptive_type): New function.
+       (ada_find_parallel_type_with_name): New function.
+       (ada_find_parallel_type): Reimplement using
+       ada_find_parallel_type_with_name.
+       * ada-valprint.c (print_field_values): Use HAVE_CPLUS_STRUCT
+       to check if type has a cplus stuff.
+       * linespec.c (total_number_of_methods): Likewise.
+       * mdebugread.c (new_type): Likewise.
+
 2010-01-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * NEWS: Document the 0b binary number prefix parsing.
index b101d58bb02e3c8f151ccb881aff2818ef084894..317c8d3ed72e2aa2cb9166d6349c623190418617 100644 (file)
@@ -157,6 +157,9 @@ static struct type *ada_lookup_struct_elt_type (struct type *, char *,
 
 static struct value *evaluate_subexp_type (struct expression *, int *);
 
+static struct type *ada_find_parallel_type_with_name (struct type *,
+                                                      const char *);
+
 static int is_dynamic_field (struct type *, int);
 
 static struct type *to_fixed_variant_branch_type (struct type *,
@@ -1874,13 +1877,13 @@ decode_constrained_packed_array_type (struct type *type)
   memcpy (name, raw_name, tail - raw_name);
   name[tail - raw_name] = '\000';
 
-  sym = standard_lookup (name, get_selected_block (0), VAR_DOMAIN);
-  if (sym == NULL || SYMBOL_TYPE (sym) == NULL)
+  shadow_type = ada_find_parallel_type_with_name (type, name);
+
+  if (shadow_type == NULL)
     {
       lim_warning (_("could not find bounds information on packed array"));
       return NULL;
     }
-  shadow_type = SYMBOL_TYPE (sym);
   CHECK_TYPEDEF (shadow_type);
 
   if (TYPE_CODE (shadow_type) != TYPE_CODE_ARRAY)
@@ -6666,31 +6669,90 @@ ada_type_name (struct type *type)
     return TYPE_TAG_NAME (type);
 }
 
-/* Find a parallel type to TYPE whose name is formed by appending
+/* Search the list of "descriptive" types associated to TYPE for a type
+   whose name is NAME.  */
+
+static struct type *
+find_parallel_type_by_descriptive_type (struct type *type, const char *name)
+{
+  struct type *result;
+
+  /* If there no descriptive-type info, then there is no parallel type
+     to be found.  */
+  if (!HAVE_GNAT_AUX_INFO (type))
+    return NULL;
+
+  result = TYPE_DESCRIPTIVE_TYPE (type);
+  while (result != NULL)
+    {
+      char *result_name = ada_type_name (result);
+
+      if (result_name == NULL)
+        {
+          warning (_("unexpected null name on descriptive type"));
+          return NULL;
+        }
+
+      /* If the names match, stop.  */
+      if (strcmp (result_name, name) == 0)
+       break;
+
+      /* Otherwise, look at the next item on the list, if any.  */
+      if (HAVE_GNAT_AUX_INFO (result))
+       result = TYPE_DESCRIPTIVE_TYPE (result);
+      else
+       result = NULL;
+    }
+
+  /* If we didn't find a match, see whether this is a packed array.  With
+     older compilers, the descriptive type information is either absent or
+     irrelevant when it comes to packed arrays so the above lookup fails.
+     Fall back to using a parallel lookup by name in this case.  */
+  if (result == NULL && ada_is_packed_array_type (type))
+    return ada_find_any_type (name);
+
+  return result;
+}
+
+/* Find a parallel type to TYPE with the specified NAME, using the
+   descriptive type taken from the debugging information, if available,
+   and otherwise using the (slower) name-based method.  */
+
+static struct type *
+ada_find_parallel_type_with_name (struct type *type, const char *name)
+{
+  struct type *result = NULL;
+
+  if (HAVE_GNAT_AUX_INFO (type))
+    result = find_parallel_type_by_descriptive_type (type, name);
+  else
+    result = ada_find_any_type (name);
+
+  return result;
+}
+
+/* Same as above, but specify the name of the parallel type by appending
    SUFFIX to the name of TYPE.  */
 
 struct type *
 ada_find_parallel_type (struct type *type, const char *suffix)
 {
-  static char *name;
-  static size_t name_len = 0;
+  char *name, *typename = ada_type_name (type);
   int len;
-  char *typename = ada_type_name (type);
 
   if (typename == NULL)
     return NULL;
 
   len = strlen (typename);
 
-  GROW_VECT (name, name_len, len + strlen (suffix) + 1);
+  name = (char *) alloca (len + strlen (suffix) + 1);
 
   strcpy (name, typename);
   strcpy (name + len, suffix);
 
-  return ada_find_any_type (name);
+  return ada_find_parallel_type_with_name (type, name);
 }
 
-
 /* If TYPE is a variable-size record type, return the corresponding template
    type describing its fields.  Otherwise, return NULL.  */
 
index 4f644b845a612589ce611420be97ae3d0eaaa43d..1c8bfc639cd8ad1ae76281b42e8b5914d348168d 100644 (file)
@@ -1077,8 +1077,7 @@ print_field_values (struct type *type, const gdb_byte *valaddr,
 
          /* Bitfields require special handling, especially due to byte
             order problems.  */
-         if (TYPE_CPLUS_SPECIFIC (type) != NULL
-             && TYPE_FIELD_IGNORE (type, i))
+         if (HAVE_CPLUS_STRUCT (type) && TYPE_FIELD_IGNORE (type, i))
            {
              fputs_filtered (_("<optimized out or zero length>"), stream);
            }
index 7623035a5332bc0f98b755a31d149f91911da1cf..243859c568c91b42f1f07f8734b9843373d74aae 100644 (file)
@@ -926,6 +926,13 @@ static void dwarf2_const_value_data (struct attribute *attr,
 
 static struct type *die_type (struct die_info *, struct dwarf2_cu *);
 
+static int need_gnat_info (struct dwarf2_cu *);
+
+static struct type *die_descriptive_type (struct die_info *, struct dwarf2_cu *);
+
+static void set_descriptive_type (struct type *, struct die_info *,
+                                 struct dwarf2_cu *);
+
 static struct type *die_containing_type (struct die_info *,
                                         struct dwarf2_cu *);
 
@@ -4564,7 +4571,7 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
     TYPE_ALLOC (type, sizeof (struct field) * nfields);
   memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
 
-  if (fip->non_public_fields)
+  if (fip->non_public_fields && cu->language != language_ada)
     {
       ALLOCATE_CPLUS_STRUCT_TYPE (type);
 
@@ -4583,7 +4590,7 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
 
   /* If the type has baseclasses, allocate and clear a bit vector for
      TYPE_FIELD_VIRTUAL_BITS.  */
-  if (fip->nbaseclasses)
+  if (fip->nbaseclasses && cu->language != language_ada)
     {
       int num_bytes = B_BYTES (fip->nbaseclasses);
       unsigned char *pointer;
@@ -4617,11 +4624,13 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
       switch (fieldp->accessibility)
        {
        case DW_ACCESS_private:
-         SET_TYPE_FIELD_PRIVATE (type, nfields);
+         if (cu->language != language_ada)
+           SET_TYPE_FIELD_PRIVATE (type, nfields);
          break;
 
        case DW_ACCESS_protected:
-         SET_TYPE_FIELD_PROTECTED (type, nfields);
+         if (cu->language != language_ada)
+           SET_TYPE_FIELD_PROTECTED (type, nfields);
          break;
 
        case DW_ACCESS_public:
@@ -4641,6 +4650,8 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
            {
            case DW_VIRTUALITY_virtual:
            case DW_VIRTUALITY_pure_virtual:
+             if (cu->language == language_ada)
+               error ("unexpected virtuality in component of Ada type");
              SET_TYPE_FIELD_VIRTUAL (type, nfields);
              break;
            }
@@ -4664,6 +4675,9 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
   struct nextfnfield *new_fnfield;
   struct type *this_type;
 
+  if (cu->language == language_ada)
+    error ("unexpected member function in Ada type");
+
   /* Get name of member function.  */
   fieldname = dwarf2_name (die, cu);
   if (fieldname == NULL)
@@ -4837,6 +4851,9 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
   int total_length = 0;
   int i;
 
+  if (cu->language == language_ada)
+    error ("unexpected member functions in Ada type");
+
   ALLOCATE_CPLUS_STRUCT_TYPE (type);
   TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
     TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
@@ -5038,6 +5055,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   if (die_is_declaration (die, cu))
     TYPE_STUB (type) = 1;
 
+  set_descriptive_type (type, die, cu);
+
   /* We need to add the type field to the die immediately so we don't
      infinitely recurse when dealing with pointers to the structure
      type within the structure itself. */
@@ -5451,6 +5470,8 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name)
     TYPE_NAME (type) = name;
   
+  set_descriptive_type (type, die, cu);
+
   do_cleanups (back_to);
 
   /* Install the type in the die. */
@@ -6113,6 +6134,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   if (attr)
     TYPE_LENGTH (range_type) = DW_UNSND (attr);
 
+  set_descriptive_type (range_type, die, cu);
+
   return set_die_type (die, range_type, cu);
 }
   
@@ -8768,6 +8791,67 @@ die_type (struct die_info *die, struct dwarf2_cu *cu)
   return type;
 }
 
+/* True iff CU's producer generates GNAT Ada auxiliary information
+   that allows to find parallel types through that information instead
+   of having to do expensive parallel lookups by type name.  */
+
+static int
+need_gnat_info (struct dwarf2_cu *cu)
+{
+  /* FIXME: brobecker/2010-10-12: As of now, only the AdaCore version
+     of GNAT produces this auxiliary information, without any indication
+     that it is produced.  Part of enhancing the FSF version of GNAT
+     to produce that information will be to put in place an indicator
+     that we can use in order to determine whether the descriptive type
+     info is available or not.  One suggestion that has been made is
+     to use a new attribute, attached to the CU die.  For now, assume
+     that the descriptive type info is not available.  */
+  return 0;
+}
+
+
+/* Return the auxiliary type of the die in question using its
+   DW_AT_GNAT_descriptive_type attribute.  Returns NULL if the
+   attribute is not present.  */
+
+static struct type *
+die_descriptive_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct type *type;
+  struct attribute *type_attr;
+  struct die_info *type_die;
+
+  type_attr = dwarf2_attr (die, DW_AT_GNAT_descriptive_type, cu);
+  if (!type_attr)
+    return NULL;
+
+  type_die = follow_die_ref (die, type_attr, &cu);
+  type = tag_type_to_type (type_die, cu);
+  if (!type)
+    {
+      dump_die_for_error (type_die);
+      error (_("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]"),
+                     cu->objfile->name);
+    }
+  return type;
+}
+
+/* If DIE has a descriptive_type attribute, then set the TYPE's
+   descriptive type accordingly.  */
+
+static void
+set_descriptive_type (struct type *type, struct die_info *die,
+                     struct dwarf2_cu *cu)
+{
+  struct type *descriptive_type = die_descriptive_type (die, cu);
+
+  if (descriptive_type)
+    {
+      ALLOCATE_GNAT_AUX_TYPE (type);
+      TYPE_DESCRIPTIVE_TYPE (type) = descriptive_type;
+    }
+}
+
 /* Return the containing type of the die in question using its
    DW_AT_containing_type attribute.  */
 
@@ -11724,6 +11808,19 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 {
   struct dwarf2_offset_and_type **slot, ofs;
 
+  /* For Ada types, make sure that the gnat-specific data is always
+     initialized (if not already set).  There are a few types where
+     we should not be doing so, because the type-specific area is
+     already used to hold some other piece of info (eg: TYPE_CODE_FLT
+     where the type-specific area is used to store the floatformat).
+     But this is not a problem, because the gnat-specific information
+     is actually not needed for these types.  */
+  if (need_gnat_info (cu)
+      && TYPE_CODE (type) != TYPE_CODE_FUNC
+      && TYPE_CODE (type) != TYPE_CODE_FLT
+      && !HAVE_GNAT_AUX_INFO (type))
+    INIT_GNAT_SPECIFIC (type);
+
   if (cu->type_hash == NULL)
     {
       gdb_assert (cu->per_cu != NULL);
index 255f04a6056150105b13cf3a2e2f67e5eeaa5888..6a01aeb7368003f33f2a962f1b0f1a637f9996fb 100644 (file)
@@ -1717,14 +1717,32 @@ const struct cplus_struct_type cplus_struct_default;
 void
 allocate_cplus_struct_type (struct type *type)
 {
-  if (!HAVE_CPLUS_STRUCT (type))
-    {
-      TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
-       TYPE_ALLOC (type, sizeof (struct cplus_struct_type));
-      *(TYPE_CPLUS_SPECIFIC (type)) = cplus_struct_default;
-    }
+  if (HAVE_CPLUS_STRUCT (type))
+    /* Structure was already allocated.  Nothing more to do.  */
+    return;
+
+  TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_CPLUS_STUFF;
+  TYPE_RAW_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
+    TYPE_ALLOC (type, sizeof (struct cplus_struct_type));
+  *(TYPE_RAW_CPLUS_SPECIFIC (type)) = cplus_struct_default;
 }
 
+const struct gnat_aux_type gnat_aux_default =
+  { NULL };
+
+/* Set the TYPE's type-specific kind to TYPE_SPECIFIC_GNAT_STUFF,
+   and allocate the associated gnat-specific data.  The gnat-specific
+   data is also initialized to gnat_aux_default.  */
+void
+allocate_gnat_aux_type (struct type *type)
+{
+  TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_GNAT_STUFF;
+  TYPE_GNAT_SPECIFIC (type) = (struct gnat_aux_type *)
+    TYPE_ALLOC (type, sizeof (struct gnat_aux_type));
+  *(TYPE_GNAT_SPECIFIC (type)) = gnat_aux_default;
+}
+
+
 /* Helper function to initialize the standard scalar types.
 
    If NAME is non-NULL, then we make a copy of the string pointed
@@ -1777,10 +1795,19 @@ init_type (enum type_code code, int length, int flags,
   if (name && strcmp (name, "char") == 0)
     TYPE_NOSIGN (type) = 1;
 
-  if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION
-      || code == TYPE_CODE_NAMESPACE)
+  switch (code)
     {
-      INIT_CPLUS_SPECIFIC (type);
+      case TYPE_CODE_STRUCT:
+      case TYPE_CODE_UNION:
+      case TYPE_CODE_NAMESPACE:
+        INIT_CPLUS_SPECIFIC (type);
+        break;
+      case TYPE_CODE_FLT:
+        TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_FLOATFORMAT;
+        break;
+      case TYPE_CODE_FUNC:
+        TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_CALLING_CONVENTION;
+        break;
     }
   return type;
 }
@@ -2495,6 +2522,17 @@ print_cplus_stuff (struct type *type, int spaces)
     }
 }
 
+/* Print the contents of the TYPE's type_specific union, assuming that
+   its type-specific kind is TYPE_SPECIFIC_GNAT_STUFF.  */
+
+static void
+print_gnat_stuff (struct type *type, int spaces)
+{
+  struct type *descriptive_type = TYPE_DESCRIPTIVE_TYPE (type);
+
+  recursive_dump_type (descriptive_type, spaces + 2);
+}
+
 static struct obstack dont_print_type_obstack;
 
 void
@@ -2506,7 +2544,7 @@ recursive_dump_type (struct type *type, int spaces)
     obstack_begin (&dont_print_type_obstack, 0);
 
   if (TYPE_NFIELDS (type) > 0
-      || (TYPE_CPLUS_SPECIFIC (type) && TYPE_NFN_FIELDS (type) > 0))
+      || (HAVE_CPLUS_STRUCT (type) && TYPE_NFN_FIELDS (type) > 0))
     {
       struct type **first_dont_print
        = (struct type **) obstack_base (&dont_print_type_obstack);
@@ -2775,55 +2813,55 @@ recursive_dump_type (struct type *type, int spaces)
     }
   printfi_filtered (spaces, "vptr_fieldno %d\n", 
                    TYPE_VPTR_FIELDNO (type));
-  switch (TYPE_CODE (type))
-    {
-    case TYPE_CODE_STRUCT:
-      printfi_filtered (spaces, "cplus_stuff ");
-      gdb_print_host_address (TYPE_CPLUS_SPECIFIC (type), 
-                             gdb_stdout);
-      puts_filtered ("\n");
-      print_cplus_stuff (type, spaces);
-      break;
 
-    case TYPE_CODE_FLT:
-      printfi_filtered (spaces, "floatformat ");
-      if (TYPE_FLOATFORMAT (type) == NULL)
-       puts_filtered ("(null)");
-      else
-       {
-         puts_filtered ("{ ");
-         if (TYPE_FLOATFORMAT (type)[0] == NULL
-             || TYPE_FLOATFORMAT (type)[0]->name == NULL)
-           puts_filtered ("(null)");
-         else
-           puts_filtered (TYPE_FLOATFORMAT (type)[0]->name);
-
-         puts_filtered (", ");
-         if (TYPE_FLOATFORMAT (type)[1] == NULL
-             || TYPE_FLOATFORMAT (type)[1]->name == NULL)
-           puts_filtered ("(null)");
-         else
-           puts_filtered (TYPE_FLOATFORMAT (type)[1]->name);
+  switch (TYPE_SPECIFIC_FIELD (type))
+    {
+      case TYPE_SPECIFIC_CPLUS_STUFF:
+       printfi_filtered (spaces, "cplus_stuff ");
+       gdb_print_host_address (TYPE_CPLUS_SPECIFIC (type), 
+                               gdb_stdout);
+       puts_filtered ("\n");
+       print_cplus_stuff (type, spaces);
+       break;
 
-         puts_filtered (" }");
-       }
-      puts_filtered ("\n");
-      break;
+      case TYPE_SPECIFIC_GNAT_STUFF:
+       printfi_filtered (spaces, "gnat_stuff ");
+       gdb_print_host_address (TYPE_GNAT_SPECIFIC (type), gdb_stdout);
+       puts_filtered ("\n");
+       print_gnat_stuff (type, spaces);
+       break;
 
-    default:
-      /* 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 ");
-      gdb_print_host_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
-      if (TYPE_CPLUS_SPECIFIC (type) != NULL)
-       {
-         printf_filtered (_(" (unknown data form)"));
-       }
-      printf_filtered ("\n");
-      break;
+      case TYPE_SPECIFIC_FLOATFORMAT:
+       printfi_filtered (spaces, "floatformat ");
+       if (TYPE_FLOATFORMAT (type) == NULL)
+         puts_filtered ("(null)");
+       else
+         {
+           puts_filtered ("{ ");
+           if (TYPE_FLOATFORMAT (type)[0] == NULL
+               || TYPE_FLOATFORMAT (type)[0]->name == NULL)
+             puts_filtered ("(null)");
+           else
+             puts_filtered (TYPE_FLOATFORMAT (type)[0]->name);
+
+           puts_filtered (", ");
+           if (TYPE_FLOATFORMAT (type)[1] == NULL
+               || TYPE_FLOATFORMAT (type)[1]->name == NULL)
+             puts_filtered ("(null)");
+           else
+             puts_filtered (TYPE_FLOATFORMAT (type)[1]->name);
+
+           puts_filtered (" }");
+         }
+       puts_filtered ("\n");
+       break;
 
+      case TYPE_SPECIFIC_CALLING_CONVENTION:
+       printfi_filtered (spaces, "calling_convention %d\n",
+                          TYPE_CALLING_CONVENTION (type));
+       break;
     }
+
   if (spaces == 0)
     obstack_free (&dont_print_type_obstack, NULL);
 }
index 7ef0b1d306747883761723f86bb7574a90221761..f329b1e94cda3ced4d83df353624335e405cec69 100644 (file)
@@ -340,6 +340,26 @@ enum field_loc_kind
     FIELD_LOC_KIND_DWARF_BLOCK /* dwarf_block */
   };
 
+/* A discriminant to determine which field in the main_type.type_specific
+   union is being used, if any.
+
+   For types such as TYPE_CODE_FLT or TYPE_CODE_FUNC, the use of this
+   discriminant is really redundant, as we know from the type code
+   which field is going to be used.  As such, it would be possible to
+   reduce the size of this enum in order to save a bit or two for
+   other fields of struct main_type.  But, since we still have extra
+   room , and for the sake of clarity and consistency, we treat all fields
+   of the union the same way.  */
+
+enum type_specific_kind
+{
+  TYPE_SPECIFIC_NONE,
+  TYPE_SPECIFIC_CPLUS_STUFF,
+  TYPE_SPECIFIC_GNAT_STUFF,
+  TYPE_SPECIFIC_FLOATFORMAT,
+  TYPE_SPECIFIC_CALLING_CONVENTION
+};
+
 /* This structure is space-critical.
    Its layout has been tweaked to reduce the space used.  */
 
@@ -367,6 +387,10 @@ struct main_type
   unsigned int flag_fixed_instance : 1;
   unsigned int flag_objfile_owned : 1;
 
+  /* A discriminant telling us which field of the type_specific union
+     is being used for this type, if any.  */
+  ENUM_BITFIELD(type_specific_kind) type_specific_field : 3;
+
   /* Number of fields described for this type.  This field appears at
      this location because it packs nicely here.  */
 
@@ -554,6 +578,10 @@ struct main_type
 
     struct cplus_struct_type *cplus_stuff;
 
+    /* GNAT_STUFF is for types for which the GNAT Ada compiler
+       provides additional information.  */
+    struct gnat_aux_type *gnat_stuff;
+
     /* FLOATFORMAT is for TYPE_CODE_FLT.  It is a pointer to two
        floatformat objects that describe the floating-point value
        that resides within the type.  The first is for big endian
@@ -825,6 +853,15 @@ struct badness_vector
     int *rank;
   };
 
+/* GNAT Ada-specific information for various Ada types.  */
+struct gnat_aux_type
+  {
+    /* Parallel type used to encode information about dynamic types
+       used in Ada (such as variant records, variable-size array,
+       etc).  */
+    struct type* descriptive_type;
+  };
+
 /* The default value of TYPE_CPLUS_SPECIFIC(T) points to the
    this shared static structure. */
 
@@ -833,10 +870,27 @@ extern const struct cplus_struct_type cplus_struct_default;
 extern void allocate_cplus_struct_type (struct type *);
 
 #define INIT_CPLUS_SPECIFIC(type) \
-  (TYPE_CPLUS_SPECIFIC(type)=(struct cplus_struct_type*)&cplus_struct_default)
+  (TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_CPLUS_STUFF, \
+   TYPE_RAW_CPLUS_SPECIFIC (type) = (struct cplus_struct_type*) &cplus_struct_default)
+
 #define ALLOCATE_CPLUS_STRUCT_TYPE(type) allocate_cplus_struct_type (type)
+
 #define HAVE_CPLUS_STRUCT(type) \
-  (TYPE_CPLUS_SPECIFIC(type) != &cplus_struct_default)
+  (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_CPLUS_STUFF \
+   && TYPE_RAW_CPLUS_SPECIFIC (type) !=  &cplus_struct_default)
+
+extern const struct gnat_aux_type gnat_aux_default;
+
+extern void allocate_gnat_aux_type (struct type *);
+
+#define INIT_GNAT_SPECIFIC(type) \
+  (TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_GNAT_STUFF, \
+   TYPE_GNAT_SPECIFIC (type) = (struct gnat_aux_type *) &gnat_aux_default)
+#define ALLOCATE_GNAT_AUX_TYPE(type) allocate_gnat_aux_type (type)
+/* A macro that returns non-zero if the type-specific data should be
+   read as "gnat-stuff".  */
+#define HAVE_GNAT_AUX_INFO(type) \
+  (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_GNAT_STUFF)
 
 #define TYPE_INSTANCE_FLAGS(thistype) (thistype)->instance_flags
 #define TYPE_MAIN_TYPE(thistype) (thistype)->main_type
@@ -890,9 +944,22 @@ extern void allocate_cplus_struct_type (struct type *);
 #define TYPE_NFN_FIELDS_TOTAL(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields_total
 #define TYPE_NTEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->ntemplate_args
 #define TYPE_DECLARED_TYPE(thistype) TYPE_CPLUS_SPECIFIC(thistype)->declared_type
+#define TYPE_SPECIFIC_FIELD(thistype) \
+  TYPE_MAIN_TYPE(thistype)->type_specific_field
 #define        TYPE_TYPE_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific
-#define TYPE_CPLUS_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.cplus_stuff
+/* We need this tap-dance with the TYPE_RAW_SPECIFIC because of the case
+   where we're trying to print an Ada array using the C language.
+   In that case, there is no "cplus_stuff", but the C language assumes
+   that there is.  What we do, in that case, is pretend that there is
+   an implicit one which is the default cplus stuff.  */
+#define TYPE_CPLUS_SPECIFIC(thistype) \
+   (!HAVE_CPLUS_STRUCT(thistype) \
+    ? (struct cplus_struct_type*)&cplus_struct_default \
+    : TYPE_RAW_CPLUS_SPECIFIC(thistype))
+#define TYPE_RAW_CPLUS_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.cplus_stuff
 #define TYPE_FLOATFORMAT(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.floatformat
+#define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
+#define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.calling_convention
 #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
@@ -1004,7 +1071,7 @@ extern void allocate_cplus_struct_type (struct type *);
 #define TYPE_IS_OPAQUE(thistype) (((TYPE_CODE (thistype) == TYPE_CODE_STRUCT) ||        \
                                    (TYPE_CODE (thistype) == TYPE_CODE_UNION))        && \
                                   (TYPE_NFIELDS (thistype) == 0)                     && \
-                                  (TYPE_CPLUS_SPECIFIC (thistype) && (TYPE_NFN_FIELDS (thistype) == 0)) && \
+                                  (HAVE_CPLUS_STRUCT (thistype) && (TYPE_NFN_FIELDS (thistype) == 0)) && \
                                   (TYPE_STUB (thistype) || !TYPE_STUB_SUPPORTED (thistype)))
 
 struct builtin_type
index 138f0d8a3360b31b12cfc456487202f5aeafab3a..74902b6f9d714e872122d7a01baf763cfc4827be 100644 (file)
@@ -186,7 +186,7 @@ total_number_of_methods (struct type *type)
   int count;
 
   CHECK_TYPEDEF (type);
-  if (TYPE_CPLUS_SPECIFIC (type) == NULL)
+  if (! HAVE_CPLUS_STRUCT (type))
     return 0;
   count = TYPE_NFN_FIELDS_TOTAL (type);
 
index fc28637cab34b982e4a14942acf33732d0501da6..28d52a415b90f79993c8a6168a4350b6db281fa9 100644 (file)
@@ -4800,7 +4800,7 @@ new_type (char *name)
 
   t = alloc_type (current_objfile);
   TYPE_NAME (t) = name;
-  TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default;
+  INIT_CPLUS_SPECIFIC (t);
   return t;
 }
 \f
index ae6fda9e6011b5c857f30ee881b7a83d616df98f..789043f9294ed333a81eb830d4b3436ee8b55aad 100644 (file)
@@ -1,3 +1,9 @@
+2010-01-12  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.base/maint.exp: Adjust the expected output for the
+       "maint print type" test. Use gdb_test_multiple instead of
+       gdb_sent/gdb_expect.
+
 2010-01-11  Doug Evans  <dje@google.com>
 
        * lib/gdbserver-support.exp (gdbserver_download_current_prog): Rename
index 45d2a73de6eb51084f55f1191ee4d98339f07155..6cff01339bb3b9ca7d2fe8530fb8b382eda94a93 100644 (file)
@@ -397,13 +397,12 @@ gdb_expect  {
         timeout         { fail "(timeout) maint print symbols" }
         }
 
-send_gdb "maint print type argc\n"
-gdb_expect  {
-        -re "type node $hex\r\nname .int. \\($hex\\)\r\ntagname .<NULL>. \\($hex\\)\r\ncode $hex \\(TYPE_CODE_INT\\)\r\nlength \[24\]\r\nobjfile $hex\r\ntarget_type $hex\r\npointer_type $hex\r\nreference_type $hex\r\ntype_chain $hex\r\ninstance_flags $hex\r\nflags\r\nnfields 0 $hex\r\nvptr_basetype $hex\r\nvptr_fieldno -1\r\ntype_specific $hex\r\n$gdb_prompt $"\
-                        { pass "maint print type" }
-        -re ".*$gdb_prompt $"       { fail "maint print type" }
-        timeout         { fail "(timeout) maint print type" }
-        }
+set msg "maint print type"
+gdb_test_multiple "maint print type argc" $msg {
+    -re "type node $hex\r\nname .int. \\($hex\\)\r\ntagname .<NULL>. \\($hex\\)\r\ncode $hex \\(TYPE_CODE_INT\\)\r\nlength \[24\]\r\nobjfile $hex\r\ntarget_type $hex\r\npointer_type $hex\r\nreference_type $hex\r\ntype_chain $hex\r\ninstance_flags $hex\r\nflags\r\nnfields 0 $hex\r\nvptr_basetype $hex\r\nvptr_fieldno -1\r\n$gdb_prompt $" {
+        pass $msg
+    }
+}
 
 if [istarget "hppa*-*-11*"] {
     setup_xfail hppa*-*-*11* CLLbs14860