msg_129.c revision 1.11 1 1.11 rillig /* $NetBSD: msg_129.c,v 1.11 2025/09/17 19:25:23 rillig Exp $ */
2 1.1 rillig # 3 "msg_129.c"
3 1.1 rillig
4 1.1 rillig // Test for message: expression has null effect [129]
5 1.1 rillig
6 1.7 rillig /* lint1-extra-flags: -h -X 351 */
7 1.2 rillig
8 1.2 rillig typedef unsigned char uint8_t;
9 1.2 rillig typedef unsigned int uint32_t;
10 1.2 rillig
11 1.3 rillig _Bool side_effect(void);
12 1.3 rillig
13 1.2 rillig /*
14 1.3 rillig * Before tree.c 1.198 from 2021-01-30, the nested comma operators were
15 1.3 rillig * wrongly reported as having no side effect.
16 1.2 rillig *
17 1.3 rillig * The bug was that has_side_effect did not properly examine the sub-nodes.
18 1.4 rillig * The ',' operator itself has m_has_side_effect == false since it depends
19 1.4 rillig * on its operands whether the ',' actually has side effects. For nested ','
20 1.3 rillig * operators, the function did not evaluate the operands deeply but only did
21 1.3 rillig * a quick shallow test on the m_has_side_effect property. Since that is
22 1.3 rillig * false, lint thought that the whole expression would have no side effect.
23 1.2 rillig */
24 1.2 rillig void
25 1.2 rillig uint8_buffer_write_uint32(uint8_t *c, uint32_t l)
26 1.2 rillig {
27 1.2 rillig (*(c++) = (uint8_t)(l & 0xff),
28 1.2 rillig *(c++) = (uint8_t)((l >> 8L) & 0xff),
29 1.2 rillig *(c++) = (uint8_t)((l >> 16L) & 0xff),
30 1.3 rillig *(c++) = (uint8_t)((l >> 24L) & 0xff));
31 1.3 rillig }
32 1.3 rillig
33 1.3 rillig void
34 1.11 rillig operator_and(_Bool cond)
35 1.11 rillig {
36 1.11 rillig cond && side_effect();
37 1.11 rillig // ... is an abbreviation for ...
38 1.11 rillig if (cond)
39 1.11 rillig side_effect();
40 1.11 rillig // This pattern is much more common in shell or Perl than in C.
41 1.11 rillig
42 1.11 rillig /* expect+1: warning: expression has null effect [129] */
43 1.11 rillig side_effect() && cond;
44 1.11 rillig }
45 1.11 rillig
46 1.11 rillig void
47 1.11 rillig operator_or(_Bool cond)
48 1.11 rillig {
49 1.11 rillig cond || side_effect();
50 1.11 rillig // ... is an abbreviation for ...
51 1.11 rillig if (!cond)
52 1.11 rillig side_effect();
53 1.11 rillig // This pattern is much more common in shell or Perl than in C.
54 1.11 rillig
55 1.11 rillig /* expect+1: warning: expression has null effect [129] */
56 1.11 rillig side_effect() || cond;
57 1.11 rillig }
58 1.11 rillig
59 1.11 rillig void
60 1.11 rillig operator_quest_colon(void)
61 1.11 rillig {
62 1.11 rillig side_effect() ? side_effect() : side_effect();
63 1.11 rillig
64 1.11 rillig /* expect+1: warning: expression has null effect [129] */
65 1.11 rillig side_effect() ? side_effect() : 0;
66 1.11 rillig
67 1.11 rillig /* expect+1: warning: expression has null effect [129] */
68 1.11 rillig side_effect() ? 0 : side_effect();
69 1.11 rillig
70 1.11 rillig /* expect+1: warning: expression has null effect [129] */
71 1.11 rillig side_effect() ? 0 : 1;
72 1.11 rillig
73 1.11 rillig 0 ? side_effect() : side_effect();
74 1.11 rillig
75 1.11 rillig /* expect+1: warning: expression has null effect [129] */
76 1.11 rillig 0 ? side_effect() : 0;
77 1.11 rillig
78 1.11 rillig /* expect+1: warning: expression has null effect [129] */
79 1.11 rillig 0 ? 0 : side_effect();
80 1.11 rillig
81 1.11 rillig /* expect+1: warning: expression has null effect [129] */
82 1.11 rillig 0 ? 0 : 1;
83 1.11 rillig
84 1.11 rillig 1 ? side_effect() : side_effect();
85 1.11 rillig
86 1.11 rillig /* expect+1: warning: expression has null effect [129] */
87 1.11 rillig 1 ? side_effect() : 0;
88 1.11 rillig
89 1.11 rillig /* expect+1: warning: expression has null effect [129] */
90 1.11 rillig 1 ? 0 : side_effect();
91 1.11 rillig
92 1.11 rillig /* expect+1: warning: expression has null effect [129] */
93 1.11 rillig 1 ? 1 : 0;
94 1.11 rillig
95 1.11 rillig 0 ? (void)1 : (void)0;
96 1.11 rillig }
97 1.11 rillig
98 1.11 rillig void
99 1.3 rillig operator_comma(void)
100 1.3 rillig {
101 1.3 rillig side_effect(), 0; /* the 0 is redundant */
102 1.6 rillig /* expect+1: warning: expression has null effect [129] */
103 1.6 rillig 0, side_effect();
104 1.3 rillig
105 1.3 rillig if (side_effect(), 0) /* the 0 controls the 'if' */
106 1.3 rillig return;
107 1.6 rillig /* expect+1: warning: expression has null effect [129] */
108 1.6 rillig if (0, side_effect())
109 1.3 rillig return;
110 1.2 rillig }
111 1.4 rillig
112 1.4 rillig void
113 1.4 rillig legitimate_use_cases(int arg)
114 1.4 rillig {
115 1.4 rillig int local = 3;
116 1.4 rillig
117 1.4 rillig /*
118 1.8 rillig * This expression is commonly used to mark the parameter as
119 1.4 rillig * deliberately unused.
120 1.4 rillig */
121 1.4 rillig (void)arg;
122 1.4 rillig
123 1.4 rillig /*
124 1.4 rillig * This expression is commonly used to mark the local variable as
125 1.4 rillig * deliberately unused. This situation occurs when the local
126 1.4 rillig * variable is only used in some but not all compile-time selectable
127 1.4 rillig * variants of the code, such as in debugging mode, and writing down
128 1.4 rillig * the exact conditions would complicate the code unnecessarily.
129 1.4 rillig */
130 1.4 rillig (void)local;
131 1.4 rillig
132 1.9 rillig /* This is a shorthand notation for a do-nothing command. */
133 1.4 rillig (void)0;
134 1.4 rillig
135 1.4 rillig /*
136 1.5 rillig * At the point where lint checks for expressions having a null
137 1.5 rillig * effect, constants have been folded, therefore the following
138 1.5 rillig * expression is considered safe as well. It does not appear in
139 1.5 rillig * practice though.
140 1.5 rillig */
141 1.5 rillig (void)(3 - 3);
142 1.5 rillig
143 1.5 rillig /*
144 1.4 rillig * This variant of the do-nothing command is commonly used in
145 1.4 rillig * preprocessor macros since it works nicely with if-else and if-then
146 1.9 rillig * statements. It is longer than the above variant, and it is not
147 1.9 rillig * embeddable into an expression.
148 1.4 rillig */
149 1.4 rillig do {
150 1.4 rillig } while (0);
151 1.4 rillig
152 1.4 rillig /*
153 1.4 rillig * Only the expression '(void)0' is common, other expressions are
154 1.5 rillig * unusual enough to warrant a warning.
155 1.4 rillig */
156 1.4 rillig /* expect+1: warning: expression has null effect [129] */
157 1.4 rillig (void)13;
158 1.5 rillig
159 1.5 rillig /* Double casts are unusual enough to warrant a warning. */
160 1.5 rillig /* expect+1: warning: expression has null effect [129] */
161 1.5 rillig (void)(void)0;
162 1.4 rillig }
163 1.9 rillig
164 1.9 rillig int
165 1.9 rillig return_statement_expression(int arg)
166 1.9 rillig {
167 1.9 rillig ({
168 1.9 rillig int local = arg;
169 1.9 rillig local + 4;
170 1.9 rillig /* expect+1: warning: expression has null effect [129] */
171 1.9 rillig });
172 1.9 rillig
173 1.9 rillig if (arg == 1)
174 1.9 rillig return ({
175 1.9 rillig int local = arg;
176 1.10 rillig // Before cgram.y 1.513 from 2024-10-29, lint wrongly
177 1.10 rillig // warned that this expression would have a null effect.
178 1.9 rillig local;
179 1.9 rillig });
180 1.10 rillig
181 1.9 rillig if (arg == 2)
182 1.9 rillig return ({
183 1.9 rillig int local = arg;
184 1.10 rillig // Before cgram.y 1.513 from 2024-10-29, lint wrongly
185 1.10 rillig // warned that this expression would have a null effect.
186 1.9 rillig local + 4;
187 1.9 rillig });
188 1.10 rillig
189 1.9 rillig return 0;
190 1.9 rillig }
191