msg_129.c revision 1.11 1 /* $NetBSD: msg_129.c,v 1.11 2025/09/17 19:25:23 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_and(_Bool cond)
35 {
36 cond && side_effect();
37 // ... is an abbreviation for ...
38 if (cond)
39 side_effect();
40 // This pattern is much more common in shell or Perl than in C.
41
42 /* expect+1: warning: expression has null effect [129] */
43 side_effect() && cond;
44 }
45
46 void
47 operator_or(_Bool cond)
48 {
49 cond || side_effect();
50 // ... is an abbreviation for ...
51 if (!cond)
52 side_effect();
53 // This pattern is much more common in shell or Perl than in C.
54
55 /* expect+1: warning: expression has null effect [129] */
56 side_effect() || cond;
57 }
58
59 void
60 operator_quest_colon(void)
61 {
62 side_effect() ? side_effect() : side_effect();
63
64 /* expect+1: warning: expression has null effect [129] */
65 side_effect() ? side_effect() : 0;
66
67 /* expect+1: warning: expression has null effect [129] */
68 side_effect() ? 0 : side_effect();
69
70 /* expect+1: warning: expression has null effect [129] */
71 side_effect() ? 0 : 1;
72
73 0 ? side_effect() : side_effect();
74
75 /* expect+1: warning: expression has null effect [129] */
76 0 ? side_effect() : 0;
77
78 /* expect+1: warning: expression has null effect [129] */
79 0 ? 0 : side_effect();
80
81 /* expect+1: warning: expression has null effect [129] */
82 0 ? 0 : 1;
83
84 1 ? side_effect() : side_effect();
85
86 /* expect+1: warning: expression has null effect [129] */
87 1 ? side_effect() : 0;
88
89 /* expect+1: warning: expression has null effect [129] */
90 1 ? 0 : side_effect();
91
92 /* expect+1: warning: expression has null effect [129] */
93 1 ? 1 : 0;
94
95 0 ? (void)1 : (void)0;
96 }
97
98 void
99 operator_comma(void)
100 {
101 side_effect(), 0; /* the 0 is redundant */
102 /* expect+1: warning: expression has null effect [129] */
103 0, side_effect();
104
105 if (side_effect(), 0) /* the 0 controls the 'if' */
106 return;
107 /* expect+1: warning: expression has null effect [129] */
108 if (0, side_effect())
109 return;
110 }
111
112 void
113 legitimate_use_cases(int arg)
114 {
115 int local = 3;
116
117 /*
118 * This expression is commonly used to mark the parameter as
119 * deliberately unused.
120 */
121 (void)arg;
122
123 /*
124 * This expression is commonly used to mark the local variable as
125 * deliberately unused. This situation occurs when the local
126 * variable is only used in some but not all compile-time selectable
127 * variants of the code, such as in debugging mode, and writing down
128 * the exact conditions would complicate the code unnecessarily.
129 */
130 (void)local;
131
132 /* This is a shorthand notation for a do-nothing command. */
133 (void)0;
134
135 /*
136 * At the point where lint checks for expressions having a null
137 * effect, constants have been folded, therefore the following
138 * expression is considered safe as well. It does not appear in
139 * practice though.
140 */
141 (void)(3 - 3);
142
143 /*
144 * This variant of the do-nothing command is commonly used in
145 * preprocessor macros since it works nicely with if-else and if-then
146 * statements. It is longer than the above variant, and it is not
147 * embeddable into an expression.
148 */
149 do {
150 } while (0);
151
152 /*
153 * Only the expression '(void)0' is common, other expressions are
154 * unusual enough to warrant a warning.
155 */
156 /* expect+1: warning: expression has null effect [129] */
157 (void)13;
158
159 /* Double casts are unusual enough to warrant a warning. */
160 /* expect+1: warning: expression has null effect [129] */
161 (void)(void)0;
162 }
163
164 int
165 return_statement_expression(int arg)
166 {
167 ({
168 int local = arg;
169 local + 4;
170 /* expect+1: warning: expression has null effect [129] */
171 });
172
173 if (arg == 1)
174 return ({
175 int local = arg;
176 // Before cgram.y 1.513 from 2024-10-29, lint wrongly
177 // warned that this expression would have a null effect.
178 local;
179 });
180
181 if (arg == 2)
182 return ({
183 int local = arg;
184 // Before cgram.y 1.513 from 2024-10-29, lint wrongly
185 // warned that this expression would have a null effect.
186 local + 4;
187 });
188
189 return 0;
190 }
191