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