]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/testsuite/gdb.fortran/array-slices.exp
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.fortran / array-slices.exp
CommitLineData
213516ef 1# Copyright 2019-2023 Free Software Foundation, Inc.
5bbd8269
AB
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/> .
15
16# Print a 2 dimensional assumed shape array. We pass different slices
17# of the array to a subroutine and print the array as recieved within
18# the subroutine. This should exercise GDB's ability to handle
19# different strides for the different dimensions.
20
a5c641b5
AB
21# Testing GDB's ability to print array (and string) slices, including
22# slices that make use of array strides.
23#
24# In the Fortran code various arrays of different ranks are filled
25# with data, and slices are passed to a series of show functions.
26#
27# In this test script we break in each of the show functions, print
28# the array slice that was passed in, and then move up the stack to
29# the parent frame and check GDB can manually extract the same slice.
30#
31# This test also checks that the size of the array slice passed to the
32# function (so as extracted and described by the compiler and the
33# debug information) matches the size of the slice manually extracted
34# by GDB.
35
5bbd8269
AB
36if {[skip_fortran_tests]} { return -1 }
37
9bde221f
PA
38# This test relies on output from the inferior.
39if [target_info exists gdb,noinferiorio] {
40 return -1
41}
42
5bbd8269 43standard_testfile ".f90"
86cd6bc8 44load_lib fortran.exp
5bbd8269 45
98bf5c02 46if {[build_executable ${testfile}.exp ${testfile} ${srcfile} \
5bbd8269
AB
47 {debug f90}]} {
48 return -1
49}
50
a5c641b5
AB
51# Takes the name of an array slice as used in the test source, and extracts
52# the base array name. For example: 'array (1,2)' becomes 'array'.
53proc array_slice_to_var { slice_str } {
54 regexp "^(?:\\s*\\()*(\[^( \t\]+)" $slice_str matchvar varname
55 return $varname
5bbd8269
AB
56}
57
a5c641b5
AB
58proc run_test { repack } {
59 global binfile gdb_prompt
60
61 clean_restart ${binfile}
62
c8ed8c8a
TV
63 # Avoid shared lib symbols.
64 gdb_test_no_output "set auto-solib-add off"
65
a5c641b5 66 if ![fortran_runto_main] {
a5c641b5 67 return -1
5bbd8269 68 }
5bbd8269 69
c8ed8c8a
TV
70 # Avoid libc symbols, in particular the 'array' type.
71 gdb_test_no_output "nosharedlibrary"
72
a5c641b5
AB
73 gdb_test_no_output "set fortran repack-array-slices $repack"
74
75 # gdb_breakpoint [gdb_get_line_number "Display Message Breakpoint"]
76 gdb_breakpoint [gdb_get_line_number "Display Element"]
77 gdb_breakpoint [gdb_get_line_number "Display String"]
78 gdb_breakpoint [gdb_get_line_number "Display Array Slice 1D"]
79 gdb_breakpoint [gdb_get_line_number "Display Array Slice 2D"]
80 gdb_breakpoint [gdb_get_line_number "Display Array Slice 3D"]
81 gdb_breakpoint [gdb_get_line_number "Display Array Slice 4D"]
82 gdb_breakpoint [gdb_get_line_number "Final Breakpoint"]
83
84 # We're going to print some reasonably large arrays.
85 gdb_test_no_output "set print elements unlimited"
86
87 set found_final_breakpoint false
88
89 # We place a limit on the number of tests that can be run, just in
90 # case something goes wrong, and GDB gets stuck in an loop here.
91 set test_count 0
92 while { $test_count < 500 } {
93 with_test_prefix "test $test_count" {
94 incr test_count
95
96 set found_final_breakpoint false
97 set expected_result ""
98 set func_name ""
9bde221f 99 set found_prompt false
a5c641b5 100 gdb_test_multiple "continue" "continue" {
9bde221f
PA
101 -i $::inferior_spawn_id
102
a5c641b5
AB
103 -re ".*GDB = (\[^\r\n\]+)\r\n" {
104 set expected_result $expect_out(1,string)
9bde221f
PA
105 if {!$found_prompt} {
106 exp_continue
107 }
a5c641b5 108 }
9bde221f
PA
109
110 -i $::gdb_spawn_id
111
a5c641b5
AB
112 -re "! Display Element" {
113 set func_name "show_elem"
114 exp_continue
115 }
116 -re "! Display String" {
117 set func_name "show_str"
118 exp_continue
119 }
120 -re "! Display Array Slice (.)D" {
121 set func_name "show_$expect_out(1,string)d"
122 exp_continue
123 }
124 -re "! Final Breakpoint" {
125 set found_final_breakpoint true
126 exp_continue
127 }
128 -re "$gdb_prompt $" {
9bde221f
PA
129 set found_prompt true
130
131 if {$found_final_breakpoint
132 || ($expected_result != "" && $func_name != "")} {
133 # We're done.
134 } else {
135 exp_continue
136 }
a5c641b5
AB
137 }
138 }
6b4c676c 139
a5c641b5
AB
140 if ($found_final_breakpoint) {
141 break
142 }
6b4c676c 143
a5c641b5
AB
144 # We want to take a look at the line in the previous frame that
145 # called the current function. I couldn't find a better way of
146 # doing this than 'up', which will print the line, then 'down'
147 # again.
148 #
149 # I don't want to fill the log with passes for these up/down
150 # commands, so we don't report any. If something goes wrong then we
151 # should get a fail from gdb_test_multiple.
152 set array_slice_name ""
153 set unique_id ""
154 array unset replacement_vars
155 array set replacement_vars {}
156 gdb_test_multiple "up" "up" {
157 -re "\r\n\[0-9\]+\[ \t\]+call ${func_name} \\((\[^\r\n\]+)\\)\r\n$gdb_prompt $" {
158 set array_slice_name $expect_out(1,string)
159 }
160 -re "\r\n\[0-9\]+\[ \t\]+call ${func_name} \\((\[^\r\n\]+)\\)\[ \t\]+! VARS=(\[^ \t\r\n\]+)\r\n$gdb_prompt $" {
161 set array_slice_name $expect_out(1,string)
162 set unique_id $expect_out(2,string)
163 }
164 }
165 if {$unique_id != ""} {
166 set str ""
167 foreach v [split $unique_id ,] {
168 set val [get_integer_valueof "${v}" "??"\
169 "get variable '$v' for '$array_slice_name'"]
170 set replacement_vars($v) $val
171 if {$str != ""} {
172 set str "Str,"
173 }
174 set str "$str$v=$val"
175 }
176 set unique_id " $str"
177 }
178 gdb_test_multiple "down" "down" {
179 -re "\r\n$gdb_prompt $" {
180 # Don't issue a pass here.
181 }
182 }
183
184 # Check we have all the information we need to successfully run one
185 # of these tests.
186 if { $expected_result == "" } {
187 perror "failed to extract expected results"
188 return 0
189 }
190 if { $array_slice_name == "" } {
191 perror "failed to extract array slice name"
192 return 0
193 }
194
195 # Check GDB can correctly print the array slice that was passed into
196 # the current frame.
197 set pattern [string_to_regexp " = $expected_result"]
198 gdb_test "p array" "$pattern" \
199 "check value of '$array_slice_name'$unique_id"
200
201 # Get the size of the slice.
202 set size_in_show \
203 [get_integer_valueof "sizeof (array)" "show_unknown" \
204 "get sizeof '$array_slice_name'$unique_id in show"]
205 set addr_in_show \
206 [get_hexadecimal_valueof "&array" "show_unknown" \
207 "get address '$array_slice_name'$unique_id in show"]
208
209 # Now move into the previous frame, and see if GDB can extract the
210 # array slice from the original parent object. Again, use of
211 # gdb_test_multiple to avoid filling the logs with unnecessary
212 # passes.
213 gdb_test_multiple "up" "up" {
214 -re "\r\n$gdb_prompt $" {
215 # Do nothing.
216 }
217 }
218
219 # Print the array slice, this will force GDB to manually extract the
220 # slice from the parent array.
221 gdb_test "p $array_slice_name" "$pattern" \
222 "check array slice '$array_slice_name'$unique_id can be extracted"
223
224 # Get the size of the slice in the calling frame.
225 set size_in_parent \
226 [get_integer_valueof "sizeof ($array_slice_name)" \
227 "parent_unknown" \
228 "get sizeof '$array_slice_name'$unique_id in parent"]
229
230 # Figure out the start and end addresses of the full array in the
231 # parent frame.
232 set full_var_name [array_slice_to_var $array_slice_name]
233 set start_addr [get_hexadecimal_valueof "&${full_var_name}" \
234 "start unknown"]
235 set end_addr [get_hexadecimal_valueof \
10f92414 236 "$start_addr + sizeof (${full_var_name})" \
02baa133
AB
237 "end unknown" \
238 "get end address of ${full_var_name}"]
a5c641b5
AB
239
240 # The Fortran compiler can choose to either send a descriptor that
241 # describes the array slice to the subroutine, or it can repack the
242 # slice into an array section and send that.
243 #
244 # We find the address range of the original array in the parent,
245 # and the address of the slice in the show function, if the
246 # address of the slice (from show) is in the range of the original
247 # array then repacking has not occurred, otherwise, the slice is
248 # outside of the parent, and repacking must have occurred.
249 #
250 # The goal here is to compare the sizes of the slice in show with
251 # the size of the slice extracted by GDB. So we can only compare
252 # sizes when GDB's repacking setting matches the repacking
253 # behaviour we got from the compiler.
254 if { ($addr_in_show < $start_addr || $addr_in_show >= $end_addr) \
255 == ($repack == "on") } {
256 gdb_assert {$size_in_show == $size_in_parent} \
257 "check sizes match"
258 } elseif { $repack == "off" } {
259 # GDB's repacking is off (so slices are left unpacked), but
260 # the compiler did pack this one. As a result we can't
261 # compare the sizes between the compiler's slice and GDB's
262 # slice.
263 verbose -log "slice '$array_slice_name' was repacked, sizes can't be compared"
264 } else {
265 # Like the above, but the reverse, GDB's repacking is on, but
266 # the compiler didn't repack this slice.
267 verbose -log "slice '$array_slice_name' was not repacked, sizes can't be compared"
268 }
269
270 # If the array name we just tested included variable names, then
271 # test again with all the variables expanded.
272 if {$unique_id != ""} {
273 foreach v [array names replacement_vars] {
274 set val $replacement_vars($v)
275 set array_slice_name \
276 [regsub "\\y${v}\\y" $array_slice_name $val]
277 }
278 gdb_test "p $array_slice_name" "$pattern" \
279 "check array slice '$array_slice_name'$unique_id can be extracted, with variables expanded"
280 }
281 }
282 }
283
284 # Ensure we reached the final breakpoint. If more tests have been added
285 # to the test script, and this starts failing, then the safety 'while'
286 # loop above might need to be increased.
287 gdb_assert {$found_final_breakpoint} "ran all tests"
6b4c676c
AB
288}
289
a5c641b5
AB
290foreach_with_prefix repack { on off } {
291 run_test $repack
292}