xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_117.c (revision 122b5006ee1bd67145794b4cde92f4fe4781a5ec)
1 /*	$NetBSD: msg_117.c,v 1.10 2021/09/04 21:20:44 rillig Exp $	*/
2 # 3 "msg_117.c"
3 
4 // Test for message: bitwise '%s' on signed value possibly nonportable [117]
5 
6 /* lint1-extra-flags: -p */
7 
8 int
9 shr(int a, int b)
10 {
11 	return a >> b;			/* expect: 117 */
12 }
13 
14 int
15 shr_lhs_constant_positive(int a)
16 {
17 	return 0x1234 >> a;
18 }
19 
20 int
21 shr_lhs_constant_negative(int a)
22 {
23 	return -0x1234 >> a;		/* expect: 120 */
24 }
25 
26 int
27 shr_rhs_constant_positive(int a)
28 {
29 	return a >> 0x1234;		/* expect: 117 *//* expect: 122 */
30 }
31 
32 int
33 shr_rhs_constant_negative(int a)
34 {
35 	return a >> -0x1234;		/* expect: 117 *//* expect: 121 */
36 }
37 
38 unsigned int
39 shr_unsigned_char(unsigned char uc)
40 {
41 	/*
42 	 * Even though 'uc' is promoted to 'int', it cannot be negative.
43 	 * Before tree.c 1.335 from 2021-08-15, lint wrongly warned that
44 	 * 'uc >> 4' might be a bitwise '>>' on signed value.
45 	 */
46 	return uc >> 4;
47 }
48 
49 unsigned char
50 shr_unsigned_char_promoted_signed(unsigned char bit)
51 {
52 	/*
53 	 * The possible values for 'bit' range from 0 to 255.  Subtracting 1
54 	 * from 0 results in a negative expression value.
55 	 */
56 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
57 	return (unsigned char)((bit - 1) >> 5);
58 }
59 
60 unsigned char
61 shr_unsigned_char_promoted_unsigned(unsigned char bit)
62 {
63 	/*
64 	 * To prevent the above warning, the intermediate expression must be
65 	 * cast to 'unsigned char'.
66 	 */
67 	return (unsigned char)((unsigned char)(bit - 1) >> 5);
68 }
69 
70 /*
71  * C90 3.3.7, C99 6.5.7 and C11 6.5.7 all say the same: If E1 has a signed
72  * type and a negative value, the resulting value is implementation-defined.
73  *
74  * These standards don't guarantee anything about the lower bits of the
75  * resulting value, which are generally independent of whether the shift is
76  * performed in signed arithmetics or in unsigned arithmetics.  The C99
77  * rationale talks about signed shifts, but does not provide any guarantee
78  * either.  It merely suggests that platforms are free to use unsigned shifts
79  * even if the operand type is signed.
80  *
81  * K&R provides more guarantees by saying: Right shifting a signed quantity
82  * will fill with sign bits ("arithmetic shift") on some machines such as the
83  * PDP-Il, and with 0-bits ("logical shift") on others.
84  *
85  * https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html says:
86  * Signed '>>' acts on negative numbers by sign extension.
87  *
88  * This means that at least in GCC mode, lint may decide to not warn about
89  * these cases.
90  */
91 void
92 shr_signed_ignoring_high_bits(int x)
93 {
94 
95 	/*
96 	 * All sane platforms should define that 'x >> 0 == x', even if x is
97 	 * negative.
98 	 */
99 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
100 	if (x >> 0 != 0)
101 		return;
102 
103 	/*
104 	 * If x is negative, x >> 1 is nonzero, no matter whether the shift
105 	 * is arithmetic or logical.
106 	 */
107 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
108 	if (x >> 1 != 0)
109 		return;
110 
111 	/*
112 	 * The highest bit may be 0 or 1, the others should be well-defined
113 	 * on all sane platforms, making it irrelevant whether the actual
114 	 * shift operation is arithmetic or logical.
115 	 */
116 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
117 	if (((x >> 1) & 1) != 0)
118 		return;
119 
120 	/*
121 	 * The result of this expression is the same with arithmetic and
122 	 * logical shifts since the filled bits are masked out.
123 	 */
124 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
125 	if (((x >> 31) & 1) != 0)
126 		return;
127 
128 	/*
129 	 * In this case, arithmetic shift results in 2 while logical shift
130 	 * results in 0.  This difference is what this warning is about.
131 	 */
132 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
133 	if (((x >> 31) & 2) != 0)
134 		return;
135 }
136