[PATCH] Handle DW_TAG_subrange_type

Joel Brobecker brobecker@gnat.com
Wed Jan 14 17:28:00 GMT 2004


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
-------------- next part --------------
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 *


More information about the Gdb-patches mailing list