[rfa/Ada] Restructure fixed array range fall-back to remove builtin types

Ulrich Weigand
2009-06-26T15:53:38Z

Hello Joel,

this patch attempts to address use of current_gdbarch and global builtin
types in to_fixed_range_type. This routine decodes range information from
field names of the _XA parallel types that are associated with array types.

If symbol lookup for the type name decoded from that field name fails,
the routine today uses two fall-back strategies:
- check for a language-primitive type of that name (using current_gdbarch)
- if that fails as well, use a global built-in (builtin_type_int32)

It seems to me that a simpler, and at the same time presumably more
accurate, fall-back type to use would be the range type of the *original*
array type. This original type cannot in general be used as-is because
the array bounds and step information may not always be encoded correctly.

However, it should still be a proper integral type of the correct size
-- and thus at least as appropriate as a default fall-back as the one
determined by the current logic.

This patch implements that logic in to_fixed_range_type and the analogous
print_range_type_named routine.

I've tested this on amd64-linux with no regressions, however that doesn't
say much, as the FSF mainline Ada compiler often doesn't even generate _XA
types (the front-end generates them, but the middle-end never emits them
because it considers them unused ...). After hacking the compiler to in
fact generate those types, I still never saw a situation where GDB would
actually have to run into that fall-back case. If you have test cases
that require the fall back behaviour, I'd appreciate it if could verify
the patch against those.

Would this be OK for mainline?

Bye,
Ulrich

ChangeLog:

* ada-lang.c (to_fixed_range_type): Add ORIG_TYPE argument.
Fall back to orig_type as index type if symbol lookup fails.
Allocate result types from ORIG_TYPE's objfile.
(ada_array_bound_from_type, to_fixed_array_type,
ada_evaluate_subexp): Pass original index type to
to_fixed_range_type. Do not pass objfile.

* ada-typeprint.c (print_range_type_named): Add ORIG_TYPE argument.
Fall back to orig_type as index type if symbol lookup fails.
(print_array_type, ada_print_type): Pass original index type
to print_range_type_named.

Index: gdb-head/gdb/ada-lang.c
===================================================================
--- gdb-head.orig/gdb/ada-lang.c
+++ gdb-head/gdb/ada-lang.c
@@ -168,7 +168,7 @@ static struct type *to_fixed_variant_bra
static struct type *to_fixed_array_type (struct type *, struct value *, int);

static struct type *to_fixed_range_type (char *, struct value *,
- struct objfile *);
+ struct type *);

static struct type *to_static_fixed_type (struct type *);
static struct type *static_unwrap_type (struct type *type);
@@ -2452,8 +2452,9 @@ ada_index_type (struct type *type, int n
static LONGEST
ada_array_bound_from_type (struct type * arr_type, int n, int which)
{
- struct type *type, *index_type_desc, *index_type;
+ struct type *type, *elt_type, *index_type_desc, *index_type;
LONGEST retval;
+ int i;

gdb_assert (which == 0 || which == 1);

@@ -2468,20 +2469,16 @@ ada_array_bound_from_type (struct type *
else
type = arr_type;

+ elt_type = type;
+ for (i = n; i > 1; i--)
+ elt_type = TYPE_TARGET_TYPE (type);
+
index_type_desc = ada_find_parallel_type (type, "___XA");
if (index_type_desc != NULL)
index_type = to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n - 1),
- NULL, TYPE_OBJFILE (arr_type));
+ NULL, TYPE_INDEX_TYPE (elt_type));
else
- {
- while (n > 1)
- {
- type = TYPE_TARGET_TYPE (type);
- n -= 1;
- }
-
- index_type = TYPE_INDEX_TYPE (type);
- }
+ index_type = TYPE_INDEX_TYPE (elt_type);

switch (TYPE_CODE (index_type))
{
@@ -7192,13 +7189,16 @@ to_fixed_array_type (struct type *type0,
consult the object tag. */
result =
ada_to_fixed_type (ada_check_typedef (elt_type0), 0, 0, dval, 1);
+
+ elt_type0 = type0;
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_OBJFILE (type0));
- result = create_array_type (alloc_type (TYPE_OBJFILE (type0)),
+ dval, TYPE_INDEX_TYPE (elt_type0));
+ result = create_array_type (alloc_type (TYPE_OBJFILE (elt_type0)),
result, range_type);
+ elt_type0 = TYPE_TARGET_TYPE (elt_type0);
}
if (!ignore_too_big && TYPE_LENGTH (result) > varsize_limit)
error (_("array type with dynamic size is larger than varsize-limit"));
@@ -9124,8 +9124,7 @@ ada_evaluate_subexp (struct type *expect
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_OBJFILE (type_arg));
+ range_type = to_fixed_range_type (name, NULL, type_arg);
if (range_type == NULL)
range_type = type_arg;
switch (op)
@@ -9685,26 +9684,24 @@ get_int_var_value (char *name, int *flag
/* Return a range type whose base type is that of the range type named
NAME in the current environment, and whose bounds are calculated
from NAME according to the GNAT range encoding conventions.
- Extract discriminant values, if needed, from DVAL. If a new type
- must be created, allocate in OBJFILE's space. The bounds
- information, in general, is encoded in NAME, the base type given in
- the named range type. */
+ Extract discriminant values, if needed, from DVAL. ORIG_TYPE is the
+ corresponding range type from debug information; fall back to using it
+ if symbol lookup fails. If a new type must be created, allocate it
+ like ORIG_TYPE was. The bounds information, in general, is encoded
+ in NAME, the base type given in the named range type. */

static struct type *
-to_fixed_range_type (char *name, struct value *dval, struct objfile *objfile)
+to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
{
struct type *raw_type = ada_find_any_type (name);
struct type *base_type;
char *subtype_info;

- /* Also search primitive types if type symbol could not be found. */
+ /* Fall back to the original type if symbol lookup failed. */
if (raw_type == NULL)
- raw_type = language_lookup_primitive_type_by_name
- (language_def (language_ada), current_gdbarch, name);
+ raw_type = orig_type;

- if (raw_type == NULL)
- base_type = builtin_type_int32;
- else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
+ if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
base_type = TYPE_TARGET_TYPE (raw_type);
else
base_type = raw_type;
@@ -9717,7 +9714,8 @@ to_fixed_range_type (char *name, struct
if (L < INT_MIN || U > INT_MAX)
return raw_type;
else
- return create_range_type (alloc_type (objfile), raw_type,
+ return create_range_type (alloc_type (TYPE_OBJFILE (orig_type)),
+ raw_type,
discrete_type_low_bound (raw_type),
discrete_type_high_bound (raw_type));
}
@@ -9780,9 +9778,8 @@ to_fixed_range_type (char *name, struct
}
}

- if (objfile == NULL)
- objfile = TYPE_OBJFILE (base_type);
- type = create_range_type (alloc_type (objfile), base_type, L, U);
+ type = create_range_type (alloc_type (TYPE_OBJFILE (orig_type)),
+ base_type, L, U);
TYPE_NAME (type) = name;
return type;
}
Index: gdb-head/gdb/ada-typeprint.c
===================================================================
--- gdb-head.orig/gdb/ada-typeprint.c
+++ gdb-head/gdb/ada-typeprint.c
@@ -55,7 +55,7 @@ static void
print_dynamic_range_bound (struct type *, const char *, int,
const char *, struct ui_file *);

-static void print_range_type_named (char *, struct ui_file *);
+static void print_range_type_named (char *, struct type *, struct ui_file *);
\f

@@ -233,26 +233,27 @@ print_dynamic_range_bound (struct type *
fprintf_filtered (stream, "?");
}

-/* Print the range type named NAME. */
+/* Print the range type named NAME. If symbol lookup fails, fall back
+ to ORIG_TYPE as base type. */

static void
-print_range_type_named (char *name, struct ui_file *stream)
+print_range_type_named (char *name, struct type *orig_type,
+ struct ui_file *stream)
{
struct type *raw_type = ada_find_any_type (name);
struct type *base_type;
char *subtype_info;

if (raw_type == NULL)
- base_type = builtin_type_int32;
- else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
+ raw_type = orig_type;
+
+ if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
base_type = TYPE_TARGET_TYPE (raw_type);
else
base_type = raw_type;

subtype_info = strstr (name, "___XD");
- if (subtype_info == NULL && raw_type == NULL)
- fprintf_filtered (stream, "? .. ?");
- else if (subtype_info == NULL)
+ if (subtype_info == NULL)
print_range (raw_type, stream);
else
{
@@ -398,7 +399,8 @@ print_array_type (struct type *type, str
if (k > 0)
fprintf_filtered (stream, ", ");
print_range_type_named (TYPE_FIELD_NAME
- (range_desc_type, k), stream);
+ (range_desc_type, k),
+ TYPE_INDEX_TYPE (arr_type), stream);
if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
}
@@ -816,7 +818,7 @@ ada_print_type (struct type *type0, char
else
{
fprintf_filtered (stream, "range ");
- print_range_type_named (name, stream);
+ print_range_type_named (name, type, stream);
}
}
break;
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com