aboutsummaryrefslogtreecommitdiff
path: root/gdb/ada-lang.c
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2010-12-29 08:01:32 +0000
committerJoel Brobecker <brobecker@gnat.com>2010-12-29 08:01:32 +0000
commit720d1a4025df48e7f8fd6426e4f518c02ad3208a (patch)
tree8f72a5bc2284a330fba516511759384738a7cd94 /gdb/ada-lang.c
parent113a6f1ec903a7b627723d2c913d75c3a37e421c (diff)
downloadgdb-720d1a4025df48e7f8fd6426e4f518c02ad3208a.zip
gdb-720d1a4025df48e7f8fd6426e4f518c02ad3208a.tar.gz
gdb-720d1a4025df48e7f8fd6426e4f518c02ad3208a.tar.bz2
[Ada] do not print arrays as array pointers
This patch enhances the debugger to distinguish between fat pointers that represent either: array types, or array access types. In the latter case, the object/type is encoded as a typedef type pointing to the fat pointer. The first part of the change is to adjust ada_check_typedef to avoid stripping the typedef layer when it points to a fat pointer. The rest of the patch is adjustments required in various places to deal with the fact that the type is uses might now be a typedef. gdb/ChangeLog: * ada-lang.h (ada_coerce_to_simple_array): Add declaration. * ada-lang.c (ada_typedef_target_type): New function. (desc_base_type): Add handling of fat pointer typedefs. (ada_coerce_to_simple_array): Make non-static. (decode_packed_array_bitsize): Add handling of fat pointer typedefs. Add assertion. (ada_template_to_fixed_record_type_1, ada_to_fixed_type) (ada_check_typedef): Add handling of fat pointer typedefs. (ada_evaluate_subexp) [OP_FUNCALL]: Likewise. * ada-typeprint.c (ada_print_type): Add handling of fat pointer typedefs. * ada-valprint.c (ada_val_print_1): Convert fat pointers that are not array accesses to simple arrays rather than simple array pointers. (ada_value_print): In the case of array descriptors, do not print the value type description unless it is an array access. gdb/testsuite/ChangeLog: * gdb.ada/lang_switch.exp: Correct expected parameter value. gdb/doc/ChangeLog: * gdb.texinfo (Ada Glitches): Remove paragraph describing the occasional case where the debugger prints an array address instead of the array itself.
Diffstat (limited to 'gdb/ada-lang.c')
-rw-r--r--gdb/ada-lang.c79
1 files changed, 74 insertions, 5 deletions
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 7ea01c7..3a5b10f 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -228,8 +228,6 @@ static int ada_resolve_function (struct ada_symbol_info *, int,
struct value **, int, const char *,
struct type *);
-static struct value *ada_coerce_to_simple_array (struct value *);
-
static int ada_is_direct_array_type (struct type *);
static void ada_language_arch_info (struct gdbarch *,
@@ -366,6 +364,41 @@ ada_inferior_exit (struct inferior *inf)
/* Utilities */
+/* If TYPE is a TYPE_CODE_TYPEDEF type, return the target type after
+ all typedef layers have been pealed. Otherwise, return TYPE.
+
+ Normally, we really expect a typedef type to only have 1 typedef layer.
+ In other words, we really expect the target type of a typedef type to be
+ a non-typedef type. This is particularly true for Ada units, because
+ the language does not have a typedef vs not-typedef distinction.
+ In that respect, the Ada compiler has been trying to eliminate as many
+ typedef definitions in the debugging information, since they generally
+ do not bring any extra information (we still use typedef under certain
+ circumstances related mostly to the GNAT encoding).
+
+ Unfortunately, we have seen situations where the debugging information
+ generated by the compiler leads to such multiple typedef layers. For
+ instance, consider the following example with stabs:
+
+ .stabs "pck__float_array___XUP:Tt(0,46)=s16P_ARRAY:(0,47)=[...]"[...]
+ .stabs "pck__float_array___XUP:t(0,36)=(0,46)",128,0,6,0
+
+ This is an error in the debugging information which causes type
+ pck__float_array___XUP to be defined twice, and the second time,
+ it is defined as a typedef of a typedef.
+
+ This is on the fringe of legality as far as debugging information is
+ concerned, and certainly unexpected. But it is easy to handle these
+ situations correctly, so we can afford to be lenient in this case. */
+
+static struct type *
+ada_typedef_target_type (struct type *type)
+{
+ while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ type = TYPE_TARGET_TYPE (type);
+ return type;
+}
+
/* Given DECODED_NAME a string holding a symbol name in its
decoded form (ie using the Ada dotted notation), returns
its unqualified name. */
@@ -1354,6 +1387,9 @@ desc_base_type (struct type *type)
if (type == NULL)
return NULL;
type = ada_check_typedef (type);
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ type = ada_typedef_target_type (type);
+
if (type != NULL
&& (TYPE_CODE (type) == TYPE_CODE_PTR
|| TYPE_CODE (type) == TYPE_CODE_REF))
@@ -1819,7 +1855,7 @@ ada_coerce_to_simple_array_ptr (struct value *arr)
Otherwise, returns a standard GDB array describing ARR (which may
be ARR itself if it already is in the proper form). */
-static struct value *
+struct value *
ada_coerce_to_simple_array (struct value *arr)
{
if (ada_is_array_descriptor_type (value_type (arr)))
@@ -1893,10 +1929,17 @@ ada_is_unconstrained_packed_array_type (struct type *type)
static long
decode_packed_array_bitsize (struct type *type)
{
- char *raw_name = ada_type_name (ada_check_typedef (type));
+ char *raw_name;
char *tail;
long bits;
+ /* Access to arrays implemented as fat pointers are encoded as a typedef
+ of the fat pointer type. We need the name of the fat pointer type
+ to do the decoding, so strip the typedef layer. */
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ type = ada_typedef_target_type (type);
+
+ raw_name = ada_type_name (ada_check_typedef (type));
if (!raw_name)
raw_name = ada_type_name (desc_base_type (type));
@@ -1904,6 +1947,7 @@ decode_packed_array_bitsize (struct type *type)
return 0;
tail = strstr (raw_name, "___XP");
+ gdb_assert (tail != NULL);
if (sscanf (tail + sizeof ("___XP") - 1, "%ld", &bits) != 1)
{
@@ -7146,6 +7190,15 @@ ada_template_to_fixed_record_type_1 (struct type *type,
{
struct type *field_type = TYPE_FIELD_TYPE (type, f);
+ /* If our field is a typedef type (most likely a typedef of
+ a fat pointer, encoding an array access), then we need to
+ look at its target type to determine its characteristics.
+ In particular, we would miscompute the field size if we took
+ the size of the typedef (zero), instead of the size of
+ the target type. */
+ if (TYPE_CODE (field_type) == TYPE_CODE_TYPEDEF)
+ field_type = ada_typedef_target_type (field_type);
+
TYPE_FIELD_TYPE (rtype, f) = field_type;
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
if (TYPE_FIELD_BITSIZE (type, f) > 0)
@@ -7703,7 +7756,7 @@ ada_to_fixed_type (struct type *type, const gdb_byte *valaddr,
because we call check_typedef/ada_check_typedef pretty much everywhere.
*/
if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
- && (TYPE_MAIN_TYPE (TYPE_TARGET_TYPE (type))
+ && (TYPE_MAIN_TYPE (ada_typedef_target_type (type))
== TYPE_MAIN_TYPE (fixed_type)))
return type;
@@ -7789,6 +7842,15 @@ ada_check_typedef (struct type *type)
if (type == NULL)
return NULL;
+ /* If our type is a typedef type of a fat pointer, then we're done.
+ We don't want to strip the TYPE_CODE_TYPDEF layer, because this is
+ what allows us to distinguish between fat pointers that represent
+ array types, and fat pointers that represent array access types
+ (in both cases, the compiler implements them as fat pointers). */
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
+ && is_thick_pntr (ada_typedef_target_type (type)))
+ return type;
+
CHECK_TYPEDEF (type);
if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
|| !TYPE_STUB (type)
@@ -9282,6 +9344,13 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
argvec[0] = value_addr (argvec[0]);
type = ada_check_typedef (value_type (argvec[0]));
+
+ /* Ada allows us to implicitly dereference arrays when subscripting
+ them. So, if this is an typedef (encoding use for array access
+ types encoded as fat pointers), strip it now. */
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ type = ada_typedef_target_type (type);
+
if (TYPE_CODE (type) == TYPE_CODE_PTR)
{
switch (TYPE_CODE (ada_check_typedef (TYPE_TARGET_TYPE (type))))