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