diff options
Diffstat (limited to 'gdb/ada-lang.c')
-rw-r--r-- | gdb/ada-lang.c | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 3b3894c..83f7cf3 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -165,8 +165,7 @@ static struct type *to_fixed_variant_branch_type (struct type *, static struct type *to_fixed_array_type (struct type *, struct value *, int); -static struct type *to_fixed_range_type (char *, struct value *, - struct type *); +static struct type *to_fixed_range_type (struct type *, struct value *); static struct type *to_static_fixed_type (struct type *); static struct type *static_unwrap_type (struct type *type); @@ -1204,6 +1203,61 @@ ada_match_name (const char *sym_name, const char *name, int wild) /* Arrays */ +/* Assuming that INDEX_DESC_TYPE is an ___XA structure, a structure + generated by the GNAT compiler to describe the index type used + for each dimension of an array, check whether it follows the latest + known encoding. If not, fix it up to conform to the latest encoding. + Otherwise, do nothing. This function also does nothing if + INDEX_DESC_TYPE is NULL. + + The GNAT encoding used to describle the array index type evolved a bit. + Initially, the information would be provided through the name of each + field of the structure type only, while the type of these fields was + described as unspecified and irrelevant. The debugger was then expected + to perform a global type lookup using the name of that field in order + to get access to the full index type description. Because these global + lookups can be very expensive, the encoding was later enhanced to make + the global lookup unnecessary by defining the field type as being + the full index type description. + + The purpose of this routine is to allow us to support older versions + of the compiler by detecting the use of the older encoding, and by + fixing up the INDEX_DESC_TYPE to follow the new one (at this point, + we essentially replace each field's meaningless type by the associated + index subtype). */ + +void +ada_fixup_array_indexes_type (struct type *index_desc_type) +{ + int i; + + if (index_desc_type == NULL) + return; + gdb_assert (TYPE_NFIELDS (index_desc_type) > 0); + + /* Check if INDEX_DESC_TYPE follows the older encoding (it is sufficient + to check one field only, no need to check them all). If not, return + now. + + If our INDEX_DESC_TYPE was generated using the older encoding, + the field type should be a meaningless integer type whose name + is not equal to the field name. */ + if (TYPE_NAME (TYPE_FIELD_TYPE (index_desc_type, 0)) != NULL + && strcmp (TYPE_NAME (TYPE_FIELD_TYPE (index_desc_type, 0)), + TYPE_FIELD_NAME (index_desc_type, 0)) == 0) + return; + + /* Fixup each field of INDEX_DESC_TYPE. */ + for (i = 0; i < TYPE_NFIELDS (index_desc_type); i++) + { + char *name = TYPE_FIELD_NAME (index_desc_type, i); + struct type *raw_type = ada_check_typedef (ada_find_any_type (name)); + + if (raw_type) + TYPE_FIELD_TYPE (index_desc_type, i) = raw_type; + } +} + /* Names of MAX_ADA_DIMENS bounds in P_BOUNDS fields of array descriptors. */ static char *bound_name[] = { @@ -2530,9 +2584,10 @@ ada_array_bound_from_type (struct type * arr_type, int n, int which) elt_type = TYPE_TARGET_TYPE (type); index_type_desc = ada_find_parallel_type (type, "___XA"); + ada_fixup_array_indexes_type (index_type_desc); if (index_type_desc != NULL) - index_type = to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n - 1), - NULL, TYPE_INDEX_TYPE (elt_type)); + index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, n - 1), + NULL); else index_type = TYPE_INDEX_TYPE (elt_type); @@ -7150,6 +7205,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, type0 = decode_constrained_packed_array_type (type0); index_type_desc = ada_find_parallel_type (type0, "___XA"); + ada_fixup_array_indexes_type (index_type_desc); if (index_type_desc == NULL) { struct type *elt_type0 = ada_check_typedef (TYPE_TARGET_TYPE (type0)); @@ -7202,8 +7258,7 @@ to_fixed_array_type (struct type *type0, struct value *dval, for (i = TYPE_NFIELDS (index_type_desc) - 1; i >= 0; i -= 1) { struct type *range_type = - to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i), - dval, TYPE_INDEX_TYPE (elt_type0)); + to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, i), dval); result = create_array_type (alloc_type_copy (elt_type0), result, range_type); elt_type0 = TYPE_TARGET_TYPE (elt_type0); @@ -9182,7 +9237,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, char *name = ada_type_name (type_arg); range_type = NULL; if (name != NULL && TYPE_CODE (type_arg) != TYPE_CODE_ENUM) - range_type = to_fixed_range_type (name, NULL, type_arg); + range_type = to_fixed_range_type (type_arg, NULL); if (range_type == NULL) range_type = type_arg; switch (op) @@ -9704,21 +9759,21 @@ get_int_var_value (char *name, int *flag) in NAME, the base type given in the named range type. */ static struct type * -to_fixed_range_type (char *name, struct value *dval, struct type *orig_type) +to_fixed_range_type (struct type *raw_type, struct value *dval) { - struct type *raw_type = ada_find_any_type (name); + char *name; struct type *base_type; char *subtype_info; - /* Fall back to the original type if symbol lookup failed. */ - if (raw_type == NULL) - raw_type = orig_type; + gdb_assert (raw_type != NULL); + gdb_assert (TYPE_NAME (raw_type) != NULL); if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE) base_type = TYPE_TARGET_TYPE (raw_type); else base_type = raw_type; + name = TYPE_NAME (raw_type); subtype_info = strstr (name, "___XD"); if (subtype_info == NULL) { @@ -9727,7 +9782,7 @@ to_fixed_range_type (char *name, struct value *dval, struct type *orig_type) if (L < INT_MIN || U > INT_MAX) return raw_type; else - return create_range_type (alloc_type_copy (orig_type), raw_type, + return create_range_type (alloc_type_copy (raw_type), raw_type, ada_discrete_type_low_bound (raw_type), ada_discrete_type_high_bound (raw_type)); } @@ -9790,7 +9845,7 @@ to_fixed_range_type (char *name, struct value *dval, struct type *orig_type) } } - type = create_range_type (alloc_type_copy (orig_type), base_type, L, U); + type = create_range_type (alloc_type_copy (raw_type), base_type, L, U); TYPE_NAME (type) = name; return type; } |