Home | History | Annotate | Line # | Download | only in lint1
msg_169.c revision 1.8.2.1
      1  1.8.2.1  perseant /*	$NetBSD: msg_169.c,v 1.8.2.1 2025/08/02 05:58:16 perseant Exp $	*/
      2      1.1    rillig # 3 "msg_169.c"
      3      1.1    rillig 
      4  1.8.2.1  perseant // 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
     37      1.6    rillig 	con = (a) + b << c;
     38  1.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
     39      1.6    rillig 	con = a + (b) << c;
     40  1.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
     45      1.6    rillig 	con = ch + b << c;
     46  1.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '<<' and '+' [169] */
     47      1.6    rillig 	con = a + ch << c;
     48  1.8.2.1  perseant 	/* 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.8.2.1  perseant confusing_logical(bool a, bool b, bool c, bool d)
     54      1.2    rillig {
     55  1.8.2.1  perseant 	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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 
     70  1.8.2.1  perseant 	// When both nested operands have confusing precedence, there's only
     71  1.8.2.1  perseant 	// a single warning, as that is enough to point to the issue.
     72  1.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
     73  1.8.2.1  perseant 	con = a && b || c && d;
     74  1.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
     75  1.8.2.1  perseant 	okl = (a && b) || c && d;
     76  1.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '||' and '&&' [169] */
     77  1.8.2.1  perseant 	okr = a && b || (c && d);
     78  1.8.2.1  perseant 	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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* expect+1: warning: possible precedence confusion between '|' and '&' [169] */
    158      1.6    rillig 	con = (unsigned)a | (unsigned)b & (unsigned)c;
    159  1.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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.8.2.1  perseant 	/* 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