This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[4/6] Fortran dynamic arrays #2: Dynamic array bounds


aHi,

DW_AT_lower_bound / DW_AT_upper_bound can now have the DW_FORM_block* value.
We recalculate TYPE_LENGTH each time from CHECK_TYPEDEF. 

It also sets TYPE_ARRAY_UPPER_BOUND_TYPE to BOUND_CANNOT_BE_DETERMINED where
appropriate (the variable `vart' in the testcase code).

READ_VAR_VALUE has an chicken-and-egg problem.  It first allocates VALUE V and
then detects the variable data for it.  We need to know the variable size in
the first place to be able to allocate VALUE V with the appropriate size.

Patch provides TYPE_COUNT_BOUND for DW_AT_count.  Bidirectional interface
provided for TYPE_HIGH_BOUND/DW_AT_upper_bound <-> DW_COUNT_BOUND/DW_AT_count.


Regards,
Jan
2007-11-23  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.in: Update dependencies.
	* findvar.c: Include "dwarf2block.h".
	(read_var_value): Refactored to rely on TYPE_LENGTH_GET_WITH_ADDRESS
	and ALLOCATE_VALUE_WITH_LENGTH and allocated the returned VALUE only
	after its ADDRESS has been found.
	* gdbtypes.c: Include "dwarf2block.h".
	(create_range_type): Rename to ...
	(create_range_type_nfields): ... here and add the parameter NFIELDS.
	Move setting TYPE_LOW_BOUND_RAW, TYPE_HIGH_BOUND_RAW and
	TYPE_FLAG_UNSIGNED into ...
	(create_range_type): ... a new function.
	(create_array_type): Remove variable LOW_BOUND and HIGH_BOUND.
	No longer call GET_DISCRETE_BOUNDS, set TYPE_LENGTH only for
	non-dynamic array types.
	(range_type_any_field_internal, range_type_high_bound_internal)
	(range_type_count_bound_internal, range_type_byte_stride_internal)
	(type_length_get): New functions.
	(check_typedef): Call TYPE_LENGTH_GET to get the array memory size.
	* dwarf2read.c (enum dwarf2_get_attr_constant_value): New.
	(dwarf2_get_attr_constant_value): Update the prototype.
	(read_array_type): Propagate TYPE_ARRAY_UPPER_BOUND_TYPE and
	TYPE_ARRAY_LOWER_BOUND_TYPE from the range type into the array type.
	(read_subrange_type): New variables BYTE_STRIDE_ATTR, BYTE_STRIDE_INT,
	HIGH_TYPE and BYTE_STRIDE_TYPE.  Replace the call to CREATE_RANGE_TYPE
	with a call to CREATE_RANGE_TYPE_NFIELDS.  New support for
	`DW_AT_count'.  Support DWARF2_ATTR_BLOCK for `DW_AT_lower_bound',
	`DW_AT_upper_bound', `DW_AT_count' and `DW_AT_byte_stride'.  Fill in
	TYPE_ARRAY_UPPER_BOUND_TYPE appropriately.
	(dwarf2_get_attr_constant_value): Change the calling convention.
	Support the `DW_FORM_block', `DW_FORM_block1', `DW_FORM_block2' and
	`DW_FORM_block4' detection.  Support the NULL ATTR entry value.
	* gdbtypes.h (struct main_type): New field LOC.DWARF_BLOCK.  Include
	the range bounds meaning for the field STATIC_KIND.
	Update the TYPE_LENGTH comment also for ARRAYs.
	(TYPE_LOW_BOUND): Renamed to ...
	(TYPE_LOW_BOUND_RAW): ... here.
	(TYPE_HIGH_BOUND): Renamed to ...
	(TYPE_HIGH_BOUND_RAW): ... here.
	(TYPE_BYTE_STRIDE_RAW, TYPE_LOW_BOUND, TYPE_HIGH_BOUND)
	(TYPE_COUNT_BOUND, TYPE_BYTE_STRIDE, TYPE_BOUND_IS_DWARF_BLOCK_MASK)
	(TYPE_BOUND_IS_DWARF_BLOCK_VAR, TYPE_HIGH_BOUND_IS_COUNT_MASK)
	(TYPE_HIGH_BOUND_IS_COUNT_VAR, FIELD_DWARF_BLOCK)
	(TYPE_FIELD_DWARF_BLOCK): New macros.
	(TYPE_ARRAY_UPPER_BOUND_VALUE, TYPE_ARRAY_BYTE_STRIDE_VALUE): Redefine
	using underneath TYPE_INDEX_TYPE.
	(create_range_type_nfields, range_type_any_field_internal)
	(range_type_high_bound_internal, range_type_count_bound_internal)
	(range_type_byte_stride_internal): New prototypes.

Index: sources/gdb/Makefile.in
===================================================================
--- sources.orig/gdb/Makefile.in	2007-11-23 22:07:58.000000000 +0100
+++ sources/gdb/Makefile.in	2007-11-23 22:08:01.000000000 +0100
@@ -2091,7 +2091,7 @@ f-exp.o: f-exp.c $(defs_h) $(gdb_string_
 findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \
 	$(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \
-	$(user_regs_h) $(block_h)
+	$(user_regs_h) $(block_h) $(dwarf2block_h)
 f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 	$(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \
 	$(valprint_h) $(value_h)
@@ -2134,7 +2134,8 @@ gdb-events.o: gdb-events.c $(defs_h) $(g
 gdbtypes.o: gdbtypes.c $(defs_h) $(gdb_string_h) $(bfd_h) $(symtab_h) \
 	$(symfile_h) $(objfiles_h) $(gdbtypes_h) $(expression_h) \
 	$(language_h) $(target_h) $(value_h) $(demangle_h) $(complaints_h) \
-	$(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) $(hashtab_h)
+	$(gdbcmd_h) $(wrapper_h) $(cp_abi_h) $(gdb_assert_h) $(hashtab_h) \
+	$(dwarf2block_h)
 glibc-tdep.o: glibc-tdep.c $(defs_h) $(frame_h) $(symtab_h) $(symfile_h) \
 	$(objfiles_h) $(glibc_tdep_h)
 gnu-nat.o: gnu-nat.c $(gdb_string_h) $(defs_h) $(inferior_h) $(symtab_h) \
Index: sources/gdb/findvar.c
===================================================================
--- sources.orig/gdb/findvar.c	2007-11-23 22:07:47.000000000 +0100
+++ sources/gdb/findvar.c	2007-11-23 22:08:01.000000000 +0100
@@ -34,6 +34,7 @@
 #include "regcache.h"
 #include "user-regs.h"
 #include "block.h"
+#include "dwarf2block.h"
 
 /* Basic byte-swapping routines.  GDB has needed these for a long time...
    All extract a target-format integer at ADDR which is LEN bytes long.  */
@@ -370,24 +371,8 @@ symbol_read_needs_frame (struct symbol *
 struct value *
 read_var_value (struct symbol *var, struct frame_info *frame)
 {
-  struct value *v;
   struct type *type = SYMBOL_TYPE (var);
   CORE_ADDR addr;
-  int len;
-
-  if (SYMBOL_CLASS (var) == LOC_COMPUTED
-      || SYMBOL_CLASS (var) == LOC_COMPUTED_ARG
-      || SYMBOL_CLASS (var) == LOC_REGISTER
-      || SYMBOL_CLASS (var) == LOC_REGPARM)
-    /* These cases do not use V.  */
-    v = NULL;
-  else
-    {
-      v = allocate_value (type);
-      VALUE_LVAL (v) = lval_memory;	/* The most likely possibility.  */
-    }
-
-  len = TYPE_LENGTH (type);
 
   /* FIXME drow/2003-09-06: this call to the selected frame should be
      pushed upwards to the callers.  */
@@ -397,31 +382,39 @@ read_var_value (struct symbol *var, stru
   switch (SYMBOL_CLASS (var))
     {
     case LOC_CONST:
-      /* Put the constant back in target format.  */
-      store_signed_integer (value_contents_raw (v), len,
-			    (LONGEST) SYMBOL_VALUE (var));
-      VALUE_LVAL (v) = not_lval;
-      return v;
+      {
+	/* Put the constant back in target format.  */
+	struct value *v = allocate_value (type);
+	VALUE_LVAL (v) = not_lval;
+	store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type),
+			      (LONGEST) SYMBOL_VALUE (var));
+	return v;
+      }
 
     case LOC_LABEL:
-      /* Put the constant back in target format.  */
-      if (overlay_debugging)
-	{
-	  CORE_ADDR addr
-	    = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
-					SYMBOL_BFD_SECTION (var));
-	  store_typed_address (value_contents_raw (v), type, addr);
-	}
-      else
-	store_typed_address (value_contents_raw (v), type,
-			      SYMBOL_VALUE_ADDRESS (var));
-      VALUE_LVAL (v) = not_lval;
-      return v;
+      {
+	/* Put the constant back in target format.  */
+	struct value *v = allocate_value (type);
+	VALUE_LVAL (v) = not_lval;
+	if (overlay_debugging)
+	  {
+	    CORE_ADDR addr
+	      = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+					  SYMBOL_BFD_SECTION (var));
+	    store_typed_address (value_contents_raw (v), type, addr);
+	  }
+	else
+	  store_typed_address (value_contents_raw (v), type,
+				SYMBOL_VALUE_ADDRESS (var));
+	return v;
+      }
 
     case LOC_CONST_BYTES:
       {
-	memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), len);
+	struct value *v = allocate_value (type);
 	VALUE_LVAL (v) = not_lval;
+	memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
+		TYPE_LENGTH (type));
 	return v;
       }
 
@@ -503,12 +496,23 @@ addresses have not been bound by the dyn
       break;
 
     case LOC_BLOCK:
-      if (overlay_debugging)
-	VALUE_ADDRESS (v) = symbol_overlayed_address
-	  (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var));
-      else
-	VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
-      return v;
+      {
+        CORE_ADDR addr;
+	struct value *v;
+
+	if (overlay_debugging)
+	  addr = symbol_overlayed_address
+	    (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_BFD_SECTION (var));
+	else
+	  addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+	/* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for
+	   DW_OP_push_object_address.  */
+	object_address_set (addr);
+	v = allocate_value (type);
+	VALUE_ADDRESS (v) = addr;
+	VALUE_LVAL (v) = lval_memory;
+	return v;
+      }
 
     case LOC_REGISTER:
     case LOC_REGPARM:
@@ -532,7 +536,6 @@ addresses have not been bound by the dyn
 	      error (_("Value of register variable not available."));
 
 	    addr = value_as_address (regval);
-	    VALUE_LVAL (v) = lval_memory;
 	  }
 	else
 	  {
@@ -572,18 +575,33 @@ addresses have not been bound by the dyn
       break;
 
     case LOC_OPTIMIZED_OUT:
-      VALUE_LVAL (v) = not_lval;
-      set_value_optimized_out (v, 1);
-      return v;
+      {
+        struct value *v = allocate_value (type);
+
+	VALUE_LVAL (v) = not_lval;
+	set_value_optimized_out (v, 1);
+	return v;
+      }
 
     default:
       error (_("Cannot look up value of a botched symbol."));
       break;
     }
 
-  VALUE_ADDRESS (v) = addr;
-  set_value_lazy (v, 1);
-  return v;
+  {
+    struct value *v;
+
+    /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for
+       DW_OP_push_object_address.  */
+    object_address_set (addr);
+    v = allocate_value (type);
+    VALUE_ADDRESS (v) = addr;
+    VALUE_LVAL (v) = lval_memory;
+
+    set_value_lazy (v, 1);
+
+    return v;
+  }
 }
 
 /* Install default attributes for register values.  */
Index: sources/gdb/gdbtypes.c
===================================================================
--- sources.orig/gdb/gdbtypes.c	2007-11-23 22:07:47.000000000 +0100
+++ sources/gdb/gdbtypes.c	2007-11-23 22:08:01.000000000 +0100
@@ -38,6 +38,7 @@
 #include "cp-abi.h"
 #include "gdb_assert.h"
 #include "hashtab.h"
+#include "dwarf2block.h"
 
 /* These variables point to the objects
    representing the predefined C data types.  */
@@ -682,16 +683,21 @@ allocate_stub_method (struct type *type)
    RESULT_TYPE, or creating a new type, inheriting the objfile from
    INDEX_TYPE.
 
-   Indices will be of type INDEX_TYPE, and will range from LOW_BOUND
-   to HIGH_BOUND, inclusive.
+   Indices will be of type INDEX_TYPE.  NFIELDS should be 2 for standard
+   arrays, 3 for a custom TYPE_BYTE_STRIDE.  Use CREATE_RANGE_TYPE for common
+   constant LOW_BOUND/HIGH_BOUND ranges.
+
+   You must set TYPE_FLAG_UNSIGNED yourself as being done in CREATE_RANGE_TYPE.
 
    FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
    sure it is TYPE_CODE_UNDEF before we bash it into a range type?  */
 
 struct type *
-create_range_type (struct type *result_type, struct type *index_type,
-		   int low_bound, int high_bound)
+create_range_type_nfields (struct type *result_type, struct type *index_type,
+                           int nfields)
 {
+  int fieldno;
+
   if (result_type == NULL)
     {
       result_type = alloc_type (TYPE_OBJFILE (index_type));
@@ -702,17 +708,33 @@ create_range_type (struct type *result_t
     TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
   else
     TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type));
-  TYPE_NFIELDS (result_type) = 2;
+  TYPE_NFIELDS (result_type) = nfields;
   TYPE_FIELDS (result_type) = (struct field *)
-    TYPE_ALLOC (result_type, 2 * sizeof (struct field));
-  memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field));
-  TYPE_FIELD_BITPOS (result_type, 0) = low_bound;
-  TYPE_FIELD_BITPOS (result_type, 1) = high_bound;
+    TYPE_ALLOC (result_type,
+		TYPE_NFIELDS (result_type) * sizeof (struct field));
+  memset (TYPE_FIELDS (result_type), 0,
+	  TYPE_NFIELDS (result_type) * sizeof (struct field));
+
+  return (result_type);
+}
+
+/* Simplified CREATE_RANGE_TYPE_NFIELDS for constant ranges from LOW_BOUND to
+   HIGH_BOUND, inclusive.  TYPE_BYTE_STRIDE is always set to zero (default
+   native target type length).  */
+
+struct type *
+create_range_type (struct type *result_type, struct type *index_type,
+		   int low_bound, int high_bound)
+{
+  result_type = create_range_type_nfields (result_type, index_type, 2);
+
+  TYPE_LOW_BOUND_RAW (result_type) = low_bound;
+  TYPE_HIGH_BOUND_RAW (result_type) = high_bound;
 
   if (low_bound >= 0)
     TYPE_FLAGS (result_type) |= TYPE_FLAG_UNSIGNED;
 
-  return (result_type);
+  return result_type;
 }
 
 /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
@@ -800,19 +822,23 @@ create_array_type (struct type *result_t
 		   struct type *element_type,
 		   struct type *range_type)
 {
-  LONGEST low_bound, high_bound;
-
   if (result_type == NULL)
     {
       result_type = alloc_type (TYPE_OBJFILE (range_type));
     }
   TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
   TYPE_TARGET_TYPE (result_type) = element_type;
-  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
-    low_bound = high_bound = 0;
   CHECK_TYPEDEF (element_type);
-  TYPE_LENGTH (result_type) =
-    TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+  /* Dynamically sized arrays cannot be computed now as we may have forward
+     DWARF references here.  */
+  if ((TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 0)
+       & TYPE_BOUND_IS_DWARF_BLOCK_MASK) != 0
+      && (TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 1)
+	  & TYPE_BOUND_IS_DWARF_BLOCK_MASK) != 0)
+    TYPE_LENGTH (result_type) = 0;
+  else
+    TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type)
+				* TYPE_COUNT_BOUND (range_type);
   TYPE_NFIELDS (result_type) = 1;
   TYPE_FIELDS (result_type) =
     (struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
@@ -1349,6 +1375,111 @@ stub_noname_complaint (void)
   complaint (&symfile_complaints, _("stub type has NULL name"));
 }
 
+CORE_ADDR range_type_any_field_internal (struct type *range_type, int fieldno)
+{
+  if ((TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, fieldno)
+       & TYPE_BOUND_IS_DWARF_BLOCK_MASK) != 0)
+    return dwarf_block_exec (TYPE_FIELD_DWARF_BLOCK (range_type, fieldno));
+  else
+    return TYPE_FIELD_BITPOS (range_type, (fieldno));
+}
+
+int
+range_type_high_bound_internal (struct type *range_type)
+{
+  int raw_value = range_type_any_field_internal (range_type, 1);
+
+  if ((TYPE_HIGH_BOUND_IS_COUNT_VAR (range_type)
+       & TYPE_HIGH_BOUND_IS_COUNT_MASK) == 0)
+    {
+      /* DW_AT_upper_bound value.  */
+      return raw_value;
+    }
+  else
+    {
+      /* DW_AT_count value.  */
+      return TYPE_LOW_BOUND (range_type) + raw_value - 1;
+    }
+}
+
+int
+range_type_count_bound_internal (struct type *range_type)
+{
+  int raw_value = range_type_any_field_internal (range_type, 1);
+  if ((TYPE_HIGH_BOUND_IS_COUNT_VAR (range_type)
+       & TYPE_HIGH_BOUND_IS_COUNT_MASK) != 0)
+    {
+      /* DW_AT_count value.  */
+      return raw_value;
+    }
+  else
+    {
+      /* DW_AT_upper_bound value.  */
+      return 1 + raw_value - TYPE_LOW_BOUND (range_type);
+    }
+}
+
+CORE_ADDR range_type_byte_stride_internal (struct type *range_type)
+{
+  if (TYPE_NFIELDS (range_type) >= 3)
+    return range_type_any_field_internal (range_type, 2);
+  else
+    {
+      /* The caller will need to call something like
+	 `TYPE_LENGTH (check_typedef (element_type))
+	  * TYPE_COUNT_BOUND (range_type) '.  */
+      return 0;
+    }
+}
+
+/* Calculate the memory length of array TYPE.
+
+   TARGET_TYPE should be set to `check_typedef (TYPE_TARGET_TYPE (type))' as
+   a performance hint.  Feel free to pass NULL.  Set FULL_SPAN to return the
+   size incl. the possibly incomplete last element - it may differ from the
+   cleared FULL_SPAN return value for larger TYPE_BYTE_STRIDE values.  */
+
+static CORE_ADDR
+type_length_get (struct type *type, struct type *target_type, int full_span)
+{
+  struct type *range_type;
+  int count;
+  CORE_ADDR byte_stride = 0;	/* `= 0' for a false GCC warning.  */
+  CORE_ADDR element_size;
+
+  if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+    return TYPE_LENGTH (type);
+
+  /* Avoid executing TYPE_COUNT_BOUND for invalid (unallocated/unassociated)
+     Fortran arrays.  The allocated data will never be used so they can be
+     zero-length.  */
+  if (!LA_VALUE_ADDRESS_GET (type, NULL))
+    return 0;
+
+  range_type = TYPE_INDEX_TYPE (type);
+  count = TYPE_COUNT_BOUND (range_type);
+  if (count < 0)
+    warning (_("Object count %d < 0"), count);
+  if (count <= 0)
+    return 0;
+  if (full_span || count > 1)
+    {
+      byte_stride = TYPE_BYTE_STRIDE (range_type);
+      if (byte_stride == 0)
+        {
+	  if (target_type == NULL)
+	    target_type = check_typedef (TYPE_TARGET_TYPE (type));
+	  byte_stride = type_length_get (target_type, NULL, 1);
+	}
+    }
+  if (full_span)
+    return count * byte_stride;
+  if (target_type == NULL)
+    target_type = check_typedef (TYPE_TARGET_TYPE (type));
+  element_size = type_length_get (target_type, NULL, 1);
+  return (count - 1) * byte_stride + element_size;
+}
+
 /* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
 
    If this is a stubbed struct (i.e. declared as struct foo *), see if
@@ -1493,10 +1624,7 @@ check_typedef (struct type *type)
 	{
 	  /* Now recompute the length of the array type, based on its
 	     number of elements and the target type's length.  */
-	  TYPE_LENGTH (type) =
-	    ((TYPE_FIELD_BITPOS (range_type, 1)
-	      - TYPE_FIELD_BITPOS (range_type, 0) + 1)
-	     * TYPE_LENGTH (target_type));
+	  TYPE_LENGTH (type) = type_length_get (type, target_type, 0);
 	  TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
 	}
       else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
Index: sources/gdb/dwarf2read.c
===================================================================
--- sources.orig/gdb/dwarf2read.c	2007-11-23 22:07:59.000000000 +0100
+++ sources/gdb/dwarf2read.c	2007-11-23 22:08:01.000000000 +0100
@@ -1006,7 +1006,14 @@ static void store_in_ref_table (unsigned
 static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
 					       struct dwarf2_cu *);
 
-static int dwarf2_get_attr_constant_value (struct attribute *, int);
+enum dwarf2_get_attr_constant_value
+  {
+    dwarf2_attr_unknown,
+    dwarf2_attr_const,
+    dwarf2_attr_block
+  };
+static enum dwarf2_get_attr_constant_value dwarf2_get_attr_constant_value
+  (struct attribute *attr, int *val_return);
 
 static struct die_info *follow_die_ref (struct die_info *,
 					struct attribute *,
@@ -4299,14 +4306,27 @@ read_array_type (struct die_info *die, s
 
   if (read_array_order (die, cu) == DW_ORD_col_major)
     {
-      int i = 0;
-      while (i < ndim)
-	type = create_array_type (NULL, type, range_types[i++]);
+      int i;
+      for (i = 0; i < ndim; i++)
+	{
+	  type = create_array_type (NULL, type, range_types[i]);
+	  TYPE_ARRAY_UPPER_BOUND_TYPE (type) =
+	    TYPE_ARRAY_UPPER_BOUND_TYPE (range_types[i]);
+	  TYPE_ARRAY_LOWER_BOUND_TYPE (type) =
+	    TYPE_ARRAY_LOWER_BOUND_TYPE (range_types[i]);
+	}
     }
   else
     {
-      while (ndim-- > 0)
-	type = create_array_type (NULL, type, range_types[ndim]);
+      int i;
+      for (i = ndim - 1; i >= 0; i--)
+	{
+	  type = create_array_type (NULL, type, range_types[i]);
+	  TYPE_ARRAY_UPPER_BOUND_TYPE (type) =
+	    TYPE_ARRAY_UPPER_BOUND_TYPE (range_types[i]);
+	  TYPE_ARRAY_LOWER_BOUND_TYPE (type) =
+	    TYPE_ARRAY_LOWER_BOUND_TYPE (range_types[i]);
+	}
     }
 
   /* Understand Dwarf2 support for vector types (like they occur on
@@ -4914,9 +4934,9 @@ read_subrange_type (struct die_info *die
 {
   struct type *base_type;
   struct type *range_type;
-  struct attribute *attr;
-  int low = 0;
-  int high = -1;
+  struct attribute *attr, *byte_stride_attr;
+  int low, high, byte_stride_int;
+  enum dwarf2_get_attr_constant_value high_type, byte_stride_type;
   char *name;
   
   /* If we have already decoded this die, then nothing more to do.  */
@@ -4933,42 +4953,99 @@ read_subrange_type (struct die_info *die
 			   gdbarch_addr_bit (current_gdbarch) / 8, cu);
     }
 
-  if (cu->language == language_fortran)
-    { 
-      /* FORTRAN implies a lower bound of 1, if not given.  */
-      low = 1;
-    }
+  /* DW_AT_bit_stride is unsupported as if it would be non-constant we would
+     have to wrap it by the division by 8 or provide another value type etc.  */
+  byte_stride_attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
+  byte_stride_type = dwarf2_get_attr_constant_value (byte_stride_attr,
+						     &byte_stride_int);
+
+  range_type = create_range_type_nfields
+    (NULL, base_type, byte_stride_type == dwarf2_attr_unknown ? 2 : 3);
 
-  /* FIXME: For variable sized arrays either of these could be
-     a variable rather than a constant value.  We'll allow it,
-     but we don't know how to handle it.  */
   attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
-  if (attr)
-    low = dwarf2_get_attr_constant_value (attr, 0);
+  switch (dwarf2_get_attr_constant_value (attr, &low))
+    {
+    case dwarf2_attr_unknown:
+      if (cu->language == language_fortran)
+	{
+	  /* FORTRAN implies a lower bound of 1, if not given.  */
+	  low = 1;
+	}
+      else
+        {
+	  /* According to DWARF3 we should assume the value 0 only for
+	     LANGUAGE_C and LANGUAGE_CPLUS.  */
+	  low = 0;
+	}
+      /* PASSTHRU */
+    case dwarf2_attr_const:
+      TYPE_LOW_BOUND_RAW (range_type) = low;
+      if (low >= 0)
+	TYPE_FLAGS (range_type) |= TYPE_FLAG_UNSIGNED;
+      break;
+    case dwarf2_attr_block:
+      TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 0)
+        |= TYPE_BOUND_IS_DWARF_BLOCK_MASK;
+      TYPE_FIELD_DWARF_BLOCK (range_type, 0) = DW_BLOCK (attr);
+      /* For auto-detection of possibly missing DW_AT_upper_bound.  */
+      low = 0;
+      break;
+    }
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
-  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);
+  high_type = dwarf2_get_attr_constant_value (attr, &high);
+  if (high_type == dwarf2_attr_unknown)
+    {
+      int count;
+
+      attr = dwarf2_attr (die, DW_AT_count, cu);
+      high_type = dwarf2_get_attr_constant_value (attr, &count);
+      switch (high_type)
+	{
+	case dwarf2_attr_unknown:
+	  break;
+	case dwarf2_attr_const:
+	  /* We do not handle LOW being set as DW_BLOCK here.  */
+	  high = low + count - 1;
+	  /* PASSTHRU */
+	case dwarf2_attr_block:
+	  TYPE_HIGH_BOUND_IS_COUNT_VAR (range_type)
+	    |= TYPE_HIGH_BOUND_IS_COUNT_MASK;
+	  break;
+	}
+    }
+  switch (high_type)
+    {
+    case dwarf2_attr_unknown:
+      /* It needs to get propagated to he array type owning us.  */
+      TYPE_ARRAY_UPPER_BOUND_TYPE (range_type) = BOUND_CANNOT_BE_DETERMINED;
+      high = low - 1;
+      /* PASSTHRU */
+    case dwarf2_attr_const:
+      TYPE_HIGH_BOUND_RAW (range_type) = high;
+      break;
+    case dwarf2_attr_block:
+      TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 1)
+        |= TYPE_BOUND_IS_DWARF_BLOCK_MASK;
+      TYPE_FIELD_DWARF_BLOCK (range_type, 1) = DW_BLOCK (attr);
+      break;
     }
 
-  range_type = create_range_type (NULL, base_type, low, high);
+  switch (byte_stride_type)
+    {
+    case dwarf2_attr_unknown:
+      break;
+    case dwarf2_attr_const:
+      if (byte_stride_int == 0)
+	warning (_("Found DW_AT_byte_stride with unsupported value 0"));
+      TYPE_HIGH_BOUND_RAW (range_type) = byte_stride_int;
+      break;
+    case dwarf2_attr_block:
+      TYPE_BOUND_IS_DWARF_BLOCK_VAR (range_type, 2)
+        |= TYPE_BOUND_IS_DWARF_BLOCK_MASK;
+      TYPE_FIELD_DWARF_BLOCK (range_type, 2) = DW_BLOCK (byte_stride_attr);
+      break;
+    }
 
   name = dwarf2_name (die, cu);
   if (name)
@@ -8978,26 +9055,35 @@ dwarf2_get_ref_die_offset (struct attrib
   return result;
 }
 
-/* Return the constant value held by the given attribute.  Return -1
-   if the value held by the attribute is not constant.  */
+/* *VAL_RETURN is filled only for DWARF2_ATTR_CONST.  */
 
-static int
-dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+static enum dwarf2_get_attr_constant_value
+dwarf2_get_attr_constant_value (struct attribute *attr, int *val_return)
 {
+  if (attr == NULL)
+    return dwarf2_attr_unknown;
   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;
+      *val_return = DW_SND (attr);
+      return dwarf2_attr_const;
     }
+  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)
+    {
+      *val_return = DW_UNSND (attr);
+      return dwarf2_attr_const;
+    }
+  if (attr->form == DW_FORM_block
+      || attr->form == DW_FORM_block1
+      || attr->form == DW_FORM_block2
+      || attr->form == DW_FORM_block4)
+    return dwarf2_attr_block;
+  complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"),
+             dwarf_form_name (attr->form));
+  return dwarf2_attr_unknown;
 }
 
 static struct die_info *
Index: sources/gdb/gdbtypes.h
===================================================================
--- sources.orig/gdb/gdbtypes.h	2007-11-23 22:07:47.000000000 +0100
+++ sources/gdb/gdbtypes.h	2007-11-23 22:08:01.000000000 +0100
@@ -458,6 +458,9 @@ struct main_type
 
       CORE_ADDR physaddr;
       char *physname;
+
+      /* For dynamically-sized arrays.  Passed to DWARF_BLOCK_EXEC.  */
+      struct dwarf_block *dwarf_block;
     }
     loc;
 
@@ -468,7 +471,11 @@ struct main_type
 
     /* This flag is zero for non-static fields, 1 for fields whose location
        is specified by the label loc.physname, and 2 for fields whose location
-       is specified by loc.physaddr.  */
+       is specified by loc.physaddr.
+       For range bounds bit 0 cleared is for loc.bitpos and bit 0 set is for
+       loc.dwarf_block (TYPE_BOUND_IS_DWARF_BLOCK_MASK).
+       For range bounds bit 1 cleared is for DW_AT_upper_bound and bit 1 set is
+       for DW_AT_count (TYPE_HIGH_BOUND_IS_COUNT_MASK).  */
 
     unsigned int static_kind : 2;
 
@@ -807,9 +814,9 @@ extern void allocate_cplus_struct_type (
 #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
 #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
 #define TYPE_CHAIN(thistype) (thistype)->chain
-/* Note that if thistype is a TYPEDEF type, you have to call check_typedef.
-   But check_typedef does set the TYPE_LENGTH of the TYPEDEF type,
-   so you only have to call check_typedef once.  Since allocate_value
+/* Note that if thistype is a TYPEDEF or ARRAY type, you have to call
+   check_typedef.  But check_typedef does set the TYPE_LENGTH of the TYPEDEF
+   type, so you only have to call check_typedef once.  Since allocate_value
    calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe.  */
 #define TYPE_LENGTH(thistype) (thistype)->length
 #define TYPE_OBJFILE(thistype) TYPE_MAIN_TYPE(thistype)->objfile
@@ -823,8 +830,25 @@ extern void allocate_cplus_struct_type (
 #define TYPE_INSTANTIATIONS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->instantiations
 
 #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
-#define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0)
-#define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1)
+#define TYPE_LOW_BOUND_RAW(range_type) TYPE_FIELD_BITPOS (range_type, 0)
+#define TYPE_HIGH_BOUND_RAW(range_type) TYPE_FIELD_BITPOS (range_type, 1)
+/* `TYPE_NFIELDS (range_type) >= 3' check is required before accessing it:  */
+#define TYPE_BYTE_STRIDE_RAW(range_type) TYPE_FIELD_BITPOS (range_type, 2)
+#define TYPE_LOW_BOUND(range_type) \
+  ((int) range_type_any_field_internal ((range_type), 0))
+#define TYPE_HIGH_BOUND(range_type) \
+  range_type_high_bound_internal ((range_type))
+#define TYPE_COUNT_BOUND(range_type) \
+  range_type_count_bound_internal ((range_type))
+#define TYPE_BYTE_STRIDE(type) \
+  range_type_byte_stride_internal ((type))
+
+#define TYPE_BOUND_IS_DWARF_BLOCK_MASK 1
+#define TYPE_BOUND_IS_DWARF_BLOCK_VAR(range_type, fieldno) \
+  TYPE_FIELD_STATIC_KIND (range_type, fieldno)
+#define TYPE_HIGH_BOUND_IS_COUNT_MASK 2
+#define TYPE_HIGH_BOUND_IS_COUNT_VAR(range_type) \
+  TYPE_FIELD_STATIC_KIND (range_type, 1)
 
 /* Moto-specific stuff for FORTRAN arrays */
 
@@ -833,11 +857,12 @@ extern void allocate_cplus_struct_type (
 #define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) \
 	TYPE_MAIN_TYPE(thistype)->lower_bound_type
 
-#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
-   (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),1))
-
 #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
-   (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),0))
+  (TYPE_LOW_BOUND(TYPE_INDEX_TYPE(arraytype)))
+#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
+  (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE(arraytype)))
+#define TYPE_ARRAY_BYTE_STRIDE_VALUE(arraytype) \
+  (TYPE_BYTE_STRIDE(TYPE_INDEX_TYPE(arraytype)))
 
 /* C++ */
 
@@ -867,6 +892,7 @@ extern void allocate_cplus_struct_type (
 #define FIELD_TYPE(thisfld) ((thisfld).type)
 #define FIELD_NAME(thisfld) ((thisfld).name)
 #define FIELD_BITPOS(thisfld) ((thisfld).loc.bitpos)
+#define FIELD_DWARF_BLOCK(thisfld) ((thisfld).loc.dwarf_block)
 #define FIELD_ARTIFICIAL(thisfld) ((thisfld).artificial)
 #define FIELD_BITSIZE(thisfld) ((thisfld).bitsize)
 #define FIELD_STATIC_KIND(thisfld) ((thisfld).static_kind)
@@ -880,6 +906,7 @@ extern void allocate_cplus_struct_type (
 #define TYPE_FIELD_TYPE(thistype, n) FIELD_TYPE(TYPE_FIELD(thistype, n))
 #define TYPE_FIELD_NAME(thistype, n) FIELD_NAME(TYPE_FIELD(thistype, n))
 #define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS(TYPE_FIELD(thistype,n))
+#define TYPE_FIELD_DWARF_BLOCK(thistype, n) FIELD_DWARF_BLOCK(TYPE_FIELD(thistype,n))
 #define TYPE_FIELD_ARTIFICIAL(thistype, n) FIELD_ARTIFICIAL(TYPE_FIELD(thistype,n))
 #define TYPE_FIELD_BITSIZE(thistype, n) FIELD_BITSIZE(TYPE_FIELD(thistype,n))
 #define TYPE_FIELD_PACKED(thistype, n) (FIELD_BITSIZE(TYPE_FIELD(thistype,n))!=0)
@@ -1290,12 +1317,25 @@ extern struct type *make_function_type (
 
 extern struct type *lookup_function_type (struct type *);
 
+extern struct type *create_range_type_nfields (struct type *result_type,
+					       struct type *index_type,
+					       int nfields);
+
 extern struct type *create_range_type (struct type *, struct type *, int,
 				       int);
 
 extern struct type *create_array_type (struct type *, struct type *,
 				       struct type *);
 
+extern CORE_ADDR range_type_any_field_internal (struct type *range_type,
+						int fieldno);
+
+extern int range_type_high_bound_internal (struct type *range_type);
+
+extern int range_type_count_bound_internal (struct type *range_type);
+
+extern CORE_ADDR range_type_byte_stride_internal (struct type *range_type);
+
 extern struct type *create_string_type (struct type *, struct type *);
 
 extern struct type *create_set_type (struct type *, struct type *);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]