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