[Ada] do not print arrays as array pointers
authorJoel Brobecker <brobecker@gnat.com>
Wed, 29 Dec 2010 08:01:32 +0000 (08:01 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Wed, 29 Dec 2010 08:01:32 +0000 (08:01 +0000)
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
gdb/ada-lang.c
gdb/ada-lang.h
gdb/ada-typeprint.c
gdb/ada-valprint.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.ada/lang_switch.exp

index 717d8834f32b573d85a7bb6e57b7f6e36589719b..e1f238e4c64cd12204c75a2af5faeff1a3e971da 100644 (file)
@@ -1,3 +1,21 @@
+2010-12-29  Joel Brobecker  <brobecker@adacore.com>
+
+       * 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  <brobecker@adacore.com>
 
        * target.h (enum target_object): Expand the documentation of
index 7ea01c73cc08881d9b54c4b4c5ff45cbead0df29..3a5b10f4dbe81415426df29889d9d15535b2c2c9 100644 (file)
@@ -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))))
index 0cd20df7d10e2ae6f6bc0c49f11026c72b9c7f37..1aac7b2d73d76c38f8962eacf29244f039c4dc0f 100644 (file)
@@ -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 *);
index 677a6aa4fcb91689a7b777652cc878b0e82c80bf..f58f59966a94f0a691f985a8801e88b6cc602ce9 100644 (file)
@@ -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;
index ae2a47d7d86b6b763d6ccc996e7440f3c0554293..b5d4b02329ca91b4e5a654a12bd9628a64836d15 100644 (file)
@@ -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))
     {
index 31e35d395383f6c267241c20d41b30605b966c32..0d1ec08fbd2384adb1ea15250e00bffa78dbf91b 100644 (file)
@@ -1,3 +1,9 @@
+2010-12-29  Joel Brobecker  <brobecker@adacore.com>
+
+       * 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  <pedro@codesourcery.com>
 
        * gdb.texinfo (Packets) <read registers packet>: Document support
index b48dc70cbed1bbff6f8d75660fa6ba979370cb3a..191c60ba2ded0ebefab0f72cdbf4755a19aa3c66 100644 (file)
@@ -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.
index 02a92a910d2f5840a313a49bf669d9871f14a4f6..5124dbb8b651b7aab8a0a6f75fbcfe5957bc9efc 100644 (file)
@@ -1,3 +1,7 @@
+2010-12-29  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.ada/lang_switch.exp: Correct expected parameter value.
+
 2010-12-25  Andreas Schwab  <schwab@linux-m68k.org>
 
        * gdb.threads/tls.exp: Fix typo.
index b5bf7dd55cd8fc479d806fa001e356e0b4383792..87f9921ee6a85de403d2ce6674b9facd7f39bf6c 100644 (file)
@@ -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