This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit/Ada] do not print arrays as array pointers


Before this patch was applied, GDB was printing all arrays implemented
as a "fat pointer" (a structure with 2 pointers, one to the bounds and
one to the array itself) as if they were array pointers. Or differently
said, if the user was trying to print the value of an array, he would
sometimes get the address of the array instead.

The underlying problem was caused by the fact that, from a code generation
point of view, unconstrained arrays and pointers to unconstrained arrays
are both implemented as fat pointers.  GDB was only seeing the fat pointer, 
and thus could not decide whether the fat pointer was for an array type,
or for a pointer-to-array type.

This patch enhances the debugger to distinguish between the two cases
(in the pointer-to-array type, the object/type is encoded as a typedef
type pointing to the fat pointer - see exp_dbug.ads).

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.

Tested on x86_64-linux.  Checked in.

---
 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  <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
 	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  <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
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  <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.
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
-- 
1.7.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]