summaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2022-06-04 13:17:33 +0200
committerTom de Vries <tdevries@suse.de>2022-06-04 13:17:33 +0200
commit1d8c0dfae79a5183e9e3311fb867afd679bc8e84 (patch)
tree2415ed745f9dc5a2828564fe0e90af01b93fcadb /gdb/testsuite
parent1b4633f812b329863a523c4d798c2b55417b5144 (diff)
[gdb/c] Fix type of 2147483648 and literal truncation
[ Assuming arch i386:x86-64, sizeof (int) == 4, sizeof (long) == sizeof (long long) == 8. ] Currently we have (decimal for 0x80000000): ... (gdb) ptype 2147483648 type = unsigned int ... According to C language rules, unsigned types cannot be used for decimal constants, so the type should be long instead (reported in PR16377). Fix this by making sure the type of 2147483648 is long. The next interesting case is (decimal for 0x8000000000000000): ... (gdb) ptype 9223372036854775808 type = unsigned long ... According to the same rules, unsigned long is incorrect. Current gcc uses __int128 as type, which is allowed, but we don't have that available in gdb, so the strict response here would be erroring out with overflow. Older gcc without __int128 support, as well as clang use an unsigned type, but with a warning. Interestingly, clang uses "unsigned long long" while gcc uses "unsigned long", which seems the better choice. Given that the compilers allow this as a convience, do the same in gdb and keep type "unsigned long", and make this explicit in parser and test-case. Furthermore, make sure we error out on overflow instead of truncating in all cases. Tested on x86_64-linux with --enable-targets=all. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=16377
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/gdb.base/parse_number.exp56
1 files changed, 47 insertions, 9 deletions
diff --git a/gdb/testsuite/gdb.base/parse_number.exp b/gdb/testsuite/gdb.base/parse_number.exp
index 7c259e0a8a..638ea34238 100644
--- a/gdb/testsuite/gdb.base/parse_number.exp
+++ b/gdb/testsuite/gdb.base/parse_number.exp
@@ -68,6 +68,22 @@ proc fits_in_type { n type_bits type_signedness } {
}
}
+# Return 1 if LANG is a c-like language, in the sense that it uses the same
+# parser.
+
+proc c_like { lang } {
+ set res 0
+ switch $lang {
+ c
+ - c++
+ - asm
+ - objective-c
+ - opencl
+ - minimal {set res 1}
+ }
+ return $res
+}
+
# Parse number N for LANG, and return a list of expected type and value.
proc parse_number { lang n } {
@@ -165,26 +181,48 @@ proc parse_number { lang n } {
($any|$re_overflow)]
}
} else {
- # This is wrong for c-like languages. For the decimal case, we
- # shouldn't use unsigned.
- # See PR 16377.
+ if { [c_like $lang] } {
+ if { $hex_p } {
+ # C Hex.
+ set have_unsigned 1
+ } else {
+ # C Decimal. Unsigned not allowed according.
+ if { [fits_in_type $n $long_long_bits s] } {
+ # Fits in largest signed type.
+ set have_unsigned 0
+ } else {
+ # Doesn't fit in largest signed type, so ill-formed, but
+ # allow unsigned as a convenience, as compilers do (though
+ # with a warning).
+ set have_unsigned 1
+ }
+ }
+ } else {
+ # Non-C.
+ set have_unsigned 1
+ }
+
if { [fits_in_type $n $int_bits s] } {
return [list int $n]
- } elseif { [fits_in_type $n $int_bits u] } {
+ } elseif { $have_unsigned && [fits_in_type $n $int_bits u] } {
return [list "unsigned int" $n]
} elseif { [fits_in_type $n $long_bits s] } {
return [list long $n]
- } elseif { [fits_in_type $n $long_bits u] } {
+ } elseif { $have_unsigned && [fits_in_type $n $long_bits u] } {
return [list "unsigned long" $n]
} elseif { [fits_in_type $n $long_long_bits s] } {
return [list "long long" $n]
- } elseif { [fits_in_type $n $long_long_bits u] } {
+ } elseif { $have_unsigned && [fits_in_type $n $long_long_bits u] } {
return [list "unsigned long long" $n]
} else {
# Overflow.
- # Some truncated value or re_overflow, should be re_overflow.
- return [list "((unsigned )?(int|long)|$re_overflow)" \
- ($any|$re_overflow)]
+ if { [c_like $lang] } {
+ return [list $re_overflow $re_overflow]
+ } else {
+ # Some truncated value or re_overflow, should be re_overflow.
+ return [list "((unsigned )?(int|long)|$re_overflow)" \
+ ($any|$re_overflow)]
+ }
}
}