Home | History | Annotate | Line # | Download | only in lint1
      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