/* $NetBSD: msg_129.c,v 1.11 2025/09/17 19:25:23 rillig Exp $ */ # 3 "msg_129.c" // Test for message: expression has null effect [129] /* lint1-extra-flags: -h -X 351 */ typedef unsigned char uint8_t; typedef unsigned int uint32_t; _Bool side_effect(void); /* * Before tree.c 1.198 from 2021-01-30, the nested comma operators were * wrongly reported as having no side effect. * * The bug was that has_side_effect did not properly examine the sub-nodes. * The ',' operator itself has m_has_side_effect == false since it depends * on its operands whether the ',' actually has side effects. For nested ',' * operators, the function did not evaluate the operands deeply but only did * a quick shallow test on the m_has_side_effect property. Since that is * false, lint thought that the whole expression would have no side effect. */ void uint8_buffer_write_uint32(uint8_t *c, uint32_t l) { (*(c++) = (uint8_t)(l & 0xff), *(c++) = (uint8_t)((l >> 8L) & 0xff), *(c++) = (uint8_t)((l >> 16L) & 0xff), *(c++) = (uint8_t)((l >> 24L) & 0xff)); } void operator_and(_Bool cond) { cond && side_effect(); // ... is an abbreviation for ... if (cond) side_effect(); // This pattern is much more common in shell or Perl than in C. /* expect+1: warning: expression has null effect [129] */ side_effect() && cond; } void operator_or(_Bool cond) { cond || side_effect(); // ... is an abbreviation for ... if (!cond) side_effect(); // This pattern is much more common in shell or Perl than in C. /* expect+1: warning: expression has null effect [129] */ side_effect() || cond; } void operator_quest_colon(void) { side_effect() ? side_effect() : side_effect(); /* expect+1: warning: expression has null effect [129] */ side_effect() ? side_effect() : 0; /* expect+1: warning: expression has null effect [129] */ side_effect() ? 0 : side_effect(); /* expect+1: warning: expression has null effect [129] */ side_effect() ? 0 : 1; 0 ? side_effect() : side_effect(); /* expect+1: warning: expression has null effect [129] */ 0 ? side_effect() : 0; /* expect+1: warning: expression has null effect [129] */ 0 ? 0 : side_effect(); /* expect+1: warning: expression has null effect [129] */ 0 ? 0 : 1; 1 ? side_effect() : side_effect(); /* expect+1: warning: expression has null effect [129] */ 1 ? side_effect() : 0; /* expect+1: warning: expression has null effect [129] */ 1 ? 0 : side_effect(); /* expect+1: warning: expression has null effect [129] */ 1 ? 1 : 0; 0 ? (void)1 : (void)0; } void operator_comma(void) { side_effect(), 0; /* the 0 is redundant */ /* expect+1: warning: expression has null effect [129] */ 0, side_effect(); if (side_effect(), 0) /* the 0 controls the 'if' */ return; /* expect+1: warning: expression has null effect [129] */ if (0, side_effect()) return; } void legitimate_use_cases(int arg) { int local = 3; /* * This expression is commonly used to mark the parameter as * deliberately unused. */ (void)arg; /* * This expression is commonly used to mark the local variable as * deliberately unused. This situation occurs when the local * variable is only used in some but not all compile-time selectable * variants of the code, such as in debugging mode, and writing down * the exact conditions would complicate the code unnecessarily. */ (void)local; /* This is a shorthand notation for a do-nothing command. */ (void)0; /* * At the point where lint checks for expressions having a null * effect, constants have been folded, therefore the following * expression is considered safe as well. It does not appear in * practice though. */ (void)(3 - 3); /* * This variant of the do-nothing command is commonly used in * preprocessor macros since it works nicely with if-else and if-then * statements. It is longer than the above variant, and it is not * embeddable into an expression. */ do { } while (0); /* * Only the expression '(void)0' is common, other expressions are * unusual enough to warrant a warning. */ /* expect+1: warning: expression has null effect [129] */ (void)13; /* Double casts are unusual enough to warrant a warning. */ /* expect+1: warning: expression has null effect [129] */ (void)(void)0; } int return_statement_expression(int arg) { ({ int local = arg; local + 4; /* expect+1: warning: expression has null effect [129] */ }); if (arg == 1) return ({ int local = arg; // Before cgram.y 1.513 from 2024-10-29, lint wrongly // warned that this expression would have a null effect. local; }); if (arg == 2) return ({ int local = arg; // Before cgram.y 1.513 from 2024-10-29, lint wrongly // warned that this expression would have a null effect. local + 4; }); return 0; }