From 720d1a4025df48e7f8fd6426e4f518c02ad3208a Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Wed, 29 Dec 2010 08:01:32 +0000 Subject: [PATCH] [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. --- gdb/ChangeLog | 18 ++++++++ gdb/ada-lang.c | 79 ++++++++++++++++++++++++++++++++--- gdb/ada-lang.h | 2 + gdb/ada-typeprint.c | 1 + gdb/ada-valprint.c | 17 ++++++-- gdb/doc/ChangeLog | 6 +++ gdb/doc/gdb.texinfo | 7 ---- gdb/testsuite/ChangeLog | 4 ++ gdb/testsuite/gdb.ada/lang_switch.exp | 2 +- 9 files changed, 119 insertions(+), 17 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 717d883..e1f238e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,23 @@ 2010-12-29 Joel Brobecker + * 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. + +2010-12-29 Joel Brobecker + * target.h (enum target_object): Expand the documentation of TARGET_OBJECT_OSDATA a bit. 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)))) diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h index 0cd20df..1aac7b2 100644 --- a/gdb/ada-lang.h +++ b/gdb/ada-lang.h @@ -197,6 +197,8 @@ struct type *ada_type_of_array (struct value *, int); extern struct value *ada_coerce_to_simple_array_ptr (struct value *); +struct value *ada_coerce_to_simple_array (struct value *); + extern int ada_is_simple_array_type (struct type *); extern int ada_is_array_descriptor_type (struct type *); diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c index 677a6aa..f58f599 100644 --- a/gdb/ada-typeprint.c +++ b/gdb/ada-typeprint.c @@ -796,6 +796,7 @@ ada_print_type (struct type *type0, const char *varstring, fprintf_filtered (stream, ">"); break; case TYPE_CODE_PTR: + case TYPE_CODE_TYPEDEF: fprintf_filtered (stream, "access "); ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level); break; diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c index ae2a47d..b5d4b02 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -684,7 +684,10 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr0, struct value *val; val = value_from_contents_and_address (type, valaddr, address); - val = ada_coerce_to_simple_array_ptr (val); + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) /* array access type. */ + val = ada_coerce_to_simple_array_ptr (val); + else + val = ada_coerce_to_simple_array (val); if (val == NULL) { fprintf_filtered (stream, "(null)"); @@ -947,9 +950,15 @@ ada_value_print (struct value *val0, struct ui_file *stream, } else if (ada_is_array_descriptor_type (type)) { - fprintf_filtered (stream, "("); - type_print (type, "", stream, -1); - fprintf_filtered (stream, ") "); + /* We do not print the type description unless TYPE is an array + access type (this is encoded by the compiler as a typedef to + a fat pointer - hence the check against TYPE_CODE_TYPEDEF). */ + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + { + fprintf_filtered (stream, "("); + type_print (type, "", stream, -1); + fprintf_filtered (stream, ") "); + } } else if (ada_is_bogus_array_descriptor (type)) { diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 31e35d3..0d1ec08 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2010-12-29 Joel Brobecker + + * gdb.texinfo (Ada Glitches): Remove paragraph describing the + occasional case where the debugger prints an array address + instead of the array itself. + 2010-12-23 Pedro Alves * gdb.texinfo (Packets) : Document support diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index b48dc70..191c60b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -13665,13 +13665,6 @@ some of which will be fixed with planned future releases of the debugger and the GNU Ada compiler. @itemize @bullet -@item -Currently, the debugger -has insufficient information to determine whether certain pointers represent -pointers to objects or the objects themselves. -Thus, the user may have to tack an extra @code{.all} after an expression -to get it printed properly. - @item Static constants that the compiler chooses not to materialize as objects in storage are invisible to the debugger. diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 02a92a9..5124dbb 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2010-12-29 Joel Brobecker + + * gdb.ada/lang_switch.exp: Correct expected parameter value. + 2010-12-25 Andreas Schwab * gdb.threads/tls.exp: Fix typo. diff --git a/gdb/testsuite/gdb.ada/lang_switch.exp b/gdb/testsuite/gdb.ada/lang_switch.exp index b5bf7dd..87f9921 100644 --- a/gdb/testsuite/gdb.ada/lang_switch.exp +++ b/gdb/testsuite/gdb.ada/lang_switch.exp @@ -46,7 +46,7 @@ gdb_test_no_output "set print frame-arguments all" # Make sure that the language is switched to Ada for the second frame # by checking the string parameter. gdb_test "bt" \ - ".*#1.*lang_switch\\.ada_procedure\\s*\\(msg=$hex\\).*" \ + ".*#1.*lang_switch\\.ada_procedure\\s*\\(msg=\"msg\"\\).*" \ "backtrace" # Now, make sure that the language doesn't get automatically switched -- 2.7.4