msg_129.c revision 1.7 1 1.7 rillig /* $NetBSD: msg_129.c,v 1.7 2023/03/28 14:44:34 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.3 rillig operator_comma(void)
35 1.3 rillig {
36 1.3 rillig side_effect(), 0; /* the 0 is redundant */
37 1.6 rillig /* expect+1: warning: expression has null effect [129] */
38 1.6 rillig 0, side_effect();
39 1.3 rillig
40 1.3 rillig if (side_effect(), 0) /* the 0 controls the 'if' */
41 1.3 rillig return;
42 1.6 rillig /* expect+1: warning: expression has null effect [129] */
43 1.6 rillig if (0, side_effect())
44 1.3 rillig return;
45 1.2 rillig }
46 1.4 rillig
47 1.4 rillig void
48 1.4 rillig legitimate_use_cases(int arg)
49 1.4 rillig {
50 1.4 rillig int local = 3;
51 1.4 rillig
52 1.4 rillig /*
53 1.4 rillig * This expression is commonly used to mark the argument as
54 1.4 rillig * deliberately unused.
55 1.4 rillig */
56 1.4 rillig (void)arg;
57 1.4 rillig
58 1.4 rillig /*
59 1.4 rillig * This expression is commonly used to mark the local variable as
60 1.4 rillig * deliberately unused. This situation occurs when the local
61 1.4 rillig * variable is only used in some but not all compile-time selectable
62 1.4 rillig * variants of the code, such as in debugging mode, and writing down
63 1.4 rillig * the exact conditions would complicate the code unnecessarily.
64 1.4 rillig */
65 1.4 rillig (void)local;
66 1.4 rillig
67 1.4 rillig /* This is a short-hand notation for a do-nothing command. */
68 1.4 rillig (void)0;
69 1.4 rillig
70 1.4 rillig /*
71 1.5 rillig * At the point where lint checks for expressions having a null
72 1.5 rillig * effect, constants have been folded, therefore the following
73 1.5 rillig * expression is considered safe as well. It does not appear in
74 1.5 rillig * practice though.
75 1.5 rillig */
76 1.5 rillig (void)(3 - 3);
77 1.5 rillig
78 1.5 rillig /*
79 1.4 rillig * This variant of the do-nothing command is commonly used in
80 1.4 rillig * preprocessor macros since it works nicely with if-else and if-then
81 1.4 rillig * statements. It is longer than the above variant though.
82 1.4 rillig */
83 1.4 rillig do {
84 1.4 rillig } while (0);
85 1.4 rillig
86 1.4 rillig /*
87 1.4 rillig * Only the expression '(void)0' is common, other expressions are
88 1.5 rillig * unusual enough to warrant a warning.
89 1.4 rillig */
90 1.4 rillig /* expect+1: warning: expression has null effect [129] */
91 1.4 rillig (void)13;
92 1.5 rillig
93 1.5 rillig /* Double casts are unusual enough to warrant a warning. */
94 1.5 rillig /* expect+1: warning: expression has null effect [129] */
95 1.5 rillig (void)(void)0;
96 1.4 rillig }
97