xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_160.c (revision b2baa50111d645353fa30b4deab0f79d93650c8c)
1 /*	$NetBSD: msg_160.c,v 1.10 2023/03/28 14:44:35 rillig Exp $	*/
2 # 3 "msg_160.c"
3 
4 // Test for message: operator '==' found where '=' was expected [160]
5 
6 /* lint1-extra-flags: -h -X 351 */
7 
8 _Bool
both_equal_or_unequal(int a,int b,int c,int d)9 both_equal_or_unequal(int a, int b, int c, int d)
10 {
11 	/*
12 	 * Before tree.c 1.201 from 2021-01-31, lint warned about each of
13 	 * the '==' subexpressions even though there is nothing surprising
14 	 * about them.
15 	 */
16 	return (a == b) == (c == d);
17 }
18 
19 void
20 eval(_Bool);
21 
22 void
unparenthesized(int a,int b,int c,_Bool z)23 unparenthesized(int a, int b, int c, _Bool z)
24 {
25 	/*
26 	 * This one might be legitimate since the second '==' has _Bool
27 	 * on both sides.  Parenthesizing its left-hand operand doesn't
28 	 * hurt though.
29 	 */
30 	/* expect+1: warning: operator '==' found where '=' was expected [160] */
31 	eval(a == b == z);
32 
33 	/*
34 	 * Before tree.c 1.201 from 2021-01-31, lint warned about the
35 	 * parenthesized '==' subexpression even though there is nothing
36 	 * surprising about it.
37 	 */
38 	eval((a == b) == z);
39 
40 	/*
41 	 * This one is definitely wrong.  C, unlike Python, does not chain
42 	 * comparison operators in the way mathematicians are used to.
43 	 */
44 	/* expect+1: warning: operator '==' found where '=' was expected [160] */
45 	eval(a == b == c);
46 
47 	/* Parenthesizing one of the operands makes it obvious enough. */
48 	/*
49 	 * Before tree.c 1.201 from 2021-01-31, lint warned about the
50 	 * parenthesized '==' subexpression even though there is nothing
51 	 * surprising about it.
52 	 */
53 	eval((a == b) == c);
54 	/*
55 	 * Before tree.c 1.201 from 2021-01-31, lint warned about the
56 	 * parenthesized '==' subexpression even though there is nothing
57 	 * surprising about it.
58 	 */
59 	eval(a == (b == c));
60 }
61 
62 void
assignment_in_comma_expression(int len)63 assignment_in_comma_expression(int len)
64 {
65 
66 	/*
67 	 * No extra parentheses, just a comma operator.
68 	 *
69 	 * The usual interpretation is that the left-hand operand of the
70 	 * comma is a preparation, most often an assignment, and the
71 	 * right-hand operand of the comma is the actual condition.
72 	 */
73 	if (len = 3 * len + 1, len == 0)
74 		return;
75 
76 	/* Seen in bin/csh/dir.c 1.35 from 2020-08-09, line 223. */
77 	/*
78 	 * The extra parentheses are typically used to inform the compiler
79 	 * that an assignment using '=' is intentional, in particular it is
80 	 * not a typo of the comparison operator '=='.
81 	 *
82 	 * The comma operator in a condition is seldom used, which makes it
83 	 * reasonable to assume that the code author selected the operators
84 	 * on purpose.
85 	 *
86 	 * In this case the parentheses are redundant, it's quite possible
87 	 * that they come from a macro expansion though.
88 	 */
89 	if ((len = 3 * len + 1, len == 0))
90 		return;
91 
92 	/*
93 	 * If the comma expression is part of a larger expression, the
94 	 * parentheses are required to mark the operator precedence.  The
95 	 * parentheses must therefore not be interpreted as changing the
96 	 * intention from a condition to an assignment.
97 	 */
98 	if ((len = 3 * len + 1, len == 0) && len < 2)
99 		return;
100 }
101