+2018-01-02 Joel Brobecker <brobecker@adacore.com>
+
+ * gdbtypes.h (enum dynamic_prop_node_kind) <DYN_PROP_BYTE_STRIDE>:
+ New enum value.
+ (create_array_type_with_stride): Add byte_stride_prop parameter.
+ * gdbtypes.c (create_array_type_with_stride) <byte_stride_prop>:
+ New parameter. Update all callers in this file.
+ (array_type_has_dynamic_stride): New function.
+ (is_dynamic_type_internal, resolve_dynamic_array): Add handling
+ of arrays with dynamic byte strides.
+ * dwarf2read.c (read_array_type): Add support for dynamic
+ DW_AT_byte_stride attributes.
+
2018-01-02 Joel Brobecker <brobecker@adacore.com>
* dwarf2read.c (read_unspecified_type): Treat
struct type *element_type, *range_type, *index_type;
struct attribute *attr;
const char *name;
+ struct dynamic_prop *byte_stride_prop = NULL;
unsigned int bit_stride = 0;
element_type = die_type (die, cu);
attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
if (attr != NULL)
- bit_stride = DW_UNSND (attr) * 8;
+ {
+ int stride_ok;
+
+ byte_stride_prop
+ = (struct dynamic_prop *) alloca (sizeof (struct dynamic_prop));
+ stride_ok = attr_to_dynamic_prop (attr, die, cu, byte_stride_prop);
+ if (!stride_ok)
+ {
+ complaint (&symfile_complaints,
+ _("unable to read array DW_AT_byte_stride "
+ " - DIE at 0x%x [in module %s]"),
+ to_underlying (die->sect_off),
+ objfile_name (cu->objfile));
+ /* Ignore this attribute. We will likely not be able to print
+ arrays of this type correctly, but there is little we can do
+ to help if we cannot read the attribute's value. */
+ byte_stride_prop = NULL;
+ }
+ }
attr = dwarf2_attr (die, DW_AT_bit_stride, cu);
if (attr != NULL)
index_type = objfile_type (objfile)->builtin_int;
range_type = create_static_range_type (NULL, index_type, 0, -1);
type = create_array_type_with_stride (NULL, element_type, range_type,
- bit_stride);
+ byte_stride_prop, bit_stride);
return set_die_type (die, type, cu);
}
while (i < range_types.size ())
type = create_array_type_with_stride (NULL, type, range_types[i++],
- bit_stride);
+ byte_stride_prop, bit_stride);
}
else
{
size_t ndim = range_types.size ();
while (ndim-- > 0)
type = create_array_type_with_stride (NULL, type, range_types[ndim],
- bit_stride);
+ byte_stride_prop, bit_stride);
}
/* Understand Dwarf2 support for vector types (like they occur on
Elements will be of type ELEMENT_TYPE, the indices will be of type
RANGE_TYPE.
+ BYTE_STRIDE_PROP, when not NULL, provides the array's byte stride.
+ This byte stride property is added to the resulting array type
+ as a DYN_PROP_BYTE_STRIDE. As a consequence, the BYTE_STRIDE_PROP
+ argument can only be used to create types that are objfile-owned
+ (see add_dyn_prop), meaning that either this function must be called
+ with an objfile-owned RESULT_TYPE, or an objfile-owned RANGE_TYPE.
+
+ BIT_STRIDE is taken into account only when BYTE_STRIDE_PROP is NULL.
If BIT_STRIDE is not zero, build a packed array type whose element
size is BIT_STRIDE. Otherwise, ignore this parameter.
create_array_type_with_stride (struct type *result_type,
struct type *element_type,
struct type *range_type,
+ struct dynamic_prop *byte_stride_prop,
unsigned int bit_stride)
{
+ if (byte_stride_prop != NULL
+ && byte_stride_prop->kind == PROP_CONST)
+ {
+ /* The byte stride is actually not dynamic. Pretend we were
+ called with bit_stride set instead of byte_stride_prop.
+ This will give us the same result type, while avoiding
+ the need to handle this as a special case. */
+ bit_stride = byte_stride_prop->data.const_val * 8;
+ byte_stride_prop = NULL;
+ }
+
if (result_type == NULL)
result_type = alloc_type_copy (range_type);
TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
TYPE_TARGET_TYPE (result_type) = element_type;
- if (has_static_range (TYPE_RANGE_DATA (range_type))
+ if (byte_stride_prop == NULL
+ && has_static_range (TYPE_RANGE_DATA (range_type))
&& (!type_not_associated (result_type)
&& !type_not_allocated (result_type)))
{
TYPE_FIELDS (result_type) =
(struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
TYPE_INDEX_TYPE (result_type) = range_type;
- if (bit_stride > 0)
+ if (byte_stride_prop != NULL)
+ add_dyn_prop (DYN_PROP_BYTE_STRIDE, *byte_stride_prop, result_type,
+ TYPE_OBJFILE (result_type));
+ else if (bit_stride > 0)
TYPE_FIELD_BITSIZE (result_type, 0) = bit_stride;
/* TYPE_TARGET_STUB will take care of zero length arrays. */
struct type *range_type)
{
return create_array_type_with_stride (result_type, element_type,
- range_type, 0);
+ range_type, NULL, 0);
}
struct type *
complaint (&symfile_complaints, _("stub type has NULL name"));
}
+/* Return nonzero if TYPE has a DYN_PROP_BYTE_STRIDE dynamic property
+ attached to it, and that property has a non-constant value. */
+
+static int
+array_type_has_dynamic_stride (struct type *type)
+{
+ struct dynamic_prop *prop = get_dyn_prop (DYN_PROP_BYTE_STRIDE, type);
+
+ return (prop != NULL && prop->kind != PROP_CONST);
+}
+
/* Worker for is_dynamic_type. */
static int
{
gdb_assert (TYPE_NFIELDS (type) == 1);
- /* The array is dynamic if either the bounds are dynamic,
- or the elements it contains have a dynamic contents. */
+ /* The array is dynamic if either the bounds are dynamic... */
if (is_dynamic_type_internal (TYPE_INDEX_TYPE (type), 0))
return 1;
- return is_dynamic_type_internal (TYPE_TARGET_TYPE (type), 0);
+ /* ... or the elements it contains have a dynamic contents... */
+ if (is_dynamic_type_internal (TYPE_TARGET_TYPE (type), 0))
+ return 1;
+ /* ... or if it has a dynamic stride... */
+ if (array_type_has_dynamic_stride (type))
+ return 1;
+ return 0;
}
case TYPE_CODE_STRUCT:
struct type *range_type;
struct type *ary_dim;
struct dynamic_prop *prop;
+ unsigned int bit_stride = 0;
gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
else
elt_type = TYPE_TARGET_TYPE (type);
- return create_array_type_with_stride (type, elt_type, range_type,
- TYPE_FIELD_BITSIZE (type, 0));
+ prop = get_dyn_prop (DYN_PROP_BYTE_STRIDE, type);
+ if (prop != NULL)
+ {
+ int prop_eval_ok
+ = dwarf2_evaluate_property (prop, NULL, addr_stack, &value);
+
+ if (prop_eval_ok)
+ {
+ remove_dyn_prop (DYN_PROP_BYTE_STRIDE, type);
+ bit_stride = (unsigned int) (value * 8);
+ }
+ else
+ {
+ /* Could be a bug in our code, but it could also happen
+ if the DWARF info is not correct. Issue a warning,
+ and assume no byte/bit stride (leave bit_stride = 0). */
+ warning (_("cannot determine array stride for type %s"),
+ TYPE_NAME (type) ? TYPE_NAME (type) : "<no name>");
+ }
+ }
+ else
+ bit_stride = TYPE_FIELD_BITSIZE (type, 0);
+
+ return create_array_type_with_stride (type, elt_type, range_type, NULL,
+ bit_stride);
}
/* Resolve dynamic bounds of members of the union TYPE to static
/* A property representing DW_AT_allocated. The presence of this attribute
indicated that the object of the type can be associated. */
DYN_PROP_ASSOCIATED,
+
+ /* A property providing an array's byte stride. */
+ DYN_PROP_BYTE_STRIDE,
};
/* * List for dynamic type attributes. */
extern struct type *create_array_type_with_stride
- (struct type *, struct type *, struct type *, unsigned int);
+ (struct type *, struct type *, struct type *,
+ struct dynamic_prop *, unsigned int);
extern struct type *create_range_type (struct type *, struct type *,
const struct dynamic_prop *,
+2018-01-02 Joel Brobecker <brobecker@adacore.com>
+
+ * gdb.ada/dyn_stride: New testcase.
+
2017-12-27 Stafford Horne <shorne@gmail.com>
* gdb.xml/extra-regs.xml: Add example foo reggroup.
--- /dev/null
+# Copyright 2015-2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb]
+if ![runto "foo.adb:$bp_location" ] then {
+ return -1
+}
+
+gdb_test "print A1(1)" \
+ "\\(i => 0, s => \"\"\\)"
+
+gdb_test "print A1(2)" \
+ "\\(i => 1, s => \"A\"\\)"
+
+gdb_test "print A1(3)" \
+ "\\(i => 2, s => \"AB\"\\)"
--- /dev/null
+-- Copyright 2015-2018 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+procedure Foo is
+
+ procedure Nested (L, U : Integer) is
+ subtype Small_Type is Integer range L .. U;
+ type Record_Type (I : Small_Type := L) is record
+ S : String (1 .. I);
+ end record;
+ type Array_Type is array (Integer range <>) of Record_Type;
+
+ A1 : Array_Type :=
+ (1 => (I => 0, S => <>),
+ 2 => (I => 1, S => "A"),
+ 3 => (I => 2, S => "AB"));
+
+ procedure Discard (R : Record_Type) is
+ begin
+ null;
+ end Discard;
+
+ begin
+ Discard (A1 (1)); -- STOP
+ end;
+
+begin
+ Nested (0, 10);
+ Nested (-10, 10);
+end Foo;