msg_169.c revision 1.8 1 /* $NetBSD: msg_169.c,v 1.8 2023/07/07 06:03:31 rillig Exp $ */
2 # 3 "msg_169.c"
3
4 // Test for message: precedence confusion possible: parenthesize! [169]
5
6 /* lint1-flags: -g -h -S -w -X 191,351 */
7
8 typedef _Bool bool;
9
10 void
11 confusing_shift_arith(unsigned a, unsigned b, unsigned c, unsigned char ch)
12 {
13 unsigned con, okl, okr;
14
15 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
16 con = a + b << c;
17 okl = (a + b) << c;
18 okr = a + (b << c);
19
20 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
21 con = a << b + c;
22 okl = (a << b) + c;
23 okr = a << (b + c);
24
25 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
26 con = a - b >> c;
27 okl = (a - b) >> c;
28 okr = a - (b >> c);
29
30 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
31 con = a >> b - c;
32 okl = (a >> b) - c;
33 okr = a >> (b - c);
34
35 // Parenthesizing the inner operands has no effect on the warning.
36 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
37 con = (a) + b << c;
38 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
39 con = a + (b) << c;
40 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
41 con = a + b << (c);
42
43 // The usual arithmetic promotions have no effect on the warning.
44 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
45 con = ch + b << c;
46 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
47 con = a + ch << c;
48 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
49 con = a + b << ch;
50 }
51
52 void
53 confusing_logical(bool a, bool b, bool c)
54 {
55 bool con, okl, okr, eql;
56
57 eql = a && b && c;
58 eql = a || b || c;
59
60 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
61 con = a && b || c;
62 okl = (a && b) || c;
63 okr = a && (b || c);
64
65 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
66 con = a || b && c;
67 okl = (a || b) && c;
68 okr = a || (b && c);
69 }
70
71 void
72 confusing_bitwise(unsigned a, unsigned b, unsigned c)
73 {
74 bool con, okl, okr, eql;
75
76 eql = a & b & c;
77 eql = a | b | c;
78 eql = a ^ b ^ c;
79
80 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
81 con = a | b ^ c;
82 okl = (a | b) ^ c;
83 okr = a | (b ^ c);
84
85 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
86 con = a | b & c;
87 okl = (a | b) & c;
88 okr = a | (b & c);
89
90 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
91 con = a ^ b | c;
92 okl = (a ^ b) | c;
93 okr = a ^ (b | c);
94
95 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
96 con = a ^ b & c;
97 okl = (a ^ b) & c;
98 okr = a ^ (b & c);
99
100 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
101 con = a & b | c;
102 okl = (a & b) ^ c;
103 okr = a & (b ^ c);
104
105 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
106 con = a & b ^ c;
107 okl = (a & b) ^ c;
108 okr = a & (b ^ c);
109
110 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
111 con = a & b + c;
112 okl = (a & b) + c;
113 okr = a & (b + c);
114
115 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
116 con = a - b | c;
117 okl = (a - b) | c;
118 okr = a - (b | c);
119
120 // This looks like a binomial formula but isn't.
121 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
122 con = a ^ 2 - 2 * a * b + b ^ 2;
123
124 // This isn't a binomial formula either since '^' means xor.
125 con = (a ^ 2) - 2 * a * b + (b ^ 2);
126 }
127
128 void
129 constant_expressions(void)
130 {
131 unsigned con;
132
133 // The check for confusing precedence happens after constant folding.
134 // Therefore the following lines do not generate warnings.
135 con = 1 & 2 | 3;
136 con = 4 << 5 + 6;
137 con = 7 ^ 8 & 9;
138 }
139
140 void
141 cast_expressions(char a, char b, char c)
142 {
143 unsigned con;
144
145 // Adding casts to the leaf nodes doesn't change anything about the
146 // confusing precedence.
147 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
148 con = (unsigned)a | (unsigned)b & (unsigned)c;
149 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
150 con = (unsigned)a & (unsigned)b | (unsigned)c;
151
152 // Adding a cast around the whole calculation doesn't change the
153 // precedence as well.
154 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
155 con = (unsigned)(a | b & c);
156
157 // Adding a cast around an intermediate result groups the operands
158 // of the main node, which prevents any confusion about precedence.
159 con = (unsigned)a | (unsigned)(b & c);
160 con = a | (unsigned)(b & c);
161 con = (unsigned)(a | b) & (unsigned)c;
162 con = (unsigned)(a | b) & c;
163 }
164
165 void
166 expected_precedence(int a, int b, int c)
167 {
168 int ok;
169
170 ok = a + b * c;
171 }
172
173 void
174 implicit_conversion_to_long(long la, int a)
175 {
176 int ok;
177
178 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
179 ok = a & a | la;
180
181 /*
182 * Before tree.c 1.132 from 2021-01-04, there was a typo in
183 * check_precedence_confusion that prevented the right-hand operand
184 * from being flagged as possibly confusing if there was an implicit
185 * conversion or an explicit cast between the main operator ('|') and
186 * the nested operator ('&').
187 */
188 /* expect+1: warning: precedence confusion possible: parenthesize! [169] */
189 ok = la | a & a;
190
191 ok = (a & a) | la; /* always ok */
192 ok = la | (a & a); /* always ok */
193
194 /*
195 * Before tree.c 1.132, this expression didn't generate a warning
196 * because the right-hand operand was CVT, and there is no confusing
197 * precedence between BITOR and CVT.
198 *
199 * Since tree.c 1.132, this expression doesn't generate a warning
200 * because the right-hand operand is parenthesized. There is no way
201 * to have the right operand casted and at the same time not
202 * parenthesized since the cast operator has higher precedence.
203 *
204 * In summary, there is no visible change, but the implementation is
205 * now works as intended.
206 */
207 ok = la | (int)(a & a); /* always ok */
208 }
209