gdb/fortran: Support negative array stride in one limited case

This commit adds support for negative Fortran array strides in one
limited case, that is the case of a single element array with a
negative array stride.

The changes in this commit will be required in order for more general
negative array stride support to work correctly, however, right now
other problems in GDB prevent negative array strides from working in
the general case.

The reason negative array strides don't currently work in the general
case is that when dealing with such arrays, the base address for the
objects data is actually the highest addressed element, subsequent
elements are then accessed with a negative offset from that address,
and GDB is not currently happy with this configuration.

The changes here can be summarised as, stop treating signed values as
unsigned, specifically, the array stride, and offsets calculated using
the array stride.

This issue was identified on the mailing list by Sergio:

  https://sourceware.org/ml/gdb-patches/2020-01/msg00360.html

The test for this issue is a new one written by me as the copyright
status of the original test is currently unknown.

gdb/ChangeLog:

	* gdbtypes.c (create_array_type_with_stride): Handle negative
	array strides.
	* valarith.c (value_subscripted_rvalue): Likewise.

gdb/testsuite/ChangeLog:

	* gdb.fortran/derived-type-striding.exp: Add a new test.
	* gdb.fortran/derived-type-striding.f90: Add pointer variable for
	new test.
This commit is contained in:
Andrew Burgess 2020-01-18 22:38:29 +00:00
parent 09624f1fec
commit 9e80cfa14e
6 changed files with 31 additions and 6 deletions

View File

@ -1,3 +1,9 @@
2020-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdbtypes.c (create_array_type_with_stride): Handle negative
array strides.
* valarith.c (value_subscripted_rvalue): Likewise.
2020-02-25 Luis Machado <luis.machado@linaro.org>
* aarch64-tdep.c (aarch64_vnv_type): Fix comment typo.

View File

@ -1223,7 +1223,7 @@ create_array_type_with_stride (struct type *result_type,
&& !type_not_allocated (result_type)))
{
LONGEST low_bound, high_bound;
unsigned int stride;
int stride;
/* If the array itself doesn't provide a stride value then take
whatever stride the range provides. Don't update BIT_STRIDE as
@ -1241,9 +1241,18 @@ create_array_type_with_stride (struct type *result_type,
In such cases, the array length should be zero. */
if (high_bound < low_bound)
TYPE_LENGTH (result_type) = 0;
else if (stride > 0)
TYPE_LENGTH (result_type) =
(stride * (high_bound - low_bound + 1) + 7) / 8;
else if (stride != 0)
{
/* Ensure that the type length is always positive, even in the
case where (for example in Fortran) we have a negative
stride. It is possible to have a single element array with a
negative stride in Fortran (this doesn't mean anything
special, it's still just a single element array) so do
consider that case when touching this code. */
LONGEST element_count = abs (high_bound - low_bound + 1);
TYPE_LENGTH (result_type)
= ((abs (stride) * element_count) + 7) / 8;
}
else
TYPE_LENGTH (result_type) =
TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);

View File

@ -1,3 +1,9 @@
2020-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.fortran/derived-type-striding.exp: Add a new test.
* gdb.fortran/derived-type-striding.f90: Add pointer variable for
new test.
2020-02-25 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.base/cached-source-file.exp: Avoid source file paths in test

View File

@ -41,3 +41,5 @@ gdb_test "p point_dimension" "= \\\(2, 2, 2, 2, 2, 2, 2, 2, 2\\\)"
# Test mixed type derived type.
if { $gcc_with_broken_stride } { setup_kfail *-*-* gcc/92775 }
gdb_test "p point_mixed_dimension" "= \\\(3, 3, 3, 3\\\)"
gdb_test "p cloud_slice" " = \\\(\\\( x = 1, y = 2, z = 3 \\\)\\\)"

View File

@ -28,9 +28,11 @@ program derived_type_member_stride
type(mixed_cartesian), dimension(10), target :: mixed_cloud
integer(kind=8), dimension(:), pointer :: point_dimension => null()
integer(kind=8), dimension(:), pointer :: point_mixed_dimension => null()
type(cartesian), dimension(:), pointer :: cloud_slice => null()
cloud(:)%x = 1
cloud(:)%y = 2
cloud(:)%z = 3
cloud_slice => cloud(3:2:-2)
point_dimension => cloud(1:9)%y
mixed_cloud(:)%x = 1
mixed_cloud(:)%y = 2

View File

@ -187,7 +187,7 @@ value_subscripted_rvalue (struct value *array, LONGEST index, LONGEST lowerbound
{
struct type *array_type = check_typedef (value_type (array));
struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type));
ULONGEST elt_size = type_length_units (elt_type);
LONGEST elt_size = type_length_units (elt_type);
/* Fetch the bit stride and convert it to a byte stride, assuming 8 bits
in a byte. */
@ -199,7 +199,7 @@ value_subscripted_rvalue (struct value *array, LONGEST index, LONGEST lowerbound
elt_size = stride / (unit_size * 8);
}
ULONGEST elt_offs = elt_size * (index - lowerbound);
LONGEST elt_offs = elt_size * (index - lowerbound);
if (index < lowerbound
|| (!TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (array_type)