aboutsummaryrefslogtreecommitdiff
path: root/gdb/ada-lang.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/ada-lang.c')
-rw-r--r--gdb/ada-lang.c83
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;
}