[commit/Ada,2/2] slices of arrays with dynamic strides

Message ID 1513227213-37871-2-git-send-email-brobecker@adacore.com
State New, archived
Headers

Commit Message

Joel Brobecker Dec. 14, 2017, 4:53 a.m. UTC
  Hello,

This is a patch which fixes an isses with array slices in Ada
when the array has a dynamic stride.  It depends on the patch
adding support for DW_AT_byte_stride, so I will push after
the first one gets approved.

Consider the following Ada code:

       procedure Nested (L, U : Integer) is
          subtype Small_Type is Integer range L .. U;
          type Record_Type (I : Small_Type := L) is record
             S : String (1 .. I);
          end record;
          type Array_Type is array (Integer range <>) of Record_Type;

          A1 : Array_Type :=
            (1 => (I => 0, S => <>),
             2 => (I => 1, S => "A"),
             3 => (I => 2, S => "AB"));

          procedure Discard (R : Record_Type) is
          begin
             null;
          end Discard;

       begin
          Discard (A1 (1));  -- STOP
       end;

Trying to print a slice of that array currently yields:

    (gdb) p a1(1..3)
    $1 = ((i => 0, s => ""), (i => 0, s => ""), (i => 0, s => ""))

We expected instead:

    (gdb) p a1(1..3)
    $1 = ((i => 0, s => ""), (i => 1, s => "A"), (i => 2, s => "AB"))

This is because the functions we use in ada-lang.c to create the type
of the array slice (ada_value_slice and ada_value_slice_from_ptr) was
not taking into account the stride of the array. This patch fixes this.

gdb/ChangeLog:

        * ada-lang.c (ada_value_slice_from_ptr): Take array stride into
        account when creating the array type of the slice.
        (ada_value_slice): Likewise.

gdb/testsuite/ChangeLog:

        * gdb.ada/dyn_stride.exp: Add slice test.

Note that, with the current use of ada_value_slice, the enhancement
to handle dynamic array strides seems unnecessary, because I do not
see how an array with a dynamic stride can be referenced by either
by reference or pointer. Since references are coerced to array pointers,
in both cases, the slice is performed by ada_value_slice_from_ptr.
But ada_value_slice is enhanced nonetheless, in the spirit of making
the code more robust, in case we missed something, and also as similar
as possible with its from_ptr counterpart.

tested on x86_64-linux.

Thanks,
  

Comments

Joel Brobecker Jan. 2, 2018, 3:56 a.m. UTC | #1
> gdb/ChangeLog:
> 
>         * ada-lang.c (ada_value_slice_from_ptr): Take array stride into
>         account when creating the array type of the slice.
>         (ada_value_slice): Likewise.
> 
> gdb/testsuite/ChangeLog:
> 
>         * gdb.ada/dyn_stride.exp: Add slice test.

Pushed as well :).
  

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 9e637eb..c3b1cd3 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -2910,8 +2910,10 @@  ada_value_slice_from_ptr (struct value *array_ptr, struct type *type,
   struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0));
   struct type *index_type
     = create_static_range_type (NULL, base_index_type, low, high);
-  struct type *slice_type =
-    create_array_type (NULL, TYPE_TARGET_TYPE (type0), index_type);
+  struct type *slice_type = create_array_type_with_stride
+			      (NULL, TYPE_TARGET_TYPE (type0), index_type,
+			       get_dyn_prop (DYN_PROP_BYTE_STRIDE, type0),
+			       TYPE_FIELD_BITSIZE (type0, 0));
   int base_low =  ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0));
   LONGEST base_low_pos, low_pos;
   CORE_ADDR base;
@@ -2938,8 +2940,10 @@  ada_value_slice (struct value *array, int low, int high)
   struct type *base_index_type = TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type));
   struct type *index_type
     = create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
-  struct type *slice_type =
-    create_array_type (NULL, TYPE_TARGET_TYPE (type), index_type);
+  struct type *slice_type = create_array_type_with_stride
+			      (NULL, TYPE_TARGET_TYPE (type), index_type,
+			       get_dyn_prop (DYN_PROP_BYTE_STRIDE, type),
+			       TYPE_FIELD_BITSIZE (type, 0));
   LONGEST low_pos, high_pos;
 
   if (!discrete_position (base_index_type, low, &low_pos)
diff --git a/gdb/testsuite/gdb.ada/dyn_stride.exp b/gdb/testsuite/gdb.ada/dyn_stride.exp
index 4dd1177..19be9cb 100644
--- a/gdb/testsuite/gdb.ada/dyn_stride.exp
+++ b/gdb/testsuite/gdb.ada/dyn_stride.exp
@@ -36,3 +36,6 @@  gdb_test "print A1(2)" \
 
 gdb_test "print A1(3)" \
          "\\(i => 2, s => \"AB\"\\)"
+
+gdb_test "print A1(1..3)" \
+         "\\(\\(i => 0, s => \"\"\\), \\(i => 1, s => \"A\"\\), \\(i => 2, s => \"AB\"\\)\\)"