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