Module Name: src Committed By: rillig Date: Sat Sep 4 21:20:44 UTC 2021
Modified Files: src/tests/usr.bin/xlint/lint1: msg_117.c msg_117.exp Log Message: tests/lint: provide more background information on signed '>>' To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/tests/usr.bin/xlint/lint1/msg_117.c cvs rdiff -u -r1.8 -r1.9 src/tests/usr.bin/xlint/lint1/msg_117.exp Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/xlint/lint1/msg_117.c diff -u src/tests/usr.bin/xlint/lint1/msg_117.c:1.9 src/tests/usr.bin/xlint/lint1/msg_117.c:1.10 --- src/tests/usr.bin/xlint/lint1/msg_117.c:1.9 Fri Aug 27 17:59:46 2021 +++ src/tests/usr.bin/xlint/lint1/msg_117.c Sat Sep 4 21:20:44 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_117.c,v 1.9 2021/08/27 17:59:46 rillig Exp $ */ +/* $NetBSD: msg_117.c,v 1.10 2021/09/04 21:20:44 rillig Exp $ */ # 3 "msg_117.c" // Test for message: bitwise '%s' on signed value possibly nonportable [117] @@ -66,3 +66,70 @@ shr_unsigned_char_promoted_unsigned(unsi */ return (unsigned char)((unsigned char)(bit - 1) >> 5); } + +/* + * C90 3.3.7, C99 6.5.7 and C11 6.5.7 all say the same: If E1 has a signed + * type and a negative value, the resulting value is implementation-defined. + * + * These standards don't guarantee anything about the lower bits of the + * resulting value, which are generally independent of whether the shift is + * performed in signed arithmetics or in unsigned arithmetics. The C99 + * rationale talks about signed shifts, but does not provide any guarantee + * either. It merely suggests that platforms are free to use unsigned shifts + * even if the operand type is signed. + * + * K&R provides more guarantees by saying: Right shifting a signed quantity + * will fill with sign bits ("arithmetic shift") on some machines such as the + * PDP-Il, and with 0-bits ("logical shift") on others. + * + * https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html says: + * Signed '>>' acts on negative numbers by sign extension. + * + * This means that at least in GCC mode, lint may decide to not warn about + * these cases. + */ +void +shr_signed_ignoring_high_bits(int x) +{ + + /* + * All sane platforms should define that 'x >> 0 == x', even if x is + * negative. + */ + /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ + if (x >> 0 != 0) + return; + + /* + * If x is negative, x >> 1 is nonzero, no matter whether the shift + * is arithmetic or logical. + */ + /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ + if (x >> 1 != 0) + return; + + /* + * The highest bit may be 0 or 1, the others should be well-defined + * on all sane platforms, making it irrelevant whether the actual + * shift operation is arithmetic or logical. + */ + /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ + if (((x >> 1) & 1) != 0) + return; + + /* + * The result of this expression is the same with arithmetic and + * logical shifts since the filled bits are masked out. + */ + /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ + if (((x >> 31) & 1) != 0) + return; + + /* + * In this case, arithmetic shift results in 2 while logical shift + * results in 0. This difference is what this warning is about. + */ + /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ + if (((x >> 31) & 2) != 0) + return; +} Index: src/tests/usr.bin/xlint/lint1/msg_117.exp diff -u src/tests/usr.bin/xlint/lint1/msg_117.exp:1.8 src/tests/usr.bin/xlint/lint1/msg_117.exp:1.9 --- src/tests/usr.bin/xlint/lint1/msg_117.exp:1.8 Fri Aug 27 17:59:46 2021 +++ src/tests/usr.bin/xlint/lint1/msg_117.exp Sat Sep 4 21:20:44 2021 @@ -5,3 +5,8 @@ msg_117.c(29): warning: shift amount 466 msg_117.c(35): warning: bitwise '>>' on signed value possibly nonportable [117] msg_117.c(35): warning: negative shift [121] msg_117.c(57): warning: bitwise '>>' on signed value possibly nonportable [117] +msg_117.c(100): warning: bitwise '>>' on signed value possibly nonportable [117] +msg_117.c(108): warning: bitwise '>>' on signed value possibly nonportable [117] +msg_117.c(117): warning: bitwise '>>' on signed value possibly nonportable [117] +msg_117.c(125): warning: bitwise '>>' on signed value possibly nonportable [117] +msg_117.c(133): warning: bitwise '>>' on signed value possibly nonportable [117]