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