xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_117.c (revision e6298b924c5ba98f3a22919b56dab04a87cdbb1c)
1*e6298b92Srillig /*	$NetBSD: msg_117.c,v 1.14 2023/07/07 19:45:22 rillig Exp $	*/
2a0a15c14Srillig # 3 "msg_117.c"
3a0a15c14Srillig 
473fb62d3Srillig // Test for message: bitwise '%s' on signed value possibly nonportable [117]
5a0a15c14Srillig 
6*e6298b92Srillig /* lint1-extra-flags: -p -X 351 */
7e3ae774eSrillig 
8e3ae774eSrillig int
shr(int a,int b)9e3ae774eSrillig shr(int a, int b)
10e3ae774eSrillig {
1165e5c21bSrillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
1265e5c21bSrillig 	return a >> b;
13e3ae774eSrillig }
14e3ae774eSrillig 
15e3ae774eSrillig int
shr_lhs_constant_positive(int a)16e3ae774eSrillig shr_lhs_constant_positive(int a)
17e3ae774eSrillig {
18e3ae774eSrillig 	return 0x1234 >> a;
19e3ae774eSrillig }
20e3ae774eSrillig 
21e3ae774eSrillig int
shr_lhs_constant_negative(int a)22e3ae774eSrillig shr_lhs_constant_negative(int a)
23e3ae774eSrillig {
2465e5c21bSrillig 	/* expect+1: warning: bitwise '>>' on signed value nonportable [120] */
2565e5c21bSrillig 	return -0x1234 >> a;
26e3ae774eSrillig }
27e3ae774eSrillig 
28e3ae774eSrillig int
shr_rhs_constant_positive(int a)29e3ae774eSrillig shr_rhs_constant_positive(int a)
30e3ae774eSrillig {
3165e5c21bSrillig 	/* expect+2: warning: bitwise '>>' on signed value possibly nonportable [117] */
3265e5c21bSrillig 	/* expect+1: warning: shift amount 4660 is greater than bit-size 32 of 'int' [122] */
3365e5c21bSrillig 	return a >> 0x1234;
34e3ae774eSrillig }
35e3ae774eSrillig 
36e3ae774eSrillig int
shr_rhs_constant_negative(int a)37e3ae774eSrillig shr_rhs_constant_negative(int a)
38e3ae774eSrillig {
3965e5c21bSrillig 	/* expect+2: warning: bitwise '>>' on signed value possibly nonportable [117] */
4065e5c21bSrillig 	/* expect+1: warning: negative shift [121] */
4165e5c21bSrillig 	return a >> -0x1234;
42e3ae774eSrillig }
430064a1bcSrillig 
440064a1bcSrillig unsigned int
shr_unsigned_char(unsigned char uc)450064a1bcSrillig shr_unsigned_char(unsigned char uc)
460064a1bcSrillig {
473b353a6dSrillig 	/*
483b353a6dSrillig 	 * Even though 'uc' is promoted to 'int', it cannot be negative.
493b353a6dSrillig 	 * Before tree.c 1.335 from 2021-08-15, lint wrongly warned that
503b353a6dSrillig 	 * 'uc >> 4' might be a bitwise '>>' on signed value.
513b353a6dSrillig 	 */
520064a1bcSrillig 	return uc >> 4;
530064a1bcSrillig }
541da775bdSrillig 
551da775bdSrillig unsigned char
shr_unsigned_char_promoted_signed(unsigned char bit)561c32c722Srillig shr_unsigned_char_promoted_signed(unsigned char bit)
571da775bdSrillig {
581da775bdSrillig 	/*
591c32c722Srillig 	 * The possible values for 'bit' range from 0 to 255.  Subtracting 1
601c32c722Srillig 	 * from 0 results in a negative expression value.
611da775bdSrillig 	 */
621da775bdSrillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
631da775bdSrillig 	return (unsigned char)((bit - 1) >> 5);
641da775bdSrillig }
651c32c722Srillig 
661c32c722Srillig unsigned char
shr_unsigned_char_promoted_unsigned(unsigned char bit)671c32c722Srillig shr_unsigned_char_promoted_unsigned(unsigned char bit)
681c32c722Srillig {
691c32c722Srillig 	/*
701c32c722Srillig 	 * To prevent the above warning, the intermediate expression must be
711c32c722Srillig 	 * cast to 'unsigned char'.
721c32c722Srillig 	 */
731c32c722Srillig 	return (unsigned char)((unsigned char)(bit - 1) >> 5);
741c32c722Srillig }
7553c614b4Srillig 
7653c614b4Srillig /*
7753c614b4Srillig  * C90 3.3.7, C99 6.5.7 and C11 6.5.7 all say the same: If E1 has a signed
7853c614b4Srillig  * type and a negative value, the resulting value is implementation-defined.
7953c614b4Srillig  *
8053c614b4Srillig  * These standards don't guarantee anything about the lower bits of the
8153c614b4Srillig  * resulting value, which are generally independent of whether the shift is
8253c614b4Srillig  * performed in signed arithmetics or in unsigned arithmetics.  The C99
8353c614b4Srillig  * rationale talks about signed shifts, but does not provide any guarantee
8453c614b4Srillig  * either.  It merely suggests that platforms are free to use unsigned shifts
8553c614b4Srillig  * even if the operand type is signed.
8653c614b4Srillig  *
8753c614b4Srillig  * K&R provides more guarantees by saying: Right shifting a signed quantity
8853c614b4Srillig  * will fill with sign bits ("arithmetic shift") on some machines such as the
896b8b6837Srillig  * PDP-11, and with 0-bits ("logical shift") on others.
9053c614b4Srillig  *
9153c614b4Srillig  * https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html says:
9253c614b4Srillig  * Signed '>>' acts on negative numbers by sign extension.
9353c614b4Srillig  *
9453c614b4Srillig  * This means that at least in GCC mode, lint may decide to not warn about
9553c614b4Srillig  * these cases.
9653c614b4Srillig  */
9753c614b4Srillig void
shr_signed_ignoring_high_bits(int x)9853c614b4Srillig shr_signed_ignoring_high_bits(int x)
9953c614b4Srillig {
10053c614b4Srillig 
10153c614b4Srillig 	/*
10253c614b4Srillig 	 * All sane platforms should define that 'x >> 0 == x', even if x is
10353c614b4Srillig 	 * negative.
10453c614b4Srillig 	 */
10553c614b4Srillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
10653c614b4Srillig 	if (x >> 0 != 0)
10753c614b4Srillig 		return;
10853c614b4Srillig 
10953c614b4Srillig 	/*
11053c614b4Srillig 	 * If x is negative, x >> 1 is nonzero, no matter whether the shift
11153c614b4Srillig 	 * is arithmetic or logical.
11253c614b4Srillig 	 */
11353c614b4Srillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
11453c614b4Srillig 	if (x >> 1 != 0)
11553c614b4Srillig 		return;
11653c614b4Srillig 
11753c614b4Srillig 	/*
11853c614b4Srillig 	 * The highest bit may be 0 or 1, the others should be well-defined
11953c614b4Srillig 	 * on all sane platforms, making it irrelevant whether the actual
12053c614b4Srillig 	 * shift operation is arithmetic or logical.
12153c614b4Srillig 	 */
12253c614b4Srillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
12353c614b4Srillig 	if (((x >> 1) & 1) != 0)
12453c614b4Srillig 		return;
12553c614b4Srillig 
12653c614b4Srillig 	/*
12753c614b4Srillig 	 * The result of this expression is the same with arithmetic and
12853c614b4Srillig 	 * logical shifts since the filled bits are masked out.
12953c614b4Srillig 	 */
13053c614b4Srillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
13153c614b4Srillig 	if (((x >> 31) & 1) != 0)
13253c614b4Srillig 		return;
13353c614b4Srillig 
13453c614b4Srillig 	/*
13553c614b4Srillig 	 * In this case, arithmetic shift results in 2 while logical shift
13653c614b4Srillig 	 * results in 0.  This difference is what this warning is about.
13753c614b4Srillig 	 */
13853c614b4Srillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
13953c614b4Srillig 	if (((x >> 31) & 2) != 0)
14053c614b4Srillig 		return;
1416b8b6837Srillig 
1422f057630Srillig 	/*
1432f057630Srillig 	 * The result of '&' is guaranteed to be positive, so don't warn.
1442f057630Srillig 	 * Code like this typically occurs in hexdump functions.
1452f057630Srillig 	 */
1466b8b6837Srillig 	if ((x & 0xf0) >> 4 != 0)
1476b8b6837Srillig 		return;
14853c614b4Srillig }
149