]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/testsuite/gdb.base/bitshift.exp
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / testsuite / gdb.base / bitshift.exp
CommitLineData
1d506c26 1# Copyright 2022-2024 Free Software Foundation, Inc.
6849c6a2
PA
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# Test left and right bit shifting, in all languages that have such
17# operator.
18
19clean_restart
20
21# Test a print command that prints out RESULT_RE. If WARNING_OR_ERROR
22# is non-empty, it is expected that for languages other than Go, GDB
23# prints this warning before the print result. For Go, this is an
24# expected error. If WARNING_OR_ERROR is empty, it is expected that
25# GDB prints no text other than the print result.
26proc test_shift {lang cmd result_re {warning_or_error ""}} {
6849c6a2
PA
27 if {$lang == "go"} {
28 if {$warning_or_error != ""} {
29 set error_re "[string_to_regexp $warning_or_error]"
30 gdb_test_multiple $cmd "" {
a68f7e98 31 -re -wrap "^$error_re" {
6849c6a2
PA
32 pass $gdb_test_name
33 }
34 }
35 } else {
36 gdb_test_multiple $cmd "" {
a68f7e98 37 -re -wrap "^\\$$::decimal$result_re" {
6849c6a2
PA
38 pass $gdb_test_name
39 }
40 }
41 }
42 } else {
43 if {$warning_or_error != ""} {
44 set warning_re "warning: [string_to_regexp $warning_or_error]\r\n"
45 } else {
46 set warning_re ""
47 }
48
49 gdb_test_multiple $cmd "" {
a68f7e98 50 -re -wrap "^$warning_re\\$$::decimal$result_re" {
6849c6a2
PA
51 pass $gdb_test_name
52 }
53 }
54 }
55}
56
57# Some warnings/errors GDB outputs.
58set rs_negative_shift_count "right shift count is negative"
59set rs_too_large_shift_count "right shift count >= width of type"
60set ls_negative_shift_count "left shift count is negative"
61set ls_too_large_shift_count "left shift count >= width of type"
62
63# Test a left shift that results in a too-large shift count warning in
64# all languages except Go.
65proc test_lshift_tl {lang cmd result_re} {
66 if {$lang != "go"} {
67 test_shift $lang $cmd $result_re $::ls_too_large_shift_count
68 } else {
69 test_shift $lang $cmd $result_re
70 }
71}
72
73# Test a right shift that results in a too-large shift count warning
74# in all languages except Go.
75proc test_rshift_tl {lang cmd result_re} {
76 if {$lang != "go"} {
77 test_shift $lang $cmd $result_re $::rs_too_large_shift_count
78 } else {
79 test_shift $lang $cmd $result_re
80 }
81}
82
83# Return VAL, an integer value converted/cast to the right type for
84# LANG. SIGNED indicates whether the type should be signed or
85# unsigned. BITS indicates the bit width of the type. E.g., signed=0
86# and bits=32 results in:
87# Go => "uint($VAL)"
88# D => "cast(uint) $VAL"
89# Rust => "$VAL as i32"
90# C/C++/others => "(unsigned int) $VAL"
91proc make_val_cast {lang signed bits val} {
92 if {$lang == "go"} {
93 if {$signed} {
94 set sign_prefix ""
95 } else {
96 set sign_prefix "u"
97 }
98 return "${sign_prefix}int${bits}($val)"
99 } elseif {$lang == "d"} {
100 if {$signed} {
101 set sign_prefix ""
102 } else {
103 set sign_prefix "u"
104 }
105 if {$bits == 8} {
106 set type "byte"
107 } elseif {$bits == 16} {
108 set type "short"
109 } elseif {$bits == 32} {
110 set type "int"
111 } elseif {$bits == 64} {
112 set type "long"
113 } else {
114 error "$lang: unsupported bits"
115 }
116 return "cast(${sign_prefix}$type) $val"
117 } elseif {$lang == "rust"} {
118 if {$signed} {
119 set sign_prefix "i"
120 } else {
121 set sign_prefix "u"
122 }
123 return "$val as ${sign_prefix}$bits"
124 } else {
125 # C-like cast.
126 if {$signed} {
127 set sign_prefix ""
128 } else {
129 set sign_prefix "un"
130 }
131 if {$bits == 8} {
132 set type "char"
133 } elseif {$bits == 16} {
134 set type "short"
135 } elseif {$bits == 32} {
136 set type "int"
137 } elseif {$bits == 64} {
138 if {$lang == "opencl"} {
139 set type "long"
140 } else {
141 set type "long long"
142 }
143 } else {
144 error "$lang: unsupported bits"
145 }
146 return "(${sign_prefix}signed $type) $val"
147 }
148}
149
150# Generate make_int8 ... make_uint64 convenience procs, wrappers
151# around make_val_cast.
152foreach signed {0 1} {
153 if {$signed} {
154 set sign_prefix ""
155 } else {
156 set sign_prefix "u"
157 }
158 foreach bits {8 16 32 64} {
159 proc make_${sign_prefix}int${bits} {lang val} \
160 "make_val_cast \$lang $signed $bits \$val"
161 }
162}
163
164# Test bitshifting, particularly with negative shift counts and
165# too-large-for-type shift counts. Exercises all C-like-ish
166# languages.
167proc test_shifts {} {
168 global ls_negative_shift_count rs_negative_shift_count
169
170 # Extract the set of all supported languages. We try all except
171 # languages we know wouldn't work. We do this instead of
172 # hardcoding the set of languages that we know work, so that if
173 # GDB gains a new language, it is automatically exercised.
174 set supported_langs [get_set_option_choices "set language"]
175
176 foreach_with_prefix lang $supported_langs {
177 set skip_langs {
178 "unknown" "ada" "modula-2" "pascal" "fortran"
179 }
180 if {[lsearch -exact $skip_langs $lang] >= 0} {
cdd42066 181 return
6849c6a2
PA
182 }
183
184 gdb_test_no_output "set language $lang"
185
186 # Make sure a signed left shift that overflows, i.e., whose
187 # result isn't representable in the signed type of the lhs,
188 # which is actually undefined, doesn't crash GDB when is it
189 # built with UBSan.
190
191 with_test_prefix "lsh overflow" {
192 test_shift $lang "print /x 0x0fffffffffffffff << 8" \
193 " = 0xffffffffffffff00"
194 test_shift $lang "print /x 0x0fffffff << 8" \
195 " = 0xffffff00"
196
197 # Make sure the result is still signed when the lhs was
198 # signed.
199 test_shift $lang "print 0x0fffffffffffffff << 8" " = -256"
200 test_shift $lang "print 0x0fffffff << 8" " = -256"
201 }
202
203 # 8-bit and 16-bit are promoted to int.
204 with_test_prefix "8-bit, promoted" {
205 foreach lhs \
206 [list \
207 [make_int8 $lang 0x0f] \
208 [make_uint8 $lang 0x0f]] \
209 {
210 test_shift $lang "print /x $lhs << 8" " = 0xf00"
211 test_shift $lang "print $lhs << 8" " = 3840"
212 }
213 }
214 with_test_prefix "16-bit, promoted" {
215 foreach lhs \
216 [list \
217 [make_int16 $lang 0x0fff] \
218 [make_uint16 $lang 0x0fff]] \
219 {
220 test_shift $lang "print /x $lhs << 8" " = 0xfff00"
221 test_shift $lang "print $lhs << 8" " = 1048320"
222 }
223 }
224
225 # Similarly, test shifting with both negative and too-large
226 # rhs. Both cases are undefined, but GDB lets them go through
227 # anyhow, similarly to how compilers don't error out. Try
228 # both signed and unsigned lhs.
229
230 # 8-bit lhs, signed and unsigned. These get promoted to
231 # 32-bit int.
232 with_test_prefix "8-bit, invalid" {
233 foreach lhs \
234 [list \
235 [make_int8 $lang 0x7f] \
236 [make_uint8 $lang 0xff]] \
237 {
238 test_shift $lang "print $lhs << -1" " = 0" \
239 $ls_negative_shift_count
240 test_shift $lang "print $lhs >> -1" " = 0" \
241 $rs_negative_shift_count
242
243 test_shift $lang "print/x $lhs << 8" " = 0x(7|f)f00"
244 test_shift $lang "print/x $lhs >> 8" " = 0x0"
245
246 test_lshift_tl $lang "print $lhs << 32" " = 0"
247 test_rshift_tl $lang "print $lhs >> 32" " = 0"
248 test_lshift_tl $lang "print $lhs << 33" " = 0"
249 test_rshift_tl $lang "print $lhs >> 33" " = 0"
250 }
251 }
252
253 # 16-bit lhs, signed and unsigned. These get promoted to 32-bit int.
254 with_test_prefix "16-bit, invalid" {
255 foreach {lhs res} \
256 [list \
257 [make_int16 $lang 0x7fff] 0x7fff \
258 [make_uint16 $lang 0xffff] 0xffff] \
259 {
260 test_shift $lang "print $lhs << -1" " = 0" \
261 $ls_negative_shift_count
262 test_shift $lang "print $lhs >> -1" " = 0" \
263 $rs_negative_shift_count
264
265 # Confirm shifting by 0 doesn't warn.
266 test_shift $lang "print/x $lhs << 0" " = $res"
267 test_shift $lang "print/x $lhs >> 0" " = $res"
268
269 # These don't overflow due to promotion.
270 test_shift $lang "print/x $lhs << 16" " = 0x(7|f)fff0000"
271 test_shift $lang "print/x $lhs >> 16" " = 0x0"
272
273 test_lshift_tl $lang "print $lhs << 32" " = 0"
274 test_rshift_tl $lang "print $lhs >> 32" " = 0"
275 test_lshift_tl $lang "print $lhs << 33" " = 0"
276 test_rshift_tl $lang "print $lhs >> 33" " = 0"
277 }
278 }
279
280 # 32-bit lhs, signed and unsigned.
281 with_test_prefix "32-bit, invalid" {
282 foreach {lhs res} \
283 [list \
284 [make_int32 $lang 0x7fffffff] 0x7fffffff \
285 [make_uint32 $lang 0xffffffff] 0xffffffff] \
286 {
287 test_shift $lang "print $lhs << -1" " = 0" \
288 $ls_negative_shift_count
289 test_shift $lang "print $lhs >> -1" " = 0" \
290 $rs_negative_shift_count
291
292 # Confirm shifting by 0 doesn't warn.
293 test_shift $lang "print/x $lhs << 0" " = $res"
294 test_shift $lang "print/x $lhs >> 0" " = $res"
295
296 test_lshift_tl $lang "print $lhs << 32" " = 0"
297 test_rshift_tl $lang "print $lhs >> 32" " = 0"
298
299 test_lshift_tl $lang "print $lhs << 33" " = 0"
300 test_rshift_tl $lang "print $lhs >> 33" " = 0"
301 }
302 }
303
304 # 64-bit lhs, signed and unsigned.
305 with_test_prefix "64-bit, invalid" {
306 foreach {lhs res} \
307 [list \
308 [make_int64 $lang 0x7fffffffffffffff] \
309 0x7fffffffffffffff \
310 \
311 [make_uint64 $lang 0xffffffffffffffff] \
312 0xffffffffffffffff] \
313 {
314 test_shift $lang "print $lhs << -1" " = 0" \
315 $ls_negative_shift_count
316 test_shift $lang "print $lhs >> -1" " = 0" \
317 $rs_negative_shift_count
318
319 # Confirm shifting by 0 doesn't warn.
320 test_shift $lang "print/x $lhs << 0" " = $res"
321 test_shift $lang "print/x $lhs >> 0" " = $res"
322
323 test_lshift_tl $lang "print $lhs << 64" " = 0"
324 test_rshift_tl $lang "print $lhs >> 64" " = 0"
325
326 test_lshift_tl $lang "print $lhs << 65" " = 0"
327 test_rshift_tl $lang "print $lhs >> 65" " = 0"
328 }
329 }
330
331 # Right shift a negative number by a negative amount.
332 with_test_prefix "neg lhs/rhs" {
333 test_shift $lang "print -1 >> -1" " = -1" $rs_negative_shift_count
334 test_shift $lang "print -4 >> -2" " = -1" $rs_negative_shift_count
335 }
336
337 # Check right shifting a negative value. For C++, this is
338 # implementation-defined, up until C++20. In most
339 # implementations, this performs an arithmetic right shift, so
340 # that the result remains negative. Currently, GDB does
341 # whatever the host's compiler does. If that turns out wrong
342 # for some host/target, then GDB should be taught to ask the
343 # target gdbarch what to do.
344 with_test_prefix "rsh neg lhs" {
345 test_shift $lang "print -1 >> 0" " = -1"
346 test_shift $lang "print -1 >> 1" " = -1"
347 test_shift $lang "print -8 >> 1" " = -4"
348 test_shift $lang "print [make_int64 $lang -8] >> 1" " = -4"
349 }
350
351 # Make sure an unsigned 64-bit value with high bit set isn't
352 # confused for a negative shift count in the warning messages.
353 with_test_prefix "max-uint64" {
354 test_lshift_tl $lang \
355 "print 1 << [make_uint64 $lang 0xffffffffffffffff]" " = 0"
356 test_rshift_tl $lang \
357 "print 1 >> [make_uint64 $lang 0xffffffffffffffff]" " = 0"
358 test_lshift_tl $lang \
359 "print -1 << [make_uint64 $lang 0xffffffffffffffff]" " = 0"
360 test_rshift_tl $lang \
361 "print -1 >> [make_uint64 $lang 0xffffffffffffffff]" " = -1"
362 }
363 }
364}
365
366test_shifts