From patchwork Fri Nov 29 23:32:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Simon Marchi (Code Review)" X-Patchwork-Id: 36388 Received: (qmail 55235 invoked by alias); 29 Nov 2019 23:32:50 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 55218 invoked by uid 89); 29 Nov 2019 23:32:50 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT autolearn=ham version=3.3.1 spammy=recurse, strides, elts, Prevent X-HELO: mx1.osci.io Received: from polly.osci.io (HELO mx1.osci.io) (8.43.85.229) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Nov 2019 23:32:45 +0000 Received: by mx1.osci.io (Postfix, from userid 994) id 14D0D203AE; Fri, 29 Nov 2019 18:32:44 -0500 (EST) Received: from gnutoolchain-gerrit.osci.io (gnutoolchain-gerrit.osci.io [8.43.85.239]) by mx1.osci.io (Postfix) with ESMTP id 1DE29202DF; Fri, 29 Nov 2019 18:32:41 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by gnutoolchain-gerrit.osci.io (Postfix) with ESMTP id EF01E20AF6; Fri, 29 Nov 2019 18:32:40 -0500 (EST) X-Gerrit-PatchSet: 7 Date: Fri, 29 Nov 2019 18:32:40 -0500 From: "Andrew Burgess (Code Review)" To: gdb-patches@sourceware.org Cc: Tom Tromey , Simon Marchi Auto-Submitted: auto-generated X-Gerrit-MessageType: newpatchset Subject: [review v7] gdb/fortran: array stride support X-Gerrit-Change-Id: I9af2bcd1f2d4c56f76f5f3f9f89d8f06bef10d9a X-Gerrit-Change-Number: 627 X-Gerrit-ChangeURL: X-Gerrit-Commit: 0e1c15735750a50fc7eccf275bd08135398f0dd8 In-Reply-To: References: Reply-To: andrew.burgess@embecosm.com, simon.marchi@polymtl.ca, tromey@sourceware.org, gdb-patches@sourceware.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Gerrit/3.0.3-79-g83ff7f88f1 Message-Id: <20191129233240.EF01E20AF6@gnutoolchain-gerrit.osci.io> Change URL: https://gnutoolchain-gerrit.osci.io/r/c/binutils-gdb/+/627 ...................................................................... gdb/fortran: array stride support Currently GDB supports a byte or bit stride on arrays, in DWARF this would be DW_AT_bit_stride or DW_AT_byte_stride on DW_TAG_array_type. However, DWARF can also support DW_AT_byte_stride or DW_AT_bit_stride on DW_TAG_subrange_type, the tag used to describe each dimension of an array. Strides on subranges are used by gFortran to represent Fortran arrays, and this commit adds support for this to GDB. I've extended the range_bounds struct to include the stride information. The name is possibly a little inaccurate now, but this still sort of makes sense, the structure represents information about the bounds of the range, and also how to move from the lower to the upper bound (the stride). I've added initial support for bit strides, but I've never actually seen an example of this being generated. Further, I don't really see right now how GDB would currently handle a bit stride that was not a multiple of the byte size as the code in, for example, valarith.c:value_subscripted_rvalue seems geared around byte addressing. As a consequence if we see a bit stride that is not a multiple of 8 then GDB will give an error. gdb/ChangeLog: * dwarf2read.c (read_subrange_type): Read bit and byte stride and create a range with stride where appropriate. * f-valprint.c (f77_print_array_1): Take the stride into account when walking the array. * gdbtypes.c (create_range_type): Initialise the stride to constant zero. (create_range_type_with_stride): Initialise the range as normal, and then setup the stride. (has_static_range): Include the stride here. Also change the return type to bool. (create_array_type_with_stride): Consider the range stride if the array isn't given its own stride. (resolve_dynamic_range): Resolve the stride if needed. * gdbtypes.h (struct range_bounds) : New member variable. (struct range_bounds) : New member variable. (TYPE_BIT_STRIDE): Define. (TYPE_ARRAY_BIT_STRIDE): Define. (create_range_type_with_stride): Declare. * valarith.c (value_subscripted_rvalue): Take range stride into account when walking the array. gdb/testsuite/ChangeLog: * gdb.fortran/derived-type-striding.exp: New file. * gdb.fortran/derived-type-striding.f90: New file. * gdb.fortran/array-slices.exp: New file. * gdb.fortran/array-slices.f90: New file. Change-Id: I9af2bcd1f2d4c56f76f5f3f9f89d8f06bef10d9a --- M gdb/ChangeLog M gdb/dwarf2read.c M gdb/f-valprint.c M gdb/gdbtypes.c M gdb/gdbtypes.h M gdb/testsuite/ChangeLog A gdb/testsuite/gdb.fortran/array-slices.exp A gdb/testsuite/gdb.fortran/array-slices.f90 A gdb/testsuite/gdb.fortran/derived-type-striding.exp A gdb/testsuite/gdb.fortran/derived-type-striding.f90 M gdb/valarith.c 11 files changed, 369 insertions(+), 10 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4b7e506..4c7d6b3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2019-11-18 Andrew Burgess + + * dwarf2read.c (read_subrange_type): Read bit and byte stride and + create a range with stride where appropriate. + * f-valprint.c (f77_print_array_1): Take the stride into account + when walking the array. + * gdbtypes.c (create_range_type): Initialise the stride to + constant zero. + (create_range_type_with_stride): Initialise the range as normal, + and then setup the stride. + (has_static_range): Include the stride here. Also change the + return type to bool. + (create_array_type_with_stride): Consider the range stride if the + array isn't given its own stride. + (resolve_dynamic_range): Resolve the stride if needed. + * gdbtypes.h (struct range_bounds) : New member variable. + (struct range_bounds) : New member variable. + (TYPE_BIT_STRIDE): Define. + (TYPE_ARRAY_BIT_STRIDE): Define. + (create_range_type_with_stride): Declare. + * valarith.c (value_subscripted_rvalue): Take range stride into + account when walking the array. + 2019-11-29 Tankut Baris Aktemur * valops.c (find_oload_champ): Improve debug output. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 40626a1..0822817 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -18060,7 +18060,51 @@ && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask)) high.data.const_val |= negative_mask; - range_type = create_range_type (NULL, orig_base_type, &low, &high, bias); + /* Check for bit and byte strides. */ + struct attribute *attr_bit_stride, *attr_byte_stride; + struct dynamic_prop bit_stride_prop, byte_stride_prop; + attr_byte_stride = dwarf2_attr (die, DW_AT_byte_stride, cu); + if (attr_byte_stride != nullptr) + { + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); + attr_to_dynamic_prop (attr_byte_stride, die, cu, &byte_stride_prop, + prop_type); + } + attr_bit_stride = dwarf2_attr (die, DW_AT_bit_stride, cu); + if (attr_bit_stride != nullptr) + { + /* It only makes sense to have either a bit or byte stride. */ + if (attr_byte_stride != nullptr) + { + complaint (_("Found DW_AT_bit_stride and DW_AT_byte_stride " + "- DIE at %s [in module %s]"), + sect_offset_str (die->sect_off), + objfile_name (cu->per_cu->dwarf2_per_objfile->objfile)); + attr_bit_stride = nullptr; + } + else + { + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); + attr_to_dynamic_prop (attr_bit_stride, die, cu, &bit_stride_prop, + prop_type); + } + } + + if (attr_byte_stride != nullptr + || attr_bit_stride != nullptr) + { + bool byte_stride_p = (attr_byte_stride != nullptr); + struct dynamic_prop *stride + = byte_stride_p ? &byte_stride_prop : &bit_stride_prop; + + range_type + = create_range_type_with_stride (NULL, orig_base_type, &low, + &high, bias, stride, byte_stride_p); + } + else + range_type = create_range_type (NULL, orig_base_type, &low, &high, bias); if (high_bound_is_count) TYPE_RANGE_DATA (range_type)->flag_upper_bound_is_count = 1; diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c index d5515c8..df5b471 100644 --- a/gdb/f-valprint.c +++ b/gdb/f-valprint.c @@ -121,6 +121,9 @@ if (nss != ndimensions) { size_t dim_size = TYPE_LENGTH (TYPE_TARGET_TYPE (type)); + size_t stride = TYPE_ARRAY_BIT_STRIDE (type) / HOST_CHAR_BIT; + if (stride == 0) + stride = dim_size; size_t offs = 0; for (i = lowerbound; @@ -137,7 +140,7 @@ value_embedded_offset (subarray), value_address (subarray), stream, recurse, subarray, options, elts); - offs += dim_size; + offs += stride; fprintf_filtered (stream, ") "); } if (*elts >= options->print_max && i < upperbound) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 31c1a7b..fbc1a5b 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -935,6 +935,10 @@ TYPE_RANGE_DATA (result_type)->high = *high_bound; TYPE_RANGE_DATA (result_type)->bias = bias; + /* Initialize the stride to be a constant, the value will already be zero + thanks to the use of TYPE_ZALLOC above. */ + TYPE_RANGE_DATA (result_type)->stride.kind = PROP_CONST; + if (low_bound->kind == PROP_CONST && low_bound->data.const_val >= 0) TYPE_UNSIGNED (result_type) = 1; @@ -948,6 +952,31 @@ return result_type; } +/* Like CREATE_RANGE_TYPE but also sets up a stride. When BYTE_STRIDE_P + is true the value in STRIDE is a byte stride, otherwise STRIDE is a bit + stride. */ + +struct type * +create_range_type_with_stride (struct type *result_type, + struct type *index_type, + const struct dynamic_prop *low_bound, + const struct dynamic_prop *high_bound, + LONGEST bias, + const struct dynamic_prop *stride, + bool byte_stride_p) +{ + result_type = create_range_type (result_type, index_type, low_bound, + high_bound, bias); + + gdb_assert (stride != nullptr); + TYPE_RANGE_DATA (result_type)->stride = *stride; + TYPE_RANGE_DATA (result_type)->flag_is_byte_stride = byte_stride_p; + + return result_type; +} + + + /* Create a range type using either a blank type supplied in RESULT_TYPE, or creating a new type, inheriting the objfile from INDEX_TYPE. @@ -978,11 +1007,14 @@ /* Predicate tests whether BOUNDS are static. Returns 1 if all bounds values are static, otherwise returns 0. */ -static int +static bool has_static_range (const struct range_bounds *bounds) { + /* If the range doesn't have a defined stride then its stride field will + be initialized to the constant 0. */ return (bounds->low.kind == PROP_CONST - && bounds->high.kind == PROP_CONST); + && bounds->high.kind == PROP_CONST + && bounds->stride.kind == PROP_CONST); } @@ -1189,6 +1221,15 @@ && !type_not_allocated (result_type))) { LONGEST low_bound, high_bound; + unsigned 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 + we don't want to place the stride value from the range into this + arrays bit size field. */ + stride = bit_stride; + if (stride == 0) + stride = TYPE_BIT_STRIDE (range_type); if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0) low_bound = high_bound = 0; @@ -1198,9 +1239,9 @@ In such cases, the array length should be zero. */ if (high_bound < low_bound) TYPE_LENGTH (result_type) = 0; - else if (bit_stride > 0) + else if (stride > 0) TYPE_LENGTH (result_type) = - (bit_stride * (high_bound - low_bound + 1) + 7) / 8; + (stride * (high_bound - low_bound + 1) + 7) / 8; else TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); @@ -1982,7 +2023,7 @@ CORE_ADDR value; struct type *static_range_type, *static_target_type; const struct dynamic_prop *prop; - struct dynamic_prop low_bound, high_bound; + struct dynamic_prop low_bound, high_bound, stride; gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE); @@ -2014,13 +2055,36 @@ high_bound.data.const_val = 0; } + bool byte_stride_p = TYPE_RANGE_DATA (dyn_range_type)->flag_is_byte_stride; + prop = &TYPE_RANGE_DATA (dyn_range_type)->stride; + if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value)) + { + stride.kind = PROP_CONST; + stride.data.const_val = value; + + /* If we have a bit stride that is not a multiple of the byte stride + then I really don't think this is going to work with current GDB. + The array indexing code in GDB seems to be pretty heavily tied to + byte offsets right now. If this comes up then we warn the user + and set up a known incorrect stride. */ + if (!byte_stride_p && (value % HOST_CHAR_BIT) != 0) + error (_("bit strides that are not a multiple of the byte size " + "are currently not supported")); + } + else + { + stride.kind = PROP_UNDEFINED; + stride.data.const_val = 0; + byte_stride_p = true; + } + static_target_type = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (dyn_range_type), addr_stack, 0); LONGEST bias = TYPE_RANGE_DATA (dyn_range_type)->bias; - static_range_type = create_range_type (copy_type (dyn_range_type), - static_target_type, - &low_bound, &high_bound, bias); + static_range_type = create_range_type_with_stride + (copy_type (dyn_range_type), static_target_type, + &low_bound, &high_bound, bias, &stride, byte_stride_p); TYPE_RANGE_DATA (static_range_type)->flag_bound_evaluated = 1; return static_range_type; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 2e128aa..9f10716 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -623,6 +623,13 @@ struct dynamic_prop high; + /* The stride value for this range. This can be stored in bits or bytes + based on the value of BYTE_STRIDE_P. It is optional to have a stride + value, if this range has no stride value defined then this will be set + to the constant zero. */ + + struct dynamic_prop stride; + /* * The bias. Sometimes a range value is biased before storage. The bias is added to the stored bits to form the true value. */ @@ -637,6 +644,10 @@ a dynamic one. */ unsigned int flag_bound_evaluated : 1; + + /* If this is true this STRIDE is in bytes, otherwise STRIDE is in bits. */ + + unsigned int flag_is_byte_stride : 1; }; /* Compare two range_bounds objects for equality. Simply does @@ -1352,6 +1363,9 @@ TYPE_RANGE_DATA(range_type)->high.kind #define TYPE_LOW_BOUND_KIND(range_type) \ TYPE_RANGE_DATA(range_type)->low.kind +#define TYPE_BIT_STRIDE(range_type) \ + (TYPE_RANGE_DATA(range_type)->stride.data.const_val \ + * (TYPE_RANGE_DATA(range_type)->flag_is_byte_stride ? HOST_CHAR_BIT : 1)) /* Property accessors for the type data location. */ #define TYPE_DATA_LOCATION(thistype) \ @@ -1394,6 +1408,9 @@ #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \ (TYPE_LOW_BOUND(TYPE_INDEX_TYPE((arraytype)))) +#define TYPE_ARRAY_BIT_STRIDE(arraytype) \ + (TYPE_BIT_STRIDE(TYPE_INDEX_TYPE((arraytype)))) + /* C++ */ #define TYPE_SELF_TYPE(thistype) internal_type_self_type (thistype) @@ -1966,6 +1983,10 @@ const struct dynamic_prop *, LONGEST); +extern struct type * create_range_type_with_stride + (struct type *, struct type *, const struct dynamic_prop *, + const struct dynamic_prop *, LONGEST, const struct dynamic_prop *, bool); + extern struct type *create_array_type (struct type *, struct type *, struct type *); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 6b520e1..ae63519 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-11-18 Richard Bunt + Andrew Burgess + + * gdb.fortran/derived-type-striding.exp: New file. + * gdb.fortran/derived-type-striding.f90: New file. + * gdb.fortran/array-slices.exp: New file. + * gdb.fortran/array-slices.f90: New file. + 2019-11-28 Andrew Burgess * lib/gdb.exp (skip_btrace_tests): Return 1 if the test fails to diff --git a/gdb/testsuite/gdb.fortran/array-slices.exp b/gdb/testsuite/gdb.fortran/array-slices.exp new file mode 100644 index 0000000..afd030b --- /dev/null +++ b/gdb/testsuite/gdb.fortran/array-slices.exp @@ -0,0 +1,55 @@ +# Copyright 2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Print a 2 dimensional assumed shape array. We pass different slices +# of the array to a subroutine and print the array as recieved within +# the subroutine. This should exercise GDB's ability to handle +# different strides for the different dimensions. + +if {[skip_fortran_tests]} { return -1 } + +standard_testfile ".f90" + +if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \ + {debug f90}]} { + return -1 +} + +if ![runto_main] { + untested "could not run to main" + return -1 +} + +gdb_breakpoint "show" +gdb_breakpoint [gdb_get_line_number "Final Breakpoint"] + +set array_contents \ + [list \ + " = \\(\\( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\) \\( 11, 12, 13, 14, 15, 16, 17, 18, 19, 20\\) \\( 21, 22, 23, 24, 25, 26, 27, 28, 29, 30\\) \\( 31, 32, 33, 34, 35, 36, 37, 38, 39, 40\\) \\( 41, 42, 43, 44, 45, 46, 47, 48, 49, 50\\) \\( 51, 52, 53, 54, 55, 56, 57, 58, 59, 60\\) \\( 61, 62, 63, 64, 65, 66, 67, 68, 69, 70\\) \\( 71, 72, 73, 74, 75, 76, 77, 78, 79, 80\\) \\( 81, 82, 83, 84, 85, 86, 87, 88, 89, 90\\) \\( 91, 92, 93, 94, 95, 96, 97, 98, 99, 100\\) \\)" \ + " = \\(\\( 1, 2, 3, 4, 5\\) \\( 11, 12, 13, 14, 15\\) \\( 21, 22, 23, 24, 25\\) \\( 31, 32, 33, 34, 35\\) \\( 41, 42, 43, 44, 45\\) \\)" \ + " = \\(\\( 1, 3, 5, 7, 9\\) \\( 21, 23, 25, 27, 29\\) \\( 41, 43, 45, 47, 49\\) \\( 61, 63, 65, 67, 69\\) \\( 81, 83, 85, 87, 89\\) \\)" \ + " = \\(\\( 1, 4, 7, 10\\) \\( 21, 24, 27, 30\\) \\( 41, 44, 47, 50\\) \\( 61, 64, 67, 70\\) \\( 81, 84, 87, 90\\) \\)" \ + " = \\(\\( 1, 5, 9\\) \\( 31, 35, 39\\) \\( 61, 65, 69\\) \\( 91, 95, 99\\) \\)" ] + +set i 0 +foreach result $array_contents { + incr i + with_test_prefix "test $i" { + gdb_continue_to_breakpoint "show" + gdb_test "p array" $result + } +} + +gdb_continue_to_breakpoint "continue to Final Breakpoint" diff --git a/gdb/testsuite/gdb.fortran/array-slices.f90 b/gdb/testsuite/gdb.fortran/array-slices.f90 new file mode 100644 index 0000000..6f80a51 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/array-slices.f90 @@ -0,0 +1,56 @@ +! Copyright 2019 Free Software Foundation, Inc. +! +! This program is free software; you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation; either version 3 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see . + +subroutine show (message, array) + character (len=*) :: message + integer, dimension (:,:) :: array + + print *, message + do i=LBOUND (array, 2), UBOUND (array, 2), 1 + do j=LBOUND (array, 1), UBOUND (array, 1), 1 + write(*, fmt="(i4)", advance="no") array (j, i) + end do + print *, "" + end do + print *, array + print *, "" + +end subroutine show + +program test + + interface + subroutine show (message, array) + character (len=*) :: message + integer, dimension(:,:) :: array + end subroutine show + end interface + + integer, dimension (1:10,1:10) :: array + + do i=LBOUND (array, 2), UBOUND (array, 2), 1 + do j=LBOUND (array, 1), UBOUND (array, 1), 1 + array (j,i) = ((i - 1) * UBOUND (array, 2)) + j + end do + end do + + call show ("array", array) + call show ("array (1:5,1:5)", array (1:5,1:5)) + call show ("array (1:10:2,1:10:2)", array (1:10:2,1:10:2)) + call show ("array (1:10:3,1:10:2)", array (1:10:3,1:10:2)) + call show ("array (1:10:5,1:10:3)", array (1:10:4,1:10:3)) + + print *, "" ! Final Breakpoint. +end program test diff --git a/gdb/testsuite/gdb.fortran/derived-type-striding.exp b/gdb/testsuite/gdb.fortran/derived-type-striding.exp new file mode 100644 index 0000000..a2590a9 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/derived-type-striding.exp @@ -0,0 +1,37 @@ +# Copyright 2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Print some single dimensional integer arrays that will have a byte +# stride in the debug information. + +if {[skip_fortran_tests]} { return -1 } + +standard_testfile ".f90" + +if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \ + {debug f90}]} { + return -1 +} + +if {![runto [gdb_get_line_number "post_init"]]} then { + perror "couldn't run to breakpoint post_init" + continue +} + +# Test homogeneous derived type. +gdb_test "p point_dimension" "= \\\(2, 2, 2, 2, 2, 2, 2, 2, 2\\\)" + +# Test mixed type derived type. +gdb_test "p point_mixed_dimension" "= \\\(3, 3, 3, 3\\\)" diff --git a/gdb/testsuite/gdb.fortran/derived-type-striding.f90 b/gdb/testsuite/gdb.fortran/derived-type-striding.f90 new file mode 100644 index 0000000..8189ad3 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/derived-type-striding.f90 @@ -0,0 +1,43 @@ +! Copyright 2019 Free Software Foundation, Inc. +! +! This program is free software; you can redistribute it and/or modify +! it under the terms of the GNU General Public License as published by +! the Free Software Foundation; either version 3 of the License, or +! (at your option) any later version. +! +! This program is distributed in the hope that it will be useful, +! but WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +! GNU General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program. If not, see . + +program derived_type_member_stride + type cartesian + integer(kind=8) :: x + integer(kind=8) :: y + integer(kind=8) :: z + end type + type mixed_cartesian + integer(kind=8) :: x + integer(kind=4) :: y + integer(kind=8) :: z + end type + type(cartesian), dimension(10), target :: cloud + 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() + cloud(:)%x = 1 + cloud(:)%y = 2 + cloud(:)%z = 3 + point_dimension => cloud(1:9)%y + mixed_cloud(:)%x = 1 + mixed_cloud(:)%y = 2 + mixed_cloud(:)%z = 3 + point_mixed_dimension => mixed_cloud(1:4)%z + ! Prevent the compiler from optimising the work out. + print *, cloud(:)%x ! post_init + print *, point_dimension + print *, point_mixed_dimension +end program diff --git a/gdb/valarith.c b/gdb/valarith.c index ea999b5..fed550d 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -188,6 +188,11 @@ 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 stride = TYPE_ARRAY_BIT_STRIDE (array_type); + if (stride != 0) + elt_size = stride / HOST_CHAR_BIT; + ULONGEST elt_offs = elt_size * (index - lowerbound); if (index < lowerbound