diff options
author | Jerome Guitton <guitton@adacore.com> | 2015-03-27 14:45:08 +0100 |
---|---|---|
committer | Joel Brobecker <brobecker@adacore.com> | 2015-05-15 14:03:46 -0700 |
commit | aa7151351ed16c5a4eb1334c9a1af1b06dbb7a99 (patch) | |
tree | 44c933eb16bda42b110800a9e3cce8ce744a5174 /gdb/ada-lang.c | |
parent | 931e5bc3e19d1e279fc28c5cf5571f812c79b8d3 (diff) | |
download | gdb-aa7151351ed16c5a4eb1334c9a1af1b06dbb7a99.zip gdb-aa7151351ed16c5a4eb1334c9a1af1b06dbb7a99.tar.gz gdb-aa7151351ed16c5a4eb1334c9a1af1b06dbb7a99.tar.bz2 |
Array indexed by non-contiguous enumeration types
In Ada, index types of arrays can be enumeration types, and enumeration
types can be non-contiguous. In which case the address of elements is
not given by the value of the index, but by its position in the enumeration
type.
In other words, in this example:
type Color is (Blue, Red);
for Color use (Blue => 8, Red => 12, Green => 16);
type A is array (Color) of Integer;
type B is array (1 .. 3) of Integer;
Arrays of type A and B will have the same layout in memory, even if
the enumeration Color has a hole in its set of integer value.
Since recently support for such a feature was in ada-lang.c, where the
array was casted to a regular continuous index range. We were losing
the information of index type. And this was not quite working for
subranges in variable-length fields; their bounds are expressed using
the integer value of the bounds, not its position in the enumeration,
and there was some confusion all over ada-lang.c as to whether we had
the position or the integer value was used for indexes.
The idea behind this patch is to clean this up by keeping the real
representation of these array index types and bounds when representing
the value, and only use the position when accessing the elements or
computing the length. This first patch fixes the printing of such
an array.
To the best of my knowledge, this feature only exists in Ada so it
should only affect this language.
gdb/ChangeLog:
Jerome Guitton <guitton@adacore.com>:
* ada-lang.c (ada_value_ptr_subscript): Use enum position of
index to get element instead of enum value.
(ada_value_slice_from_ptr, ada_value_slice): Use enum position
of index to compute length, but enum values to compute bounds.
(ada_array_length): Use enum position of index instead of enum value.
(pos_atr): Move position computation to...
(ada_evaluate_subexp): Use enum values to compute bounds.
* gdbtypes.c (discrete_position): ...this new function.
* gdbtypes.h (discrete_position): New function declaration.
* valprint.c (val_print_array_elements): Call discrete_position
to handle array indexed by non-contiguous enumeration types.
gdb/testsuite/ChangeLog:
* gdb.ada/arr_enum_with_gap: New testcase.
Diffstat (limited to 'gdb/ada-lang.c')
-rw-r--r-- | gdb/ada-lang.c | 96 |
1 files changed, 65 insertions, 31 deletions
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 02d82ef..f789108 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -2765,13 +2765,15 @@ ada_value_ptr_subscript (struct value *arr, int arity, struct value **ind) for (k = 0; k < arity; k += 1) { LONGEST lwb, upb; + struct value *lwb_value; if (TYPE_CODE (type) != TYPE_CODE_ARRAY) error (_("too many subscripts (%d expected)"), k); arr = value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), value_copy (arr)); get_discrete_bounds (TYPE_INDEX_TYPE (type), &lwb, &upb); - arr = value_ptradd (arr, pos_atr (ind[k]) - lwb); + lwb_value = value_from_longest (value_type(ind[k]), lwb); + arr = value_ptradd (arr, pos_atr (ind[k]) - pos_atr (lwb_value)); type = TYPE_TARGET_TYPE (type); } @@ -2779,24 +2781,34 @@ ada_value_ptr_subscript (struct value *arr, int arity, struct value **ind) } /* Given that ARRAY_PTR is a pointer or reference to an array of type TYPE (the - actual type of ARRAY_PTR is ignored), returns the Ada slice of HIGH-LOW+1 - elements starting at index LOW. The lower bound of this array is LOW, as - per Ada rules. */ + actual type of ARRAY_PTR is ignored), returns the Ada slice of + HIGH'Pos-LOW'Pos+1 elements starting at index LOW. The lower bound of + this array is LOW, as per Ada rules. */ static struct value * ada_value_slice_from_ptr (struct value *array_ptr, struct type *type, int low, int high) { struct type *type0 = ada_check_typedef (type); - CORE_ADDR base = value_as_address (array_ptr) - + ((low - ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0))) - * TYPE_LENGTH (TYPE_TARGET_TYPE (type0))); + struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)); struct type *index_type - = create_static_range_type (NULL, - TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)), - low, high); + = create_static_range_type (NULL, base_index_type, low, high); struct type *slice_type = create_array_type (NULL, TYPE_TARGET_TYPE (type0), index_type); + int base_low = ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0)); + LONGEST base_low_pos, low_pos; + CORE_ADDR base; + + if (!discrete_position (base_index_type, low, &low_pos) + || !discrete_position (base_index_type, base_low, &base_low_pos)) + { + warning (_("unable to get positions in slice, use bounds instead")); + low_pos = low; + base_low_pos = base_low; + } + base = value_as_address (array_ptr) + + ((low_pos - base_low_pos) + * TYPE_LENGTH (TYPE_TARGET_TYPE (type0))); return value_at_lazy (slice_type, base); } @@ -2805,12 +2817,23 @@ static struct value * ada_value_slice (struct value *array, int low, int high) { struct type *type = ada_check_typedef (value_type (array)); + struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type)); struct type *index_type = create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high); struct type *slice_type = create_array_type (NULL, TYPE_TARGET_TYPE (type), index_type); + LONGEST low_pos, high_pos; - return value_cast (slice_type, value_slice (array, low, high - low + 1)); + if (!discrete_position (base_index_type, low, &low_pos) + || !discrete_position (base_index_type, high, &high_pos)) + { + warning (_("unable to get positions in slice, use bounds instead")); + low_pos = low; + high_pos = high; + } + + return value_cast (slice_type, + value_slice (array, low, high_pos - low_pos + 1)); } /* If type is a record type in the form of a standard GNAT array @@ -3012,7 +3035,8 @@ ada_array_bound (struct value *arr, int n, int which) static LONGEST ada_array_length (struct value *arr, int n) { - struct type *arr_type; + struct type *arr_type, *index_type; + int low, high; if (TYPE_CODE (check_typedef (value_type (arr))) == TYPE_CODE_PTR) arr = value_ind (arr); @@ -3022,11 +3046,30 @@ ada_array_length (struct value *arr, int n) return ada_array_length (decode_constrained_packed_array (arr), n); if (ada_is_simple_array_type (arr_type)) - return (ada_array_bound_from_type (arr_type, n, 1) - - ada_array_bound_from_type (arr_type, n, 0) + 1); + { + low = ada_array_bound_from_type (arr_type, n, 0); + high = ada_array_bound_from_type (arr_type, n, 1); + } else - return (value_as_long (desc_one_bound (desc_bounds (arr), n, 1)) - - value_as_long (desc_one_bound (desc_bounds (arr), n, 0)) + 1); + { + low = value_as_long (desc_one_bound (desc_bounds (arr), n, 0)); + high = value_as_long (desc_one_bound (desc_bounds (arr), n, 1)); + } + + CHECK_TYPEDEF (arr_type); + index_type = TYPE_INDEX_TYPE (arr_type); + if (index_type != NULL) + { + struct type *base_type; + if (TYPE_CODE (index_type) == TYPE_CODE_RANGE) + base_type = TYPE_TARGET_TYPE (index_type); + else + base_type = index_type; + + low = pos_atr (value_from_longest (base_type, low)); + high = pos_atr (value_from_longest (base_type, high)); + } + return high - low + 1; } /* An empty array whose type is that of ARR_TYPE (an array type), @@ -8995,24 +9038,15 @@ pos_atr (struct value *arg) { struct value *val = coerce_ref (arg); struct type *type = value_type (val); + LONGEST result; if (!discrete_type_p (type)) error (_("'POS only defined on discrete types")); - if (TYPE_CODE (type) == TYPE_CODE_ENUM) - { - int i; - LONGEST v = value_as_long (val); + if (!discrete_position (type, value_as_long (val), &result)) + error (_("enumeration value is invalid: can't find 'POS")); - for (i = 0; i < TYPE_NFIELDS (type); i += 1) - { - if (v == TYPE_FIELD_ENUMVAL (type, i)) - return i; - } - error (_("enumeration value is invalid: can't find 'POS")); - } - else - return value_as_long (val); + return result; } static struct value * @@ -10613,8 +10647,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, low_bound_val = coerce_ref (low_bound_val); high_bound_val = coerce_ref (high_bound_val); - low_bound = pos_atr (low_bound_val); - high_bound = pos_atr (high_bound_val); + low_bound = value_as_long (low_bound_val); + high_bound = value_as_long (high_bound_val); if (noside == EVAL_SKIP) goto nosideret; |