xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_129.c (revision 438f9189683d2ab8d1d95c1c944de71d324a4ee1)
1*438f9189Srillig /*	$NetBSD: msg_129.c,v 1.10 2024/10/29 20:44:22 rillig Exp $	*/
2a0a15c14Srillig # 3 "msg_129.c"
3a0a15c14Srillig 
4a0a15c14Srillig // Test for message: expression has null effect [129]
5a0a15c14Srillig 
6b2baa501Srillig /* lint1-extra-flags: -h -X 351 */
7d1d4e41cSrillig 
8d1d4e41cSrillig typedef unsigned char uint8_t;
9d1d4e41cSrillig typedef unsigned int uint32_t;
10d1d4e41cSrillig 
11c96543cdSrillig _Bool side_effect(void);
12c96543cdSrillig 
13d1d4e41cSrillig /*
14c96543cdSrillig  * Before tree.c 1.198 from 2021-01-30, the nested comma operators were
15c96543cdSrillig  * wrongly reported as having no side effect.
16d1d4e41cSrillig  *
17c96543cdSrillig  * The bug was that has_side_effect did not properly examine the sub-nodes.
180ab64c29Srillig  * The ',' operator itself has m_has_side_effect == false since it depends
190ab64c29Srillig  * on its operands whether the ',' actually has side effects.  For nested ','
20c96543cdSrillig  * operators, the function did not evaluate the operands deeply but only did
21c96543cdSrillig  * a quick shallow test on the m_has_side_effect property.  Since that is
22c96543cdSrillig  * false, lint thought that the whole expression would have no side effect.
23d1d4e41cSrillig  */
24d1d4e41cSrillig void
25d1d4e41cSrillig uint8_buffer_write_uint32(uint8_t *c, uint32_t l)
26d1d4e41cSrillig {
27d1d4e41cSrillig 	(*(c++) = (uint8_t)(l & 0xff),
28d1d4e41cSrillig 	    *(c++) = (uint8_t)((l >> 8L) & 0xff),
29d1d4e41cSrillig 	    *(c++) = (uint8_t)((l >> 16L) & 0xff),
30c96543cdSrillig 	    *(c++) = (uint8_t)((l >> 24L) & 0xff));
31c96543cdSrillig }
32c96543cdSrillig 
33c96543cdSrillig void
34c96543cdSrillig operator_comma(void)
35c96543cdSrillig {
36c96543cdSrillig 	side_effect(), 0;		/* the 0 is redundant */
3765e5c21bSrillig 	/* expect+1: warning: expression has null effect [129] */
3865e5c21bSrillig 	0, side_effect();
39c96543cdSrillig 
40c96543cdSrillig 	if (side_effect(), 0)		/* the 0 controls the 'if' */
41c96543cdSrillig 		return;
4265e5c21bSrillig 	/* expect+1: warning: expression has null effect [129] */
4365e5c21bSrillig 	if (0, side_effect())
44c96543cdSrillig 		return;
45d1d4e41cSrillig }
460ab64c29Srillig 
470ab64c29Srillig void
480ab64c29Srillig legitimate_use_cases(int arg)
490ab64c29Srillig {
500ab64c29Srillig 	int local = 3;
510ab64c29Srillig 
520ab64c29Srillig 	/*
53039b0100Srillig 	 * This expression is commonly used to mark the parameter as
540ab64c29Srillig 	 * deliberately unused.
550ab64c29Srillig 	 */
560ab64c29Srillig 	(void)arg;
570ab64c29Srillig 
580ab64c29Srillig 	/*
590ab64c29Srillig 	 * This expression is commonly used to mark the local variable as
600ab64c29Srillig 	 * deliberately unused.  This situation occurs when the local
610ab64c29Srillig 	 * variable is only used in some but not all compile-time selectable
620ab64c29Srillig 	 * variants of the code, such as in debugging mode, and writing down
630ab64c29Srillig 	 * the exact conditions would complicate the code unnecessarily.
640ab64c29Srillig 	 */
650ab64c29Srillig 	(void)local;
660ab64c29Srillig 
67ace9402fSrillig 	/* This is a shorthand notation for a do-nothing command. */
680ab64c29Srillig 	(void)0;
690ab64c29Srillig 
700ab64c29Srillig 	/*
71b6c2b7a7Srillig 	 * At the point where lint checks for expressions having a null
72b6c2b7a7Srillig 	 * effect, constants have been folded, therefore the following
73b6c2b7a7Srillig 	 * expression is considered safe as well.  It does not appear in
74b6c2b7a7Srillig 	 * practice though.
75b6c2b7a7Srillig 	 */
76b6c2b7a7Srillig 	(void)(3 - 3);
77b6c2b7a7Srillig 
78b6c2b7a7Srillig 	/*
790ab64c29Srillig 	 * This variant of the do-nothing command is commonly used in
800ab64c29Srillig 	 * preprocessor macros since it works nicely with if-else and if-then
81ace9402fSrillig 	 * statements.  It is longer than the above variant, and it is not
82ace9402fSrillig 	 * embeddable into an expression.
830ab64c29Srillig 	 */
840ab64c29Srillig 	do {
850ab64c29Srillig 	} while (0);
860ab64c29Srillig 
870ab64c29Srillig 	/*
880ab64c29Srillig 	 * Only the expression '(void)0' is common, other expressions are
89b6c2b7a7Srillig 	 * unusual enough to warrant a warning.
900ab64c29Srillig 	 */
910ab64c29Srillig 	/* expect+1: warning: expression has null effect [129] */
920ab64c29Srillig 	(void)13;
93b6c2b7a7Srillig 
94b6c2b7a7Srillig 	/* Double casts are unusual enough to warrant a warning. */
95b6c2b7a7Srillig 	/* expect+1: warning: expression has null effect [129] */
96b6c2b7a7Srillig 	(void)(void)0;
970ab64c29Srillig }
98ace9402fSrillig 
99ace9402fSrillig int
100ace9402fSrillig return_statement_expression(int arg)
101ace9402fSrillig {
102ace9402fSrillig 	({
103ace9402fSrillig 		int local = arg;
104ace9402fSrillig 		local + 4;
105ace9402fSrillig 	/* expect+1: warning: expression has null effect [129] */
106ace9402fSrillig 	});
107ace9402fSrillig 
108ace9402fSrillig 	if (arg == 1)
109ace9402fSrillig 		return ({
110ace9402fSrillig 			int local = arg;
111*438f9189Srillig 			// Before cgram.y 1.513 from 2024-10-29, lint wrongly
112*438f9189Srillig 			// warned that this expression would have a null effect.
113ace9402fSrillig 			local;
114ace9402fSrillig 		});
115*438f9189Srillig 
116ace9402fSrillig 	if (arg == 2)
117ace9402fSrillig 		return ({
118ace9402fSrillig 			int local = arg;
119*438f9189Srillig 			// Before cgram.y 1.513 from 2024-10-29, lint wrongly
120*438f9189Srillig 			// warned that this expression would have a null effect.
121ace9402fSrillig 			local + 4;
122ace9402fSrillig 		});
123*438f9189Srillig 
124ace9402fSrillig 	return 0;
125ace9402fSrillig }
126