/* The value of an invalid conversion badness. */
#define INVALID_CONVERSION 100
+static struct dynamic_prop_list *
+copy_dynamic_prop_list (struct obstack *, struct dynamic_prop_list *);
+
/* Initialize BADNESS constants. */
const struct rank LENGTH_MISMATCH_BADNESS = {INVALID_CONVERSION,0};
and stride information set to undefined. The RESOLVE_P set to false
case will be used when evaluating a dynamic array that is not
allocated, or not associated, i.e. the bounds information might not be
- initialized yet. */
+ initialized yet.
+
+ RANK is the array rank for which we are resolving this range, and is a
+ zero based count. The rank should never be negative.
+*/
static struct type *
resolve_dynamic_range (struct type *dyn_range_type,
struct property_addr_info *addr_stack,
- bool resolve_p = true)
+ int rank, bool resolve_p = true)
{
CORE_ADDR value;
struct type *static_range_type, *static_target_type;
struct dynamic_prop low_bound, high_bound, stride;
gdb_assert (dyn_range_type->code () == TYPE_CODE_RANGE);
+ gdb_assert (rank >= 0);
const struct dynamic_prop *prop = &dyn_range_type->bounds ()->low;
- if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value,
+ { (CORE_ADDR) rank }))
low_bound.set_const_val (value);
else
low_bound.set_undefined ();
prop = &dyn_range_type->bounds ()->high;
- if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value,
+ { (CORE_ADDR) rank }))
{
high_bound.set_const_val (value);
bool byte_stride_p = dyn_range_type->bounds ()->flag_is_byte_stride;
prop = &dyn_range_type->bounds ()->stride;
- if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+ if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value,
+ { (CORE_ADDR) rank }))
{
stride.set_const_val (value);
return static_range_type;
}
-/* Resolves dynamic bound values of an array or string type TYPE to static
- ones. ADDR_STACK is a stack of struct property_addr_info to be used if
- needed during the dynamic resolution.
+/* Helper function for resolve_dynamic_array_or_string. This function
+ resolves the properties for a single array at RANK within a nested array
+ of arrays structure. The RANK value is greater than or equal to 0, and
+ starts at it's maximum value and goes down by 1 for each recursive call
+ to this function. So, for a 3-dimensional array, the first call to this
+ function has RANK == 2, then we call ourselves recursively with RANK ==
+ 1, than again with RANK == 0, and at that point we should return.
+
+ TYPE is updated as the dynamic properties are resolved, and so, should
+ be a copy of the dynamic type, rather than the original dynamic type
+ itself.
+
+ ADDR_STACK is a stack of struct property_addr_info to be used if needed
+ during the dynamic resolution.
When RESOLVE_P is true then the dynamic properties of TYPE are
evaluated, otherwise the dynamic properties of TYPE are not evaluated,
instead we assume the array is not allocated/associated yet. */
static struct type *
-resolve_dynamic_array_or_string (struct type *type,
- struct property_addr_info *addr_stack,
- bool resolve_p = true)
+resolve_dynamic_array_or_string_1 (struct type *type,
+ struct property_addr_info *addr_stack,
+ int rank, bool resolve_p)
{
CORE_ADDR value;
struct type *elt_type;
gdb_assert (type->code () == TYPE_CODE_ARRAY
|| type->code () == TYPE_CODE_STRING);
- type = copy_type (type);
+ /* As the rank is a zero based count we expect this to never be
+ negative. */
+ gdb_assert (rank >= 0);
/* Resolve the allocated and associated properties before doing anything
else. If an array is not allocated or not associated then (at least
}
range_type = check_typedef (type->index_type ());
- range_type = resolve_dynamic_range (range_type, addr_stack, resolve_p);
+ range_type
+ = resolve_dynamic_range (range_type, addr_stack, rank, resolve_p);
ary_dim = check_typedef (TYPE_TARGET_TYPE (type));
if (ary_dim != NULL && ary_dim->code () == TYPE_CODE_ARRAY)
- elt_type = resolve_dynamic_array_or_string (ary_dim, addr_stack, resolve_p);
+ {
+ ary_dim = copy_type (ary_dim);
+ elt_type = resolve_dynamic_array_or_string_1 (ary_dim, addr_stack,
+ rank - 1, resolve_p);
+ }
else
elt_type = TYPE_TARGET_TYPE (type);
bit_stride);
}
+/* Resolve an array or string type with dynamic properties, return a new
+ type with the dynamic properties resolved to actual values. The
+ ADDR_STACK represents the location of the object being resolved. */
+
+static struct type *
+resolve_dynamic_array_or_string (struct type *type,
+ struct property_addr_info *addr_stack)
+{
+ CORE_ADDR value;
+ int rank = 0;
+
+ /* For dynamic type resolution strings can be treated like arrays of
+ characters. */
+ gdb_assert (type->code () == TYPE_CODE_ARRAY
+ || type->code () == TYPE_CODE_STRING);
+
+ type = copy_type (type);
+
+ /* Resolve the rank property to get rank value. */
+ struct dynamic_prop *prop = TYPE_RANK_PROP (type);
+ if (dwarf2_evaluate_property (prop, nullptr, addr_stack, &value))
+ {
+ prop->set_const_val (value);
+ rank = value;
+
+ if (rank == 0)
+ {
+ /* Rank is zero, if a variable is passed as an argument to a
+ function. In this case the resolved type should not be an
+ array, but should instead be that of an array element. */
+ struct type *dynamic_array_type = type;
+ type = copy_type (TYPE_TARGET_TYPE (dynamic_array_type));
+ struct dynamic_prop_list *prop_list
+ = TYPE_MAIN_TYPE (dynamic_array_type)->dyn_prop_list;
+ if (prop_list != nullptr)
+ {
+ struct obstack *obstack
+ = &type->objfile_owner ()->objfile_obstack;
+ TYPE_MAIN_TYPE (type)->dyn_prop_list
+ = copy_dynamic_prop_list (obstack, prop_list);
+ }
+ return type;
+ }
+ else if (type->code () == TYPE_CODE_STRING && rank != 1)
+ {
+ /* What would this even mean? A string with a dynamic rank
+ greater than 1. */
+ error (_("unable to handle string with dynamic rank greater than 1"));
+ }
+ else if (rank > 1)
+ {
+ /* Arrays with dynamic rank are initially just an array type
+ with a target type that is the array element.
+
+ However, now we know the rank of the array we need to build
+ the array of arrays structure that GDB expects, that is we
+ need an array type that has a target which is an array type,
+ and so on, until eventually, we have the element type at the
+ end of the chain. Create all the additional array types here
+ by copying the top level array type. */
+ struct type *element_type = TYPE_TARGET_TYPE (type);
+ struct type *rank_type = type;
+ for (int i = 1; i < rank; i++)
+ {
+ TYPE_TARGET_TYPE (rank_type) = copy_type (rank_type);
+ rank_type = TYPE_TARGET_TYPE (rank_type);
+ }
+ TYPE_TARGET_TYPE (rank_type) = element_type;
+ }
+ }
+ else
+ {
+ rank = 1;
+
+ for (struct type *tmp_type = check_typedef (TYPE_TARGET_TYPE (type));
+ tmp_type->code () == TYPE_CODE_ARRAY;
+ tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type)))
+ ++rank;
+ }
+
+ /* The rank that we calculated above is actually a count of the number of
+ ranks. However, when we resolve the type of each individual array
+ rank we should actually use a rank "offset", e.g. an array with a rank
+ count of 1 (calculated above) will use the rank offset 0 in order to
+ resolve the details of the first array dimension. As a result, we
+ reduce the rank by 1 here. */
+ --rank;
+
+ return resolve_dynamic_array_or_string_1 (type, addr_stack, rank, true);
+}
+
/* Resolve dynamic bounds of members of the union TYPE to static
bounds. ADDR_STACK is a stack of struct property_addr_info
to be used if needed during the dynamic resolution. */
CORE_ADDR addr;
if (dwarf2_evaluate_property (&prop, nullptr, addr_stack, &addr,
- true))
+ {addr_stack->addr}))
resolved_type->field (i).set_loc_bitpos
(TARGET_CHAR_BIT * (addr - addr_stack->addr));
}
break;
case TYPE_CODE_RANGE:
- resolved_type = resolve_dynamic_range (type, addr_stack);
+ /* Pass 0 for the rank value here, which indicates this is a
+ range for the first rank of an array. The assumption is that
+ this rank value is not actually required for the resolution of
+ the dynamic range, otherwise, we'd be resolving this range
+ within the context of a dynamic array. */
+ resolved_type = resolve_dynamic_range (type, addr_stack, 0);
break;
case TYPE_CODE_UNION: