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