Home | History | Annotate | Line # | Download | only in lint1
      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