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