Re: [PATCH] Handle DW_TAG_subrange_type

Joel Brobecker
2004-01-14T17:28:11Z

[-- Attachment #1: Type: text/plain, Size: 1627 bytes --]

Hello Helena,

> I agree that the subrange type should be handled in more places, so ok
> with Joel's calls for that.
>
> Almost identical code is in read_array_type. Would it be possible to
> unify that as well into a single function read_subrange_type? I.e. do
> you think that that "else if (attr->form == DW_FORM_block1)" clause
> will interfere with the ADA case? If not and we can unify them, then,
> I'd prefer the version that Andreas has, since it handles the default
> high and low, not as -1, but the same as the original code.

Here is a revised patch, which I hope addresses all your comments.
Tested on x86-linux, using gcc HEAD. No regression.

I should also mention that I am about to send a patch to gcc-patches,
which slightly modifies the dwarf-2 output, and will likely cause GCC
to generate more of these subrange_type DIEs. It is more a cleanup
patch than anything else, but I did verify that GDB together with the
attached patch handle the new GCC without trouble.

2004-01-14 J. Brobecker <brobecker@gnat.com>

* dwarf2read.c (dwarf2_non_const_array_bound_ignored_complaint):
Delete, no longer used.
(read_subrange_type): New function, mostly extracted from
read_array_type().
(read_array_type): Replace extracted code by call to
read_subrange_type().
(dwarf2_get_attr_constant_value): New function.
(scan_partial_symbols): Add handling for DW_TAG_subrange_type.
(add_partial_symbol): Likewise.
(process_die): Likewise.
(new_symbol): Likewise.
(read_type_die): Likewise.

OK to apply?

Thanks,
--
Joel

[-- Attachment #2: gdb-subrange.diff --]
[-- Type: text/plain, Size: 9396 bytes --]

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.119
diff -u -p -r1.119 dwarf2read.c
--- dwarf2read.c 9 Jan 2004 22:22:07 -0000 1.119
+++ dwarf2read.c 14 Jan 2004 15:13:02 -0000
@@ -592,13 +592,6 @@ struct field_info
/* Various complaints about symbol reading that don't abort the process */

static void
-dwarf2_non_const_array_bound_ignored_complaint (const char *arg1)
-{
- complaint (&symfile_complaints, "non-constant array bounds form '%s' ignored",
- arg1);
-}
-
-static void
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
{
complaint (&symfile_complaints,
@@ -781,6 +774,8 @@ static void read_typedef (struct die_inf

static void read_base_type (struct die_info *, struct dwarf2_cu *);

+static void read_subrange_type (struct die_info *die, struct dwarf2_cu *cu);
+
static void read_file_scope (struct die_info *, struct dwarf2_cu *);

static void read_func_scope (struct die_info *, struct dwarf2_cu *);
@@ -889,6 +884,8 @@ static void dwarf2_empty_hash_tables (vo

static unsigned int dwarf2_get_ref_die_offset (struct attribute *);

+static int dwarf2_get_attr_constant_value (struct attribute *, int);
+
static struct die_info *follow_die_ref (unsigned int);

static struct type *dwarf2_fundamental_type (struct objfile *, int);
@@ -1384,6 +1381,7 @@ scan_partial_symbols (char *info_ptr, CO
}
break;
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
/* File scope base type definitions are added to the partial
symbol table. */
add_partial_symbol (&pdi, cu, namespace);
@@ -1496,6 +1494,7 @@ add_partial_symbol (struct partial_die_i
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
@@ -1858,6 +1857,14 @@ process_die (struct die_info *die, struc
new_symbol (die, die->type, cu);
}
break;
+ case DW_TAG_subrange_type:
+ read_subrange_type (die, cu);
+ if (dwarf_attr (die, DW_AT_name))
+ {
+ /* Add a typedef symbol for the base type definition. */
+ new_symbol (die, die->type, cu);
+ }
+ break;
case DW_TAG_common_block:
read_common_block (die, cu);
break;
@@ -3062,88 +3069,22 @@ read_array_type (struct die_info *die, s
{
if (child_die->tag == DW_TAG_subrange_type)
{
- unsigned int low, high;
-
- /* Default bounds to an array with unspecified length. */
- low = 0;
- high = -1;
- if (cu_language == language_fortran)
- {
- /* FORTRAN implies a lower bound of 1, if not given. */
- low = 1;
- }
-
- index_type = die_type (child_die, cu);
- attr = dwarf_attr (child_die, DW_AT_lower_bound);
- if (attr)
- {
- if (attr->form == DW_FORM_sdata)
- {
- low = DW_SND (attr);
- }
- else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- low = DW_UNSND (attr);
- }
- else
- {
- dwarf2_non_const_array_bound_ignored_complaint
- (dwarf_form_name (attr->form));
- low = 0;
- }
- }
- attr = dwarf_attr (child_die, DW_AT_upper_bound);
- if (attr)
- {
- if (attr->form == DW_FORM_sdata)
- {
- high = DW_SND (attr);
- }
- else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- high = DW_UNSND (attr);
- }
- else if (attr->form == DW_FORM_block1)
- {
- /* GCC encodes arrays with unspecified or dynamic length
- with a DW_FORM_block1 attribute.
- FIXME: GDB does not yet know how to handle dynamic
- arrays properly, treat them as arrays with unspecified
- length for now.
-
- FIXME: jimb/2003-09-22: GDB does not really know
- how to handle arrays of unspecified length
- either; we just represent them as zero-length
- arrays. Choose an appropriate upper bound given
- the lower bound we've computed above. */
- high = low - 1;
- }
- else
- {
- dwarf2_non_const_array_bound_ignored_complaint
- (dwarf_form_name (attr->form));
- high = 1;
- }
- }
+ read_subrange_type (child_die, cu);

- /* Create a range type and save it for array type creation. */
- if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
- {
- range_types = (struct type **)
- xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct type *));
- if (ndim == 0)
- make_cleanup (free_current_contents, &range_types);
- }
- range_types[ndim++] = create_range_type (NULL, index_type, low, high);
+ if (child_die->type != NULL)
+ {
+ /* The range type was succesfully read. Save it for
+ the array type creation. */
+ if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ range_types = (struct type **)
+ xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct type *));
+ if (ndim == 0)
+ make_cleanup (free_current_contents, &range_types);
+ }
+ range_types[ndim++] = child_die->type;
+ }
}
child_die = sibling_die (child_die);
}
@@ -3689,6 +3630,78 @@ read_base_type (struct die_info *die, st
die->type = type;
}

+/* Read the given DW_AT_subrange DIE. */
+
+static void
+read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct type *base_type;
+ struct type *range_type;
+ struct attribute *attr;
+ int low = 0;
+ int high = -1;
+
+ /* If we have already decoded this die, then nothing more to do. */
+ if (die->type)
+ return;
+
+ base_type = die_type (die, cu);
+ if (base_type == NULL)
+ {
+ complaint (&symfile_complaints,
+ "DW_AT_type missing from DW_TAG_subrange_type");
+ return;
+ }
+
+ if (TYPE_CODE (base_type) == TYPE_CODE_VOID)
+ base_type = alloc_type (NULL);
+
+ if (cu_language == language_fortran)
+ {
+ /* FORTRAN implies a lower bound of 1, if not given. */
+ low = 1;
+ }
+
+ attr = dwarf_attr (die, DW_AT_lower_bound);
+ if (attr)
+ low = dwarf2_get_attr_constant_value (attr, 0);
+
+ attr = dwarf_attr (die, DW_AT_upper_bound);
+ if (attr)
+ {
+ if (attr->form == DW_FORM_block1)
+ {
+ /* GCC encodes arrays with unspecified or dynamic length
+ with a DW_FORM_block1 attribute.
+ FIXME: GDB does not yet know how to handle dynamic
+ arrays properly, treat them as arrays with unspecified
+ length for now.
+
+ FIXME: jimb/2003-09-22: GDB does not really know
+ how to handle arrays of unspecified length
+ either; we just represent them as zero-length
+ arrays. Choose an appropriate upper bound given
+ the lower bound we've computed above. */
+ high = low - 1;
+ }
+ else
+ high = dwarf2_get_attr_constant_value (attr, 1);
+ }
+
+ range_type = create_range_type (NULL, base_type, low, high);
+
+ attr = dwarf_attr (die, DW_AT_name);
+ if (attr && DW_STRING (attr))
+ TYPE_NAME (range_type) = DW_STRING (attr);
+
+ attr = dwarf_attr (die, DW_AT_byte_size);
+ if (attr)
+ TYPE_LENGTH (range_type) = DW_UNSND (attr);
+
+ die->type = range_type;
+}
+
+
/* Read a whole compilation unit into a linked list of dies. */

static struct die_info *
@@ -5344,6 +5357,7 @@ new_symbol (struct die_info *die, struct
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
add_symbol_to_list (sym, list_in_scope);
@@ -5626,6 +5640,9 @@ read_type_die (struct die_info *die, str
case DW_TAG_typedef:
read_typedef (die, cu);
break;
+ case DW_TAG_subrange_type:
+ read_subrange_type (die, cu);
+ break;
case DW_TAG_base_type:
read_base_type (die, cu);
break;
@@ -6733,6 +6750,28 @@ dwarf2_get_ref_die_offset (struct attrib
dwarf_form_name (attr->form));
}
return result;
+}
+
+/* Return the constant value held by the given attribute. Return -1
+ if the value held by the attribute is not constant. */
+
+static int
+dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+{
+ if (attr->form == DW_FORM_sdata)
+ return DW_SND (attr);
+ else if (attr->form == DW_FORM_udata
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ return DW_UNSND (attr);
+ else
+ {
+ complaint (&symfile_complaints, "Attribute value is not a constant (%s)",
+ dwarf_form_name (attr->form));
+ return default_value;
+ }
}

static struct die_info *