From b4ba55a1812c4bde23d52111e54d2b72a1ec4af1 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Tue, 12 Jan 2010 05:49:00 +0000 Subject: [PATCH] gdb/ChangeLog: 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 | 49 +++++++++++ gdb/ada-lang.c | 82 ++++++++++++++--- gdb/ada-valprint.c | 3 +- gdb/dwarf2read.c | 105 +++++++++++++++++++++- gdb/gdbtypes.c | 146 +++++++++++++++++++------------ gdb/gdbtypes.h | 75 +++++++++++++++- gdb/linespec.c | 2 +- gdb/mdebugread.c | 2 +- gdb/testsuite/ChangeLog | 6 ++ gdb/testsuite/gdb.base/maint.exp | 13 ++- 10 files changed, 400 insertions(+), 83 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7eb239160ee..55b3ea42a36 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,52 @@ +2010-01-12 Joel Brobecker + + 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 * NEWS: Document the 0b binary number prefix parsing. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index b101d58bb02..317c8d3ed72 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -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. */ diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c index 4f644b845a6..1c8bfc639cd 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -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 (_(""), stream); } diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 7623035a533..243859c568c 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -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); diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 255f04a6056..6a01aeb7368 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -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); } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 7ef0b1d3067..f329b1e94cd 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -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 diff --git a/gdb/linespec.c b/gdb/linespec.c index 138f0d8a336..74902b6f9d7 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -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); diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c index fc28637cab3..28d52a415b9 100644 --- a/gdb/mdebugread.c +++ b/gdb/mdebugread.c @@ -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; } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ae6fda9e601..789043f9294 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-01-12 Joel Brobecker + + * 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 * lib/gdbserver-support.exp (gdbserver_download_current_prog): Rename diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp index 45d2a73de6e..6cff01339bb 100644 --- a/gdb/testsuite/gdb.base/maint.exp +++ b/gdb/testsuite/gdb.base/maint.exp @@ -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 .. \\($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 .. \\($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 -- 2.30.2