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