xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_129.c (revision 438f9189683d2ab8d1d95c1c944de71d324a4ee1)
1 /*	$NetBSD: msg_129.c,v 1.10 2024/10/29 20:44:22 rillig Exp $	*/
2 # 3 "msg_129.c"
3 
4 // Test for message: expression has null effect [129]
5 
6 /* lint1-extra-flags: -h -X 351 */
7 
8 typedef unsigned char uint8_t;
9 typedef unsigned int uint32_t;
10 
11 _Bool side_effect(void);
12 
13 /*
14  * Before tree.c 1.198 from 2021-01-30, the nested comma operators were
15  * wrongly reported as having no side effect.
16  *
17  * The bug was that has_side_effect did not properly examine the sub-nodes.
18  * The ',' operator itself has m_has_side_effect == false since it depends
19  * on its operands whether the ',' actually has side effects.  For nested ','
20  * operators, the function did not evaluate the operands deeply but only did
21  * a quick shallow test on the m_has_side_effect property.  Since that is
22  * false, lint thought that the whole expression would have no side effect.
23  */
24 void
25 uint8_buffer_write_uint32(uint8_t *c, uint32_t l)
26 {
27 	(*(c++) = (uint8_t)(l & 0xff),
28 	    *(c++) = (uint8_t)((l >> 8L) & 0xff),
29 	    *(c++) = (uint8_t)((l >> 16L) & 0xff),
30 	    *(c++) = (uint8_t)((l >> 24L) & 0xff));
31 }
32 
33 void
34 operator_comma(void)
35 {
36 	side_effect(), 0;		/* the 0 is redundant */
37 	/* expect+1: warning: expression has null effect [129] */
38 	0, side_effect();
39 
40 	if (side_effect(), 0)		/* the 0 controls the 'if' */
41 		return;
42 	/* expect+1: warning: expression has null effect [129] */
43 	if (0, side_effect())
44 		return;
45 }
46 
47 void
48 legitimate_use_cases(int arg)
49 {
50 	int local = 3;
51 
52 	/*
53 	 * This expression is commonly used to mark the parameter as
54 	 * deliberately unused.
55 	 */
56 	(void)arg;
57 
58 	/*
59 	 * This expression is commonly used to mark the local variable as
60 	 * deliberately unused.  This situation occurs when the local
61 	 * variable is only used in some but not all compile-time selectable
62 	 * variants of the code, such as in debugging mode, and writing down
63 	 * the exact conditions would complicate the code unnecessarily.
64 	 */
65 	(void)local;
66 
67 	/* This is a shorthand notation for a do-nothing command. */
68 	(void)0;
69 
70 	/*
71 	 * At the point where lint checks for expressions having a null
72 	 * effect, constants have been folded, therefore the following
73 	 * expression is considered safe as well.  It does not appear in
74 	 * practice though.
75 	 */
76 	(void)(3 - 3);
77 
78 	/*
79 	 * This variant of the do-nothing command is commonly used in
80 	 * preprocessor macros since it works nicely with if-else and if-then
81 	 * statements.  It is longer than the above variant, and it is not
82 	 * embeddable into an expression.
83 	 */
84 	do {
85 	} while (0);
86 
87 	/*
88 	 * Only the expression '(void)0' is common, other expressions are
89 	 * unusual enough to warrant a warning.
90 	 */
91 	/* expect+1: warning: expression has null effect [129] */
92 	(void)13;
93 
94 	/* Double casts are unusual enough to warrant a warning. */
95 	/* expect+1: warning: expression has null effect [129] */
96 	(void)(void)0;
97 }
98 
99 int
100 return_statement_expression(int arg)
101 {
102 	({
103 		int local = arg;
104 		local + 4;
105 	/* expect+1: warning: expression has null effect [129] */
106 	});
107 
108 	if (arg == 1)
109 		return ({
110 			int local = arg;
111 			// Before cgram.y 1.513 from 2024-10-29, lint wrongly
112 			// warned that this expression would have a null effect.
113 			local;
114 		});
115 
116 	if (arg == 2)
117 		return ({
118 			int local = arg;
119 			// Before cgram.y 1.513 from 2024-10-29, lint wrongly
120 			// warned that this expression would have a null effect.
121 			local + 4;
122 		});
123 
124 	return 0;
125 }
126