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