1*438f9189Srillig /* $NetBSD: msg_129.c,v 1.10 2024/10/29 20:44:22 rillig Exp $ */ 2a0a15c14Srillig # 3 "msg_129.c" 3a0a15c14Srillig 4a0a15c14Srillig // Test for message: expression has null effect [129] 5a0a15c14Srillig 6b2baa501Srillig /* lint1-extra-flags: -h -X 351 */ 7d1d4e41cSrillig 8d1d4e41cSrillig typedef unsigned char uint8_t; 9d1d4e41cSrillig typedef unsigned int uint32_t; 10d1d4e41cSrillig 11c96543cdSrillig _Bool side_effect(void); 12c96543cdSrillig 13d1d4e41cSrillig /* 14c96543cdSrillig * Before tree.c 1.198 from 2021-01-30, the nested comma operators were 15c96543cdSrillig * wrongly reported as having no side effect. 16d1d4e41cSrillig * 17c96543cdSrillig * The bug was that has_side_effect did not properly examine the sub-nodes. 180ab64c29Srillig * The ',' operator itself has m_has_side_effect == false since it depends 190ab64c29Srillig * on its operands whether the ',' actually has side effects. For nested ',' 20c96543cdSrillig * operators, the function did not evaluate the operands deeply but only did 21c96543cdSrillig * a quick shallow test on the m_has_side_effect property. Since that is 22c96543cdSrillig * false, lint thought that the whole expression would have no side effect. 23d1d4e41cSrillig */ 24d1d4e41cSrillig void 25d1d4e41cSrillig uint8_buffer_write_uint32(uint8_t *c, uint32_t l) 26d1d4e41cSrillig { 27d1d4e41cSrillig (*(c++) = (uint8_t)(l & 0xff), 28d1d4e41cSrillig *(c++) = (uint8_t)((l >> 8L) & 0xff), 29d1d4e41cSrillig *(c++) = (uint8_t)((l >> 16L) & 0xff), 30c96543cdSrillig *(c++) = (uint8_t)((l >> 24L) & 0xff)); 31c96543cdSrillig } 32c96543cdSrillig 33c96543cdSrillig void 34c96543cdSrillig operator_comma(void) 35c96543cdSrillig { 36c96543cdSrillig side_effect(), 0; /* the 0 is redundant */ 3765e5c21bSrillig /* expect+1: warning: expression has null effect [129] */ 3865e5c21bSrillig 0, side_effect(); 39c96543cdSrillig 40c96543cdSrillig if (side_effect(), 0) /* the 0 controls the 'if' */ 41c96543cdSrillig return; 4265e5c21bSrillig /* expect+1: warning: expression has null effect [129] */ 4365e5c21bSrillig if (0, side_effect()) 44c96543cdSrillig return; 45d1d4e41cSrillig } 460ab64c29Srillig 470ab64c29Srillig void 480ab64c29Srillig legitimate_use_cases(int arg) 490ab64c29Srillig { 500ab64c29Srillig int local = 3; 510ab64c29Srillig 520ab64c29Srillig /* 53039b0100Srillig * This expression is commonly used to mark the parameter as 540ab64c29Srillig * deliberately unused. 550ab64c29Srillig */ 560ab64c29Srillig (void)arg; 570ab64c29Srillig 580ab64c29Srillig /* 590ab64c29Srillig * This expression is commonly used to mark the local variable as 600ab64c29Srillig * deliberately unused. This situation occurs when the local 610ab64c29Srillig * variable is only used in some but not all compile-time selectable 620ab64c29Srillig * variants of the code, such as in debugging mode, and writing down 630ab64c29Srillig * the exact conditions would complicate the code unnecessarily. 640ab64c29Srillig */ 650ab64c29Srillig (void)local; 660ab64c29Srillig 67ace9402fSrillig /* This is a shorthand notation for a do-nothing command. */ 680ab64c29Srillig (void)0; 690ab64c29Srillig 700ab64c29Srillig /* 71b6c2b7a7Srillig * At the point where lint checks for expressions having a null 72b6c2b7a7Srillig * effect, constants have been folded, therefore the following 73b6c2b7a7Srillig * expression is considered safe as well. It does not appear in 74b6c2b7a7Srillig * practice though. 75b6c2b7a7Srillig */ 76b6c2b7a7Srillig (void)(3 - 3); 77b6c2b7a7Srillig 78b6c2b7a7Srillig /* 790ab64c29Srillig * This variant of the do-nothing command is commonly used in 800ab64c29Srillig * preprocessor macros since it works nicely with if-else and if-then 81ace9402fSrillig * statements. It is longer than the above variant, and it is not 82ace9402fSrillig * embeddable into an expression. 830ab64c29Srillig */ 840ab64c29Srillig do { 850ab64c29Srillig } while (0); 860ab64c29Srillig 870ab64c29Srillig /* 880ab64c29Srillig * Only the expression '(void)0' is common, other expressions are 89b6c2b7a7Srillig * unusual enough to warrant a warning. 900ab64c29Srillig */ 910ab64c29Srillig /* expect+1: warning: expression has null effect [129] */ 920ab64c29Srillig (void)13; 93b6c2b7a7Srillig 94b6c2b7a7Srillig /* Double casts are unusual enough to warrant a warning. */ 95b6c2b7a7Srillig /* expect+1: warning: expression has null effect [129] */ 96b6c2b7a7Srillig (void)(void)0; 970ab64c29Srillig } 98ace9402fSrillig 99ace9402fSrillig int 100ace9402fSrillig return_statement_expression(int arg) 101ace9402fSrillig { 102ace9402fSrillig ({ 103ace9402fSrillig int local = arg; 104ace9402fSrillig local + 4; 105ace9402fSrillig /* expect+1: warning: expression has null effect [129] */ 106ace9402fSrillig }); 107ace9402fSrillig 108ace9402fSrillig if (arg == 1) 109ace9402fSrillig return ({ 110ace9402fSrillig int local = arg; 111*438f9189Srillig // Before cgram.y 1.513 from 2024-10-29, lint wrongly 112*438f9189Srillig // warned that this expression would have a null effect. 113ace9402fSrillig local; 114ace9402fSrillig }); 115*438f9189Srillig 116ace9402fSrillig if (arg == 2) 117ace9402fSrillig return ({ 118ace9402fSrillig int local = arg; 119*438f9189Srillig // Before cgram.y 1.513 from 2024-10-29, lint wrongly 120*438f9189Srillig // warned that this expression would have a null effect. 121ace9402fSrillig local + 4; 122ace9402fSrillig }); 123*438f9189Srillig 124ace9402fSrillig return 0; 125ace9402fSrillig } 126