xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_169.c (revision 608e1834dab6bb17f9c62456f75f25c8b67e3c63)
1*608e1834Srillig /*	$NetBSD: msg_169.c,v 1.10 2024/12/15 06:04:17 rillig Exp $	*/
2a0a15c14Srillig # 3 "msg_169.c"
3a0a15c14Srillig 
4976db3dfSrillig // Test for message: possible precedence confusion between '%s' and '%s' [169]
5a0a15c14Srillig 
606b80932Srillig /* lint1-flags: -g -h -S -w -X 191,351 */
7d2a5bcafSrillig 
8d2a5bcafSrillig typedef _Bool bool;
9d2a5bcafSrillig 
10d2a5bcafSrillig void
11d2a5bcafSrillig confusing_shift_arith(unsigned a, unsigned b, unsigned c, unsigned char ch)
12d2a5bcafSrillig {
13d2a5bcafSrillig 	unsigned con, okl, okr;
14d2a5bcafSrillig 
15976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
1665e5c21bSrillig 	con = a + b << c;
17d2a5bcafSrillig 	okl = (a + b) << c;
18d2a5bcafSrillig 	okr = a + (b << c);
19d2a5bcafSrillig 
20976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
2165e5c21bSrillig 	con = a << b + c;
22d2a5bcafSrillig 	okl = (a << b) + c;
23d2a5bcafSrillig 	okr = a << (b + c);
24d2a5bcafSrillig 
25976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '>>' and '-' [169] */
2665e5c21bSrillig 	con = a - b >> c;
27d2a5bcafSrillig 	okl = (a - b) >> c;
28d2a5bcafSrillig 	okr = a - (b >> c);
29d2a5bcafSrillig 
30976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '>>' and '-' [169] */
3165e5c21bSrillig 	con = a >> b - c;
32d2a5bcafSrillig 	okl = (a >> b) - c;
33d2a5bcafSrillig 	okr = a >> (b - c);
34d2a5bcafSrillig 
35d2a5bcafSrillig 	// Parenthesizing the inner operands has no effect on the warning.
36976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
3765e5c21bSrillig 	con = (a) + b << c;
38976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
3965e5c21bSrillig 	con = a + (b) << c;
40976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
4165e5c21bSrillig 	con = a + b << (c);
42d2a5bcafSrillig 
43d2a5bcafSrillig 	// The usual arithmetic promotions have no effect on the warning.
44976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
4565e5c21bSrillig 	con = ch + b << c;
46976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
4765e5c21bSrillig 	con = a + ch << c;
48976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
4965e5c21bSrillig 	con = a + b << ch;
50d2a5bcafSrillig }
51d2a5bcafSrillig 
52d2a5bcafSrillig void
53*608e1834Srillig confusing_logical(bool a, bool b, bool c, bool d)
54d2a5bcafSrillig {
55*608e1834Srillig 	bool con, okl, okr, okb, eql;
56d2a5bcafSrillig 
57d2a5bcafSrillig 	eql = a && b && c;
58d2a5bcafSrillig 	eql = a || b || c;
59d2a5bcafSrillig 
60976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
6165e5c21bSrillig 	con = a && b || c;
62d2a5bcafSrillig 	okl = (a && b) || c;
63d2a5bcafSrillig 	okr = a && (b || c);
64d2a5bcafSrillig 
65976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
6665e5c21bSrillig 	con = a || b && c;
67d2a5bcafSrillig 	okl = (a || b) && c;
68d2a5bcafSrillig 	okr = a || (b && c);
69*608e1834Srillig 
70*608e1834Srillig 	// When both nested operands have confusing precedence, there's only
71*608e1834Srillig 	// a single warning, as that is enough to point to the issue.
72*608e1834Srillig 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
73*608e1834Srillig 	con = a && b || c && d;
74*608e1834Srillig 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
75*608e1834Srillig 	okl = (a && b) || c && d;
76*608e1834Srillig 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
77*608e1834Srillig 	okr = a && b || (c && d);
78*608e1834Srillig 	okb = (a && b) || (c && d);
79d2a5bcafSrillig }
80d2a5bcafSrillig 
81d2a5bcafSrillig void
82d2a5bcafSrillig confusing_bitwise(unsigned a, unsigned b, unsigned c)
83d2a5bcafSrillig {
84d2a5bcafSrillig 	bool con, okl, okr, eql;
85d2a5bcafSrillig 
86d2a5bcafSrillig 	eql = a & b & c;
87d2a5bcafSrillig 	eql = a | b | c;
88d2a5bcafSrillig 	eql = a ^ b ^ c;
89d2a5bcafSrillig 
90976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '^' [169] */
9165e5c21bSrillig 	con = a | b ^ c;
92d2a5bcafSrillig 	okl = (a | b) ^ c;
93d2a5bcafSrillig 	okr = a | (b ^ c);
94d2a5bcafSrillig 
95976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
9665e5c21bSrillig 	con = a | b & c;
97d2a5bcafSrillig 	okl = (a | b) & c;
98d2a5bcafSrillig 	okr = a | (b & c);
99d2a5bcafSrillig 
100976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '^' [169] */
10165e5c21bSrillig 	con = a ^ b | c;
102d2a5bcafSrillig 	okl = (a ^ b) | c;
103d2a5bcafSrillig 	okr = a ^ (b | c);
104d2a5bcafSrillig 
105976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '^' and '&' [169] */
10665e5c21bSrillig 	con = a ^ b & c;
107d2a5bcafSrillig 	okl = (a ^ b) & c;
108d2a5bcafSrillig 	okr = a ^ (b & c);
109d2a5bcafSrillig 
110976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
11165e5c21bSrillig 	con = a & b | c;
112d2a5bcafSrillig 	okl = (a & b) ^ c;
113d2a5bcafSrillig 	okr = a & (b ^ c);
114d2a5bcafSrillig 
115976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '^' and '&' [169] */
11665e5c21bSrillig 	con = a & b ^ c;
117d2a5bcafSrillig 	okl = (a & b) ^ c;
118d2a5bcafSrillig 	okr = a & (b ^ c);
119d2a5bcafSrillig 
120976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '&' and '+' [169] */
12165e5c21bSrillig 	con = a & b + c;
122d2a5bcafSrillig 	okl = (a & b) + c;
123d2a5bcafSrillig 	okr = a & (b + c);
124d2a5bcafSrillig 
125976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '-' [169] */
12665e5c21bSrillig 	con = a - b | c;
127d2a5bcafSrillig 	okl = (a - b) | c;
128d2a5bcafSrillig 	okr = a - (b | c);
129d2a5bcafSrillig 
130d2a5bcafSrillig 	// This looks like a binomial formula but isn't.
131976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '^' and '+' [169] */
13265e5c21bSrillig 	con = a ^ 2 - 2 * a * b + b ^ 2;
133d2a5bcafSrillig 
134d2a5bcafSrillig 	// This isn't a binomial formula either since '^' means xor.
135d2a5bcafSrillig 	con = (a ^ 2) - 2 * a * b + (b ^ 2);
136d2a5bcafSrillig }
137d2a5bcafSrillig 
138d2a5bcafSrillig void
139d2a5bcafSrillig constant_expressions(void)
140d2a5bcafSrillig {
141d2a5bcafSrillig 	unsigned con;
142d2a5bcafSrillig 
143d2a5bcafSrillig 	// The check for confusing precedence happens after constant folding.
144d2a5bcafSrillig 	// Therefore the following lines do not generate warnings.
145d2a5bcafSrillig 	con = 1 & 2 | 3;
146d2a5bcafSrillig 	con = 4 << 5 + 6;
147d2a5bcafSrillig 	con = 7 ^ 8 & 9;
148d2a5bcafSrillig }
149d2a5bcafSrillig 
150d2a5bcafSrillig void
151d2a5bcafSrillig cast_expressions(char a, char b, char c)
152d2a5bcafSrillig {
153d2a5bcafSrillig 	unsigned con;
154d2a5bcafSrillig 
155d2a5bcafSrillig 	// Adding casts to the leaf nodes doesn't change anything about the
156d2a5bcafSrillig 	// confusing precedence.
157976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
15865e5c21bSrillig 	con = (unsigned)a | (unsigned)b & (unsigned)c;
159976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
16065e5c21bSrillig 	con = (unsigned)a & (unsigned)b | (unsigned)c;
161d2a5bcafSrillig 
162d2a5bcafSrillig 	// Adding a cast around the whole calculation doesn't change the
163d2a5bcafSrillig 	// precedence as well.
164976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
16565e5c21bSrillig 	con = (unsigned)(a | b & c);
166d2a5bcafSrillig 
167d2a5bcafSrillig 	// Adding a cast around an intermediate result groups the operands
168d2a5bcafSrillig 	// of the main node, which prevents any confusion about precedence.
169d2a5bcafSrillig 	con = (unsigned)a | (unsigned)(b & c);
170d2a5bcafSrillig 	con = a | (unsigned)(b & c);
171d2a5bcafSrillig 	con = (unsigned)(a | b) & (unsigned)c;
172d2a5bcafSrillig 	con = (unsigned)(a | b) & c;
173d2a5bcafSrillig }
174d2a5bcafSrillig 
175d2a5bcafSrillig void
176d2a5bcafSrillig expected_precedence(int a, int b, int c)
177d2a5bcafSrillig {
178d2a5bcafSrillig 	int ok;
179d2a5bcafSrillig 
180d2a5bcafSrillig 	ok = a + b * c;
181d2a5bcafSrillig }
182d2a5bcafSrillig 
1836c2a2c14Srillig void
1846c2a2c14Srillig implicit_conversion_to_long(long la, int a)
1856c2a2c14Srillig {
1866c2a2c14Srillig 	int ok;
1876c2a2c14Srillig 
188976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
18965e5c21bSrillig 	ok = a & a | la;
190e9aa9302Srillig 
191e9aa9302Srillig 	/*
192e9aa9302Srillig 	 * Before tree.c 1.132 from 2021-01-04, there was a typo in
193e9aa9302Srillig 	 * check_precedence_confusion that prevented the right-hand operand
194e9aa9302Srillig 	 * from being flagged as possibly confusing if there was an implicit
195e9aa9302Srillig 	 * conversion or an explicit cast between the main operator ('|') and
196e9aa9302Srillig 	 * the nested operator ('&').
197e9aa9302Srillig 	 */
198976db3dfSrillig 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
19965e5c21bSrillig 	ok = la | a & a;
2006c2a2c14Srillig 
2016c2a2c14Srillig 	ok = (a & a) | la;	/* always ok */
2026c2a2c14Srillig 	ok = la | (a & a);	/* always ok */
2036c2a2c14Srillig 
2046c2a2c14Srillig 	/*
2056c2a2c14Srillig 	 * Before tree.c 1.132, this expression didn't generate a warning
2066c2a2c14Srillig 	 * because the right-hand operand was CVT, and there is no confusing
2076c2a2c14Srillig 	 * precedence between BITOR and CVT.
2086c2a2c14Srillig 	 *
2096c2a2c14Srillig 	 * Since tree.c 1.132, this expression doesn't generate a warning
2106c2a2c14Srillig 	 * because the right-hand operand is parenthesized.  There is no way
2116c2a2c14Srillig 	 * to have the right operand casted and at the same time not
2126c2a2c14Srillig 	 * parenthesized since the cast operator has higher precedence.
2136c2a2c14Srillig 	 *
2146c2a2c14Srillig 	 * In summary, there is no visible change, but the implementation is
2156c2a2c14Srillig 	 * now works as intended.
2166c2a2c14Srillig 	 */
2176c2a2c14Srillig 	ok = la | (int)(a & a);	/* always ok */
2186c2a2c14Srillig }
219