diff options
author | Tom Tromey <tromey@adacore.com> | 2020-05-26 14:11:08 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2020-05-26 14:11:08 -0600 |
commit | 53a47a3e4904839a902e34d4dfd3f53c397d66e1 (patch) | |
tree | fafe61c8dc8c7d8bda8b5b00278ba0e6f571db49 /gdb/valprint.c | |
parent | 0bc2354b811e913b39c288e74d7166eaa3639309 (diff) | |
download | gdb-53a47a3e4904839a902e34d4dfd3f53c397d66e1.zip gdb-53a47a3e4904839a902e34d4dfd3f53c397d66e1.tar.gz gdb-53a47a3e4904839a902e34d4dfd3f53c397d66e1.tar.bz2 |
Handle indexing Ada arrays with enum indices
In Ada, like C, an enum can assign values to the constants. However,
unlike C (or any other language supported by gdb), the enum type can
also be used as the range of an array.
In this case, the user's code references the enum constants, but the
compiler translates these to the position of the constant in the enum.
So for example one might write:
type Enum_With_Gaps is
(
LIT0,
LIT1,
LIT2,
LIT3,
LIT4
);
for Enum_With_Gaps use
(
LIT0 => 3,
LIT1 => 5,
LIT2 => 8,
LIT3 => 13,
LIT4 => 21
);
Then index an array like "array(LIT3)" -- but this will be the 4th
element in an array of 5 elements, not the 13th element in an array of
19 (assuming I did the math right) elements.
gdb supports this to some degree, with the only missing piece being
indexing into such an array. This patch implements this missing
feature, and also fixes an existing bug, which is that in some
situations I believe gdb would mis-compute the resulting array's
length.
The approach taken here is to try to integrate this feature into the
core of gdb. My view is that much of the Ada support should be better
integrated with gdb, rather than being "on the side". This, I think,
would help avoid code duplication at least. So, I try to take steps
toward this goal when possible.
Because other languages generally don't allow the user to specify the
index type of an array, I simply made the core of gdb unconditionally
apply discrete_position when computing the range of such an array.
This is a no-op for ordinary types, but applies the enum
value-to-position transformation for TYPE_CODE_ENUM.
gdb/ChangeLog
2020-05-26 Tom Tromey <tromey@adacore.com>
* ada-lang.c (ada_print_array_index): Change type. Call val_atr.
(ada_value_ptr_subscript): Don't call pos_atr on the lower bound.
(val_atr): New function.
(value_val_atr): Use it.
* ada-valprint.c (print_optional_low_bound): Change low bound
handling for enums.
(val_print_packed_array_elements): Don't call discrete_position.
* gdbtypes.c (get_discrete_bounds) <TYPE_CODE_RANGE>: Call
discrete_position for enum types.
* language.c (default_print_array_index): Change type.
* language.h (struct language_defn) <la_print_array_index>: Add
index_type parameter, change type of index_value.
(LA_PRINT_ARRAY_INDEX): Add index_type parameter.
(default_print_array_index): Update.
* valprint.c (maybe_print_array_index): Don't call
value_from_longest. Update.
(value_print_array_elements): Don't call discrete_position.
gdb/testsuite/ChangeLog
2020-05-26 Tom Tromey <tromey@adacore.com>
* gdb.ada/arr_acc_idx_w_gap.exp: Add tests.
Diffstat (limited to 'gdb/valprint.c')
-rw-r--r-- | gdb/valprint.c | 43 |
1 files changed, 11 insertions, 32 deletions
diff --git a/gdb/valprint.c b/gdb/valprint.c index 17d091d..d678ad3 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -1851,14 +1851,10 @@ maybe_print_array_index (struct type *index_type, LONGEST index, struct ui_file *stream, const struct value_print_options *options) { - struct value *index_value; - if (!options->print_array_indexes) return; - index_value = value_from_longest (index_type, index); - - LA_PRINT_ARRAY_INDEX (index_value, stream, options); + LA_PRINT_ARRAY_INDEX (index_type, index, stream, options); } /* See valprint.h. */ @@ -1871,7 +1867,7 @@ value_print_array_elements (struct value *val, struct ui_file *stream, { unsigned int things_printed = 0; unsigned len; - struct type *elttype, *index_type, *base_index_type; + struct type *elttype, *index_type; unsigned eltlen; /* Position of the array element we are examining to see whether it is repeated. */ @@ -1879,43 +1875,26 @@ value_print_array_elements (struct value *val, struct ui_file *stream, /* Number of repetitions we have detected so far. */ unsigned int reps; LONGEST low_bound, high_bound; - LONGEST low_pos, high_pos; struct type *type = check_typedef (value_type (val)); elttype = TYPE_TARGET_TYPE (type); eltlen = type_length_units (check_typedef (elttype)); index_type = TYPE_INDEX_TYPE (type); + if (index_type->code () == TYPE_CODE_RANGE) + index_type = TYPE_TARGET_TYPE (index_type); if (get_array_bounds (type, &low_bound, &high_bound)) { - if (index_type->code () == TYPE_CODE_RANGE) - base_index_type = TYPE_TARGET_TYPE (index_type); - else - base_index_type = index_type; - - /* Non-contiguous enumerations types can by used as index types - in some languages (e.g. Ada). In this case, the array length - shall be computed from the positions of the first and last - literal in the enumeration type, and not from the values - of these literals. */ - if (!discrete_position (base_index_type, low_bound, &low_pos) - || !discrete_position (base_index_type, high_bound, &high_pos)) - { - warning (_("unable to get positions in array, use bounds instead")); - low_pos = low_bound; - high_pos = high_bound; - } - - /* The array length should normally be HIGH_POS - LOW_POS + 1. - But we have to be a little extra careful, because some languages - such as Ada allow LOW_POS to be greater than HIGH_POS for - empty arrays. In that situation, the array length is just zero, - not negative! */ - if (low_pos > high_pos) + /* The array length should normally be HIGH_BOUND - LOW_BOUND + + 1. But we have to be a little extra careful, because some + languages such as Ada allow LOW_BOUND to be greater than + HIGH_BOUND for empty arrays. In that situation, the array + length is just zero, not negative! */ + if (low_bound > high_bound) len = 0; else - len = high_pos - low_pos + 1; + len = high_bound - low_bound + 1; } else { |