commit 6556fbd588fec6a2db1ae98847ddb11df68cd71f Author: Joel Brobecker Date: Tue Sep 29 10:57:00 2009 -0700 include/ * dwarf2.h (enum dwarf_attribute): Add DW_AT_GNAT_descriptive_type. gdb/ 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 holds gnat-specific data and not 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 (lookup_struct_elt_type): Do not use TYPE_N_BASECLASSES if the type does not have an cplus-specific data. (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. diff --git a/include/dwarf2.h b/include/dwarf2.h index 559b82d..4971c41 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -425,6 +425,8 @@ enum dwarf_attribute DW_AT_GNU_template_name = 0x2110, /* VMS extensions. */ DW_AT_VMS_rtnbeg_pd_address = 0x2201, + /* GNAT extensions. */ + DW_AT_GNAT_descriptive_type = 0x2302, /* UPC extension. */ DW_AT_upc_threads_scaled = 0x3210, /* PGI (STMicroelectronics) extensions. */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index b07bd07..69e68cb 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -339,6 +339,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. */ @@ -366,6 +386,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. */ @@ -553,6 +577,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 @@ -824,6 +852,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. */ @@ -832,10 +869,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 @@ -889,9 +943,21 @@ 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 +/* FIXME: 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 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_GNAT_AUX_INFO(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 @@ -1003,7 +1069,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/gdbtypes.c b/gdb/gdbtypes.c index 035f630..7584e0c 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1197,6 +1197,7 @@ struct type * lookup_struct_elt_type (struct type *type, char *name, int noerr) { int i; + int n_base_classes; for (;;) { @@ -1231,7 +1232,11 @@ lookup_struct_elt_type (struct type *type, char *name, int noerr) } #endif - for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) + if (! HAVE_CPLUS_STRUCT (type)) + n_base_classes = 0; + else + n_base_classes = TYPE_N_BASECLASSES (type); + for (i = TYPE_NFIELDS (type) - 1; i >= n_base_classes; i -= 1) { char *t_field_name = TYPE_FIELD_NAME (type, i); @@ -1242,7 +1247,7 @@ lookup_struct_elt_type (struct type *type, char *name, int noerr) } /* OK, it's not in this class. Recursively check the baseclasses. */ - for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--) + for (i = n_base_classes - 1; i >= 0; i--) { struct type *t; @@ -1711,14 +1716,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 @@ -1771,10 +1794,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; } @@ -2489,6 +2521,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 @@ -2500,7 +2543,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); @@ -2769,55 +2812,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/dwarf2read.c b/gdb/dwarf2read.c index ffeaaf2..e0958d2 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); } @@ -8761,6 +8784,61 @@ 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) +{ + /* Assume that the Ada compiler was GNAT, which always produces + the auxiliary information. */ + return (cu->language == language_ada); +} + + +/* 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. */ @@ -11717,6 +11795,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/ada-lang.c b/gdb/ada-lang.c index a80afa4..df0b8b7 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 5fb44b1..f9c182d 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -1092,8 +1092,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/linespec.c b/gdb/linespec.c index 80aa3e1..5f0d674 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 dea7b71..f72fb62 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; }