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