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