Fix array stride bug
authorTom Tromey <tromey@adacore.com>
Fri, 18 Jun 2021 19:08:33 +0000 (13:08 -0600)
committerTom Tromey <tromey@adacore.com>
Fri, 16 Jul 2021 14:23:47 +0000 (08:23 -0600)
Investigation of using the Python API with an Ada program showed that
an array of dynamic types was not being handled properly.  I tracked
this down to an oddity of how array strides are handled.

In gdb, an array stride can be attached to the range type, via the
range_bounds object.  However, the stride can also be put into the
array's first field.  From create_range_type_with_stride:

  else if (bit_stride > 0)
    TYPE_FIELD_BITSIZE (result_type, 0) = bit_stride;

It's hard to be sure why this is done, but I would guess a combination
of historical reasons plus a desire (mentioned in a comment somewhere)
to avoid modifying the range type.

This patch fixes the problem by changing type::bit_stride to
understand this convention.  It also fixes one spot that reproduces
this logic.

Regression tested on x86-64 Fedora 32.

gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/testsuite/gdb.ada/array_of_variant.exp

index dbc82f0a4ac41a7123e8dd598cd45a0b6016fcdd..1a261719422a0c9f4480956e85edba292636d53c 100644 (file)
@@ -1280,13 +1280,7 @@ update_static_array_size (struct type *type)
       int stride;
       struct type *element_type;
 
-      /* If the array itself doesn't provide a stride value then take
-        whatever stride the range provides.  Don't update BIT_STRIDE as
-        we don't want to place the stride value from the range into this
-        arrays bit size field.  */
-      stride = TYPE_FIELD_BITSIZE (type, 0);
-      if (stride == 0)
-       stride = range_type->bit_stride ();
+      stride = type->bit_stride ();
 
       if (!get_discrete_bounds (range_type, &low_bound, &high_bound))
        low_bound = high_bound = 0;
index 0cc00e74a207ee6db56a6752e7f41fc2cc139d0c..d754f2fcd36dc2cc4f3d20912436611643bdfbbd 100644 (file)
@@ -1029,6 +1029,8 @@ struct type
 
   ULONGEST bit_stride () const
   {
+    if (this->code () == TYPE_CODE_ARRAY && this->field (0).bitsize != 0)
+      return this->field (0).bitsize;
     return this->bounds ()->bit_stride ();
   }
 
index dfcbe751b57475a96d5fad1a28bb0a10c5111b13..d93ad4704a03f72e4673136022426e57289516b3 100644 (file)
@@ -14,6 +14,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 load_lib "ada.exp"
+load_lib "gdb-python.exp"
 
 if { [skip_ada_tests] } { return -1 }
 
@@ -49,4 +50,20 @@ foreach_with_prefix scenario {all minimal} {
     gdb_test "print objects(2 .. 2)" \
        [string_to_regexp " = (2 => $v2)"] \
        "print second array slice"
+
+    # This is only supported for the DWARF encoding.
+    if {$scenario == "minimal" && ![skip_python_tests]} {
+       gdb_test_no_output \
+           "python o = gdb.parse_and_eval('objects')" \
+           "fetch value for python"
+       gdb_test "python print(o)" \
+           [string_to_regexp "($v1, $v2)"] \
+           "python print array"
+       gdb_test "python print(o\[1\])" \
+           [string_to_regexp "$v1"] \
+           "python print first array element"
+       gdb_test "python print(o\[2\])" \
+           [string_to_regexp "$v2"] \
+           "python print second array element"
+    }
 }