diff options
-rw-r--r-- | gdb/f-array-walker.h | 68 | ||||
-rw-r--r-- | gdb/f-lang.c | 2 | ||||
-rw-r--r-- | gdb/f-valprint.c | 210 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/array-repeat.exp | 167 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/array-repeat.f90 | 50 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/array-slices-repeat.f90 | 99 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/vla-value-sub-finish.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.fortran/vla-value-sub.exp | 2 |
8 files changed, 572 insertions, 28 deletions
diff --git a/gdb/f-array-walker.h b/gdb/f-array-walker.h index 24b53ff..a929dcc 100644 --- a/gdb/f-array-walker.h +++ b/gdb/f-array-walker.h @@ -115,11 +115,12 @@ struct fortran_array_walker_base_impl { return should_continue; } /* Called when GDB starts iterating over a dimension of the array. The - argument INNER_P is true for the inner most dimension (the dimension - containing the actual elements of the array), and false for more outer - dimensions. For a concrete example of how this function is called - see the comment on process_element below. */ - void start_dimension (bool inner_p) + argument NELTS holds the number of the elements in the dimension and + INNER_P is true for the inner most dimension (the dimension containing + the actual elements of the array), and false for more outer dimensions. + For a concrete example of how this function is called see the comment + on process_element below. */ + void start_dimension (LONGEST nelts, bool inner_p) { /* Nothing. */ } /* Called when GDB finishes iterating over a dimension of the array. The @@ -131,21 +132,38 @@ struct fortran_array_walker_base_impl void finish_dimension (bool inner_p, bool last_p) { /* Nothing. */ } + /* Called when processing dimensions of the array other than the + innermost one. WALK_1 is the walker to normally call, ELT_TYPE is + the type of the element being extracted, and ELT_OFF is the offset + of the element from the start of array being walked, and LAST_P is + true only when this is the last element that will be processed in + this dimension. */ + void process_dimension (gdb::function_view<void (struct type *, + int, bool)> walk_1, + struct type *elt_type, LONGEST elt_off, bool last_p) + { + walk_1 (elt_type, elt_off, last_p); + } + /* Called when processing the inner most dimension of the array, for every element in the array. ELT_TYPE is the type of the element being extracted, and ELT_OFF is the offset of the element from the start of array being walked, and LAST_P is true only when this is the last element that will be processed in this dimension. - Given this two dimensional array ((1, 2) (3, 4)), the calls to + Given this two dimensional array ((1, 2) (3, 4) (5, 6)), the calls to start_dimension, process_element, and finish_dimension look like this: - start_dimension (false); - start_dimension (true); + start_dimension (3, false); + start_dimension (2, true); process_element (TYPE, OFFSET, false); process_element (TYPE, OFFSET, true); finish_dimension (true, false); - start_dimension (true); + start_dimension (2, true); + process_element (TYPE, OFFSET, false); + process_element (TYPE, OFFSET, true); + finish_dimension (true, true); + start_dimension (2, true); process_element (TYPE, OFFSET, false); process_element (TYPE, OFFSET, true); finish_dimension (true, true); @@ -177,22 +195,23 @@ public: : m_type (type), m_address (address), m_impl (type, address, args...), - m_ndimensions (calc_f77_array_dims (m_type)) + m_ndimensions (calc_f77_array_dims (m_type)), + m_nss (0) { /* Nothing. */ } /* Walk the array. */ void walk () { - walk_1 (1, m_type, 0, false); + walk_1 (m_type, 0, false); } private: - /* The core of the array walking algorithm. NSS is the current - dimension number being processed, TYPE is the type of this dimension, - and OFFSET is the offset (in bytes) for the start of this dimension. */ + /* The core of the array walking algorithm. TYPE is the type of + the current dimension being processed and OFFSET is the offset + (in bytes) for the start of this dimension. */ void - walk_1 (int nss, struct type *type, int offset, bool last_p) + walk_1 (struct type *type, int offset, bool last_p) { /* Extract the range, and get lower and upper bounds. */ struct type *range_type = check_typedef (type)->index_type (); @@ -204,9 +223,11 @@ private: dimension. */ fortran_array_offset_calculator calc (type); - m_impl.start_dimension (nss == m_ndimensions); + m_nss++; + m_impl.start_dimension (upperbound - lowerbound + 1, + m_nss == m_ndimensions); - if (nss != m_ndimensions) + if (m_nss != m_ndimensions) { struct type *subarray_type = TYPE_TARGET_TYPE (check_typedef (type)); @@ -220,7 +241,12 @@ private: LONGEST new_offset = offset + calc.index_offset (i); /* Now print the lower dimension. */ - walk_1 (nss + 1, subarray_type, new_offset, (i == upperbound)); + m_impl.process_dimension + ([this] (struct type *w_type, int w_offset, bool w_last_p) -> void + { + this->walk_1 (w_type, w_offset, w_last_p); + }, + subarray_type, new_offset, i == upperbound); } } else @@ -245,7 +271,8 @@ private: } } - m_impl.finish_dimension (nss == m_ndimensions, last_p || nss == 1); + m_impl.finish_dimension (m_nss == m_ndimensions, last_p || m_nss == 1); + m_nss--; } /* The array type being processed. */ @@ -260,6 +287,9 @@ private: /* The total number of dimensions in M_TYPE. */ int m_ndimensions; + + /* The current dimension number being processed. */ + int m_nss; }; #endif /* F_ARRAY_WALKER_H */ diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 3ef7597..d181f38 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -263,7 +263,7 @@ public: will be creating values for each element as we load them and then copy them into the M_DEST value. Set a value mark so we can free these temporary values. */ - void start_dimension (bool inner_p) + void start_dimension (LONGEST nelts, bool inner_p) { if (inner_p) { diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c index c267469..4b1aaae 100644 --- a/gdb/f-valprint.c +++ b/gdb/f-valprint.c @@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "defs.h" +#include "annotate.h" #include "symtab.h" #include "gdbtypes.h" #include "expression.h" @@ -96,6 +97,14 @@ f77_get_dynamic_length_of_aggregate (struct type *type) * TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type))); } +/* Per-dimension statistics. */ + +struct dimension_stats +{ + /* Total number of elements in the dimension, counted as we go. */ + int nelts; +}; + /* A class used by FORTRAN_PRINT_ARRAY as a specialisation of the array walking template. This specialisation prints Fortran arrays. */ @@ -117,7 +126,10 @@ public: m_val (val), m_stream (stream), m_recurse (recurse), - m_options (options) + m_options (options), + m_dimension (0), + m_nrepeats (0), + m_stats (0) { /* Nothing. */ } /* Called while iterating over the array bounds. When SHOULD_CONTINUE is @@ -135,8 +147,17 @@ public: /* Called when we start iterating over a dimension. If it's not the inner most dimension then print an opening '(' character. */ - void start_dimension (bool inner_p) + void start_dimension (LONGEST nelts, bool inner_p) { + size_t dim_indx = m_dimension++; + + m_elt_type_prev = nullptr; + if (m_stats.size () < m_dimension) + { + m_stats.resize (m_dimension); + m_stats[dim_indx].nelts = nelts; + } + fputs_filtered ("(", m_stream); } @@ -149,22 +170,181 @@ public: fputs_filtered (")", m_stream); if (!last_p) fputs_filtered (" ", m_stream); + + m_dimension--; + } + + /* Called when processing dimensions of the array other than the + innermost one. WALK_1 is the walker to normally call, ELT_TYPE is + the type of the element being extracted, and ELT_OFF is the offset + of the element from the start of array being walked, and LAST_P is + true only when this is the last element that will be processed in + this dimension. */ + void process_dimension (gdb::function_view<void (struct type *, + int, bool)> walk_1, + struct type *elt_type, LONGEST elt_off, bool last_p) + { + size_t dim_indx = m_dimension - 1; + struct type *elt_type_prev = m_elt_type_prev; + LONGEST elt_off_prev = m_elt_off_prev; + bool repeated = (m_options->repeat_count_threshold < UINT_MAX + && elt_type_prev != nullptr + && (m_elts + ((m_nrepeats + 1) + * m_stats[dim_indx + 1].nelts) + <= m_options->print_max) + && dimension_contents_eq (m_val, elt_type, + elt_off_prev, elt_off)); + + if (repeated) + m_nrepeats++; + if (!repeated || last_p) + { + LONGEST nrepeats = m_nrepeats; + + m_nrepeats = 0; + if (nrepeats >= m_options->repeat_count_threshold) + { + annotate_elt_rep (nrepeats + 1); + fprintf_filtered (m_stream, "%p[<repeats %s times>%p]", + metadata_style.style ().ptr (), + plongest (nrepeats + 1), + nullptr); + annotate_elt_rep_end (); + if (!repeated) + fputs_filtered (" ", m_stream); + m_elts += nrepeats * m_stats[dim_indx + 1].nelts; + } + else + for (LONGEST i = nrepeats; i > 0; i--) + walk_1 (elt_type_prev, elt_off_prev, repeated && i == 1); + + if (!repeated) + { + /* We need to specially handle the case of hitting `print_max' + exactly as recursing would cause lone `(...)' to be printed. + And we need to print `...' by hand if the skipped element + would be the last one processed, because the subsequent call + to `continue_walking' from our caller won't do that. */ + if (m_elts < m_options->print_max) + { + walk_1 (elt_type, elt_off, last_p); + nrepeats++; + } + else if (last_p) + fputs_filtered ("...", m_stream); + } + } + + m_elt_type_prev = elt_type; + m_elt_off_prev = elt_off; } /* Called to process an element of ELT_TYPE at offset ELT_OFF from the start of the parent object. */ void process_element (struct type *elt_type, LONGEST elt_off, bool last_p) { - /* Extract the element value from the parent value. */ - struct value *e_val - = value_from_component (m_val, elt_type, elt_off); - common_val_print (e_val, m_stream, m_recurse, m_options, current_language); - if (!last_p) - fputs_filtered (", ", m_stream); + struct type *elt_type_prev = m_elt_type_prev; + LONGEST elt_off_prev = m_elt_off_prev; + bool repeated = (m_options->repeat_count_threshold < UINT_MAX + && elt_type_prev != nullptr + && value_contents_eq (m_val, elt_off_prev, m_val, elt_off, + TYPE_LENGTH (elt_type))); + + if (repeated) + m_nrepeats++; + if (!repeated || last_p || m_elts + 1 == m_options->print_max) + { + LONGEST nrepeats = m_nrepeats; + bool printed = false; + + if (nrepeats != 0) + { + m_nrepeats = 0; + if (nrepeats >= m_options->repeat_count_threshold) + { + annotate_elt_rep (nrepeats + 1); + fprintf_filtered (m_stream, "%p[<repeats %s times>%p]", + metadata_style.style ().ptr (), + plongest (nrepeats + 1), + nullptr); + annotate_elt_rep_end (); + } + else + { + /* Extract the element value from the parent value. */ + struct value *e_val + = value_from_component (m_val, elt_type, elt_off_prev); + + for (LONGEST i = nrepeats; i > 0; i--) + { + common_val_print (e_val, m_stream, m_recurse, m_options, + current_language); + if (i > 1) + fputs_filtered (", ", m_stream); + } + } + printed = true; + } + + if (!repeated) + { + /* Extract the element value from the parent value. */ + struct value *e_val + = value_from_component (m_val, elt_type, elt_off); + + if (printed) + fputs_filtered (", ", m_stream); + common_val_print (e_val, m_stream, m_recurse, m_options, + current_language); + } + if (!last_p) + fputs_filtered (", ", m_stream); + } + + m_elt_type_prev = elt_type; + m_elt_off_prev = elt_off; ++m_elts; } private: + /* Called to compare two VAL elements of ELT_TYPE at offsets OFFSET1 + and OFFSET2 each. Handle subarrays recursively, because they may + have been sliced and we do not want to compare any memory contents + present between the slices requested. */ + bool + dimension_contents_eq (const struct value *val, struct type *type, + LONGEST offset1, LONGEST offset2) + { + if (type->code () == TYPE_CODE_ARRAY + && TYPE_TARGET_TYPE (type)->code () != TYPE_CODE_CHAR) + { + /* Extract the range, and get lower and upper bounds. */ + struct type *range_type = check_typedef (type)->index_type (); + LONGEST lowerbound, upperbound; + if (!get_discrete_bounds (range_type, &lowerbound, &upperbound)) + error ("failed to get range bounds"); + + /* CALC is used to calculate the offsets for each element. */ + fortran_array_offset_calculator calc (type); + + struct type *subarray_type = check_typedef (TYPE_TARGET_TYPE (type)); + for (LONGEST i = lowerbound; i < upperbound + 1; i++) + { + /* Use the index and the stride to work out a new offset. */ + LONGEST index_offset = calc.index_offset (i); + + if (!dimension_contents_eq (val, subarray_type, + offset1 + index_offset, + offset2 + index_offset)) + return false; + } + return true; + } + else + return value_contents_eq (val, offset1, val, offset2, + TYPE_LENGTH (type)); + } + /* The number of elements printed so far. */ int m_elts; @@ -180,6 +360,20 @@ private: /* The print control options. Gives us the maximum number of elements to print, and is passed through to each element that we print. */ const struct value_print_options *m_options = nullptr; + + /* The number of the current dimension being handled. */ + LONGEST m_dimension; + + /* The number of element repetitions in the current series. */ + LONGEST m_nrepeats; + + /* The type and offset from M_VAL of the element handled in the previous + iteration over the current dimension. */ + struct type *m_elt_type_prev; + LONGEST m_elt_off_prev; + + /* Per-dimension stats. */ + std::vector<struct dimension_stats> m_stats; }; /* This function gets called to print a Fortran array. */ diff --git a/gdb/testsuite/gdb.fortran/array-repeat.exp b/gdb/testsuite/gdb.fortran/array-repeat.exp new file mode 100644 index 0000000..bf16735 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/array-repeat.exp @@ -0,0 +1,167 @@ +# Copyright 2022 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 <http://www.gnu.org/licenses/>. + +# Test the detection and printing of repeated elements in Fortran arrays. + +if {[skip_fortran_tests]} { return -1 } + +load_lib fortran.exp + +# Build up the expected output for each array. +set a9p9o "(9, 9, 9, 9, 9, 9)" +set a1p "(1, 1, 1, 1, 1)" +set a1p9 "(1, 1, 1, 1, 1, 9)" +set a2po "(2, 2, 2, 2, 2)" +set a2p "(${a2po} ${a2po} ${a2po} ${a2po} ${a2po})" +set a2p9o "(2, 2, 2, 2, 2, 9)" +set a2p9 "(${a2p9o} ${a2p9o} ${a2p9o} ${a2p9o} ${a2p9o} ${a9p9o})" +set a3po "(3, 3, 3, 3, 3)" +set a3p "(${a3po} ${a3po} ${a3po} ${a3po} ${a3po})" +set a3p "(${a3p} ${a3p} ${a3p} ${a3p} ${a3p})" +set a3p9o "(3, 3, 3, 3, 3, 9)" +set a3p9 "(${a3p9o} ${a3p9o} ${a3p9o} ${a3p9o} ${a3p9o} ${a9p9o})" +set a9p9 "(${a9p9o} ${a9p9o} ${a9p9o} ${a9p9o} ${a9p9o} ${a9p9o})" +set a3p9 "(${a3p9} ${a3p9} ${a3p9} ${a3p9} ${a3p9} ${a9p9})" + +# Convert the output into a regexp. +set r1p [string_to_regexp $a1p] +set r1p9 [string_to_regexp $a1p9] +set r2po [string_to_regexp $a2po] +set r2p9o [string_to_regexp $a2p9o] +set r2p [string_to_regexp $a2p] +set r2p9 [string_to_regexp $a2p9] +set r3po [string_to_regexp $a3po] +set r3p9o [string_to_regexp $a3p9o] +set r3p [string_to_regexp $a3p] +set r3p9 [string_to_regexp $a3p9] + +set rep5 "<repeats 5 times>" +set rep6 "<repeats 6 times>" + +proc array_repeat { variant } { + global testfile srcfile binfile + upvar r1p r1p r1p9 r1p9 r2po r2po r2p9o r2p9o r2p r2p r2p9 r2p9 + upvar r3po r3po r3p9o r3p9o r3p r3p r3p9 r3p9 + upvar a2po a2po a2p9o a2p9o a3po a3po a3p9o a3p9o + upvar rep5 rep5 rep6 rep6 + + standard_testfile "${variant}.f90" + + if {[prepare_for_testing ${testfile}.exp ${variant} ${srcfile} \ + {debug f90}]} { + return -1 + } + + if {![fortran_runto_main]} { + perror "Could not run to main." + continue + } + + gdb_breakpoint [gdb_get_line_number "Break here"] + gdb_continue_to_breakpoint "${variant}" + + with_test_prefix "${variant}: repeats=unlimited, elements=unlimited" { + # Check the arrays print as expected. + gdb_test_no_output "set print repeats unlimited" + gdb_test_no_output "set print elements unlimited" + + gdb_test "print array_1d" "${r1p}" + gdb_test "print array_1d9" "${r1p9}" + gdb_test "print array_2d" "${r2p}" + gdb_test "print array_2d9" "${r2p9}" + gdb_test "print array_3d" "${r3p}" + gdb_test "print array_3d9" "${r3p9}" + } + + with_test_prefix "${variant}: repeats=4, elements=unlimited" { + # Now set the repeat limit. + gdb_test_no_output "set print repeats 4" + gdb_test_no_output "set print elements unlimited" + + gdb_test "print array_1d" \ + [string_to_regexp "(1, ${rep5})"] + gdb_test "print array_1d9" \ + [string_to_regexp "(1, ${rep5}, 9)"] + gdb_test "print array_2d" \ + [string_to_regexp "((2, ${rep5}) ${rep5})"] + gdb_test "print array_2d9" \ + [string_to_regexp "((2, ${rep5}, 9) ${rep5} (9, ${rep6}))"] + gdb_test "print array_3d" \ + [string_to_regexp "(((3, ${rep5}) ${rep5}) ${rep5})"] + gdb_test "print array_3d9" \ + [string_to_regexp "(((3, ${rep5}, 9) ${rep5} (9, ${rep6})) ${rep5}\ + ((9, ${rep6}) ${rep6}))"] + } + + with_test_prefix "${variant}: repeats=unlimited, elements=12" { + # Now set the element limit. + gdb_test_no_output "set print repeats unlimited" + gdb_test_no_output "set print elements 12" + + gdb_test "print array_1d" "${r1p}" + gdb_test "print array_1d9" "${r1p9}" + gdb_test "print array_2d" \ + [string_to_regexp "(${a2po} ${a2po} (2, 2, ...) ...)"] + gdb_test "print array_2d9" \ + [string_to_regexp "(${a2p9o} ${a2p9o} ...)"] + gdb_test "print array_3d" \ + [string_to_regexp "((${a3po} ${a3po} (3, 3, ...) ...) ...)"] + gdb_test "print array_3d9" \ + [string_to_regexp "((${a3p9o} ${a3p9o} ...) ...)"] + } + + with_test_prefix "${variant}: repeats=4, elements=12" { + # Now set both limits. + gdb_test_no_output "set print repeats 4" + gdb_test_no_output "set print elements 12" + + gdb_test "print array_1d" \ + [string_to_regexp "(1, ${rep5})"] + gdb_test "print array_1d9" \ + [string_to_regexp "(1, ${rep5}, 9)"] + gdb_test "print array_2d" \ + [string_to_regexp "((2, ${rep5}) (2, ${rep5}) (2, 2, ...) ...)"] + gdb_test "print array_2d9" \ + [string_to_regexp "((2, ${rep5}, 9) (2, ${rep5}, 9) ...)"] + gdb_test "print array_3d" \ + [string_to_regexp "(((3, ${rep5}) (3, ${rep5}) (3, 3, ...) ...)\ + ...)"] + gdb_test "print array_3d9" \ + [string_to_regexp "(((3, ${rep5}, 9) (3, ${rep5}, 9) ...) ...)"] + } + + with_test_prefix "${variant}: repeats=4, elements=30" { + # Now set both limits. + gdb_test_no_output "set print repeats 4" + gdb_test_no_output "set print elements 30" + + gdb_test "print array_1d" \ + [string_to_regexp "(1, ${rep5})"] + gdb_test "print array_1d9" \ + [string_to_regexp "(1, ${rep5}, 9)"] + gdb_test "print array_2d" \ + [string_to_regexp "((2, ${rep5}) ${rep5})"] + gdb_test "print array_2d9" \ + [string_to_regexp "((2, ${rep5}, 9) ${rep5} ...)"] + gdb_test "print array_3d" \ + [string_to_regexp "(((3, ${rep5}) ${rep5}) ((3, ${rep5}) ...)\ + ...)"] + gdb_test "print array_3d9" \ + [string_to_regexp "(((3, ${rep5}, 9) ${rep5} ...) ...)"] + } +} + +array_repeat "array-repeat" +array_repeat "array-slices-repeat" diff --git a/gdb/testsuite/gdb.fortran/array-repeat.f90 b/gdb/testsuite/gdb.fortran/array-repeat.f90 new file mode 100644 index 0000000..adb6b2a --- /dev/null +++ b/gdb/testsuite/gdb.fortran/array-repeat.f90 @@ -0,0 +1,50 @@ +! Copyright 2022 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 <http://www.gnu.org/licenses/>. + +! +! Start of test program. +! +program test + + ! Declare variables used in this test. + integer, dimension (-2:2) :: array_1d + integer, dimension (-2:3) :: array_1d9 + integer, dimension (-2:2, -2:2) :: array_2d + integer, dimension (-2:3, -2:3) :: array_2d9 + integer, dimension (-2:2, -2:2, -2:2) :: array_3d + integer, dimension (-2:3, -2:3, -2:3) :: array_3d9 + + array_1d = 1 + array_1d9 = 1 + array_1d9 (3) = 9 + array_2d = 2 + array_2d9 = 2 + array_2d9 (3, :) = 9 + array_2d9 (:, 3) = 9 + array_3d = 3 + array_3d9 = 3 + array_3d9 (3, :, :) = 9 + array_3d9 (:, 3, :) = 9 + array_3d9 (:, :, 3) = 9 + + print *, "" ! Break here + print *, array_1d + print *, array_1d9 + print *, array_2d + print *, array_2d9 + print *, array_3d + print *, array_3d9 + +end program test diff --git a/gdb/testsuite/gdb.fortran/array-slices-repeat.f90 b/gdb/testsuite/gdb.fortran/array-slices-repeat.f90 new file mode 100644 index 0000000..3b9a9e3 --- /dev/null +++ b/gdb/testsuite/gdb.fortran/array-slices-repeat.f90 @@ -0,0 +1,99 @@ +! Copyright 2022 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 <http://www.gnu.org/licenses/>. + +subroutine show (array_1d, array_1d9, array_2d, array_2d9, array_3d, array_3d9) + integer, dimension (-2:) :: array_1d + integer, dimension (-2:) :: array_1d9 + integer, dimension (-2:, -2:) :: array_2d + integer, dimension (-2:, -2:) :: array_2d9 + integer, dimension (-2:, -2:, -2:) :: array_3d + integer, dimension (-2:, -2:, -2:) :: array_3d9 + + print *, "" ! Break here + print *, array_1d + print *, array_1d9 + print *, array_2d + print *, array_2d9 + print *, array_3d + print *, array_3d9 +end subroutine show + +! +! Start of test program. +! +program test + interface + subroutine show (array_1d, array_1d9, array_2d, array_2d9, & + array_3d, array_3d9) + integer, dimension (:) :: array_1d + integer, dimension (:) :: array_1d9 + integer, dimension (:, :) :: array_2d + integer, dimension (:, :) :: array_2d9 + integer, dimension (:, :, :) :: array_3d + integer, dimension (:, :, :) :: array_3d9 + end subroutine show + end interface + + ! Declare variables used in this test. + integer, dimension (-8:6) :: array_1d + integer, dimension (-8:9) :: array_1d9 + integer, dimension (-8:6, -8:6) :: array_2d + integer, dimension (-8:9, -8:9) :: array_2d9 + integer, dimension (-8:6, -8:6, -8:6) :: array_3d + integer, dimension (-8:9, -8:9, -8:9) :: array_3d9 + + integer, parameter :: v6 (6) = [-5, -4, -3, 1, 2, 3] + integer, parameter :: v9 (9) = [-5, -4, -3, 1, 2, 3, 7, 8, 9] + + ! Intersperse slices selected with varying data to make sure it is + ! correctly ignored for the purpose of repeated element recognition + ! in the slices. + array_1d = 7 + array_1d (::3) = 1 + array_1d9 = 7 + array_1d9 (::3) = 1 + array_1d9 (7) = 9 + array_2d = 7 + array_2d (:, v6) = 6 + array_2d (::3, ::3) = 2 + array_2d9 = 7 + array_2d9 (:, v9) = 6 + array_2d9 (::3, ::3) = 2 + array_2d9 (7, ::3) = 9 + array_2d9 (::3, 7) = 9 + array_3d = 7 + array_3d (:, v6, :) = 6 + array_3d (:, v6, v6) = 5 + array_3d (::3, ::3, ::3) = 3 + array_3d9 = 7 + array_3d9 (:, v9, :) = 6 + array_3d9 (:, v9, v9) = 5 + array_3d9 (::3, ::3, ::3) = 3 + array_3d9 (7, ::3, ::3) = 9 + array_3d9 (::3, 7, ::3) = 9 + array_3d9 (::3, ::3, 7) = 9 + + call show (array_1d (::3), array_1d9 (::3), & + array_2d (::3, ::3), array_2d9 (::3, ::3), & + array_3d (::3, ::3, ::3), array_3d9 (::3, ::3, ::3)) + + print *, array_1d + print *, array_1d9 + print *, array_2d + print *, array_2d9 + print *, array_3d + print *, array_3d9 + +end program test diff --git a/gdb/testsuite/gdb.fortran/vla-value-sub-finish.exp b/gdb/testsuite/gdb.fortran/vla-value-sub-finish.exp index ec1dd55..7b7b489 100644 --- a/gdb/testsuite/gdb.fortran/vla-value-sub-finish.exp +++ b/gdb/testsuite/gdb.fortran/vla-value-sub-finish.exp @@ -32,6 +32,8 @@ if ![fortran_runto_main] { # We need both variants as depending on the arch we optionally may still be # executing the caller line or not after `finish'. +gdb_test_no_output "set print repeats unlimited" + gdb_breakpoint [gdb_get_line_number "array2-almost-filled"] gdb_continue_to_breakpoint "array2-almost-filled" # array2 size is 296352 bytes. diff --git a/gdb/testsuite/gdb.fortran/vla-value-sub.exp b/gdb/testsuite/gdb.fortran/vla-value-sub.exp index 0aa9a42..b7ab7a5 100644 --- a/gdb/testsuite/gdb.fortran/vla-value-sub.exp +++ b/gdb/testsuite/gdb.fortran/vla-value-sub.exp @@ -29,6 +29,8 @@ if ![fortran_runto_main] { # Check the values of VLA's in subroutine can be evaluated correctly +gdb_test_no_output "set print repeats unlimited" + # Try to access values from a fixed array handled as VLA in subroutine. gdb_breakpoint [gdb_get_line_number "not-filled"] gdb_continue_to_breakpoint "not-filled (1st)" |