Home | History | Annotate | Line # | Download | only in lint1
msg_117.c revision 1.14
      1  1.14  rillig /*	$NetBSD: msg_117.c,v 1.14 2023/07/07 19:45:22 rillig Exp $	*/
      2   1.1  rillig # 3 "msg_117.c"
      3   1.1  rillig 
      4   1.4  rillig // Test for message: bitwise '%s' on signed value possibly nonportable [117]
      5   1.1  rillig 
      6  1.14  rillig /* lint1-extra-flags: -p -X 351 */
      7   1.2  rillig 
      8   1.2  rillig int
      9   1.2  rillig shr(int a, int b)
     10   1.2  rillig {
     11  1.11  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
     12  1.11  rillig 	return a >> b;
     13   1.2  rillig }
     14   1.2  rillig 
     15   1.2  rillig int
     16   1.2  rillig shr_lhs_constant_positive(int a)
     17   1.2  rillig {
     18   1.2  rillig 	return 0x1234 >> a;
     19   1.2  rillig }
     20   1.2  rillig 
     21   1.2  rillig int
     22   1.2  rillig shr_lhs_constant_negative(int a)
     23   1.2  rillig {
     24  1.11  rillig 	/* expect+1: warning: bitwise '>>' on signed value nonportable [120] */
     25  1.11  rillig 	return -0x1234 >> a;
     26   1.2  rillig }
     27   1.2  rillig 
     28   1.2  rillig int
     29   1.2  rillig shr_rhs_constant_positive(int a)
     30   1.2  rillig {
     31  1.11  rillig 	/* expect+2: warning: bitwise '>>' on signed value possibly nonportable [117] */
     32  1.11  rillig 	/* expect+1: warning: shift amount 4660 is greater than bit-size 32 of 'int' [122] */
     33  1.11  rillig 	return a >> 0x1234;
     34   1.2  rillig }
     35   1.2  rillig 
     36   1.2  rillig int
     37   1.2  rillig shr_rhs_constant_negative(int a)
     38   1.2  rillig {
     39  1.11  rillig 	/* expect+2: warning: bitwise '>>' on signed value possibly nonportable [117] */
     40  1.11  rillig 	/* expect+1: warning: negative shift [121] */
     41  1.11  rillig 	return a >> -0x1234;
     42   1.2  rillig }
     43   1.6  rillig 
     44   1.6  rillig unsigned int
     45   1.6  rillig shr_unsigned_char(unsigned char uc)
     46   1.6  rillig {
     47   1.7  rillig 	/*
     48   1.7  rillig 	 * Even though 'uc' is promoted to 'int', it cannot be negative.
     49   1.7  rillig 	 * Before tree.c 1.335 from 2021-08-15, lint wrongly warned that
     50   1.7  rillig 	 * 'uc >> 4' might be a bitwise '>>' on signed value.
     51   1.7  rillig 	 */
     52   1.6  rillig 	return uc >> 4;
     53   1.6  rillig }
     54   1.8  rillig 
     55   1.8  rillig unsigned char
     56   1.9  rillig shr_unsigned_char_promoted_signed(unsigned char bit)
     57   1.8  rillig {
     58   1.8  rillig 	/*
     59   1.9  rillig 	 * The possible values for 'bit' range from 0 to 255.  Subtracting 1
     60   1.9  rillig 	 * from 0 results in a negative expression value.
     61   1.8  rillig 	 */
     62   1.8  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
     63   1.8  rillig 	return (unsigned char)((bit - 1) >> 5);
     64   1.8  rillig }
     65   1.9  rillig 
     66   1.9  rillig unsigned char
     67   1.9  rillig shr_unsigned_char_promoted_unsigned(unsigned char bit)
     68   1.9  rillig {
     69   1.9  rillig 	/*
     70   1.9  rillig 	 * To prevent the above warning, the intermediate expression must be
     71   1.9  rillig 	 * cast to 'unsigned char'.
     72   1.9  rillig 	 */
     73   1.9  rillig 	return (unsigned char)((unsigned char)(bit - 1) >> 5);
     74   1.9  rillig }
     75  1.10  rillig 
     76  1.10  rillig /*
     77  1.10  rillig  * C90 3.3.7, C99 6.5.7 and C11 6.5.7 all say the same: If E1 has a signed
     78  1.10  rillig  * type and a negative value, the resulting value is implementation-defined.
     79  1.10  rillig  *
     80  1.10  rillig  * These standards don't guarantee anything about the lower bits of the
     81  1.10  rillig  * resulting value, which are generally independent of whether the shift is
     82  1.10  rillig  * performed in signed arithmetics or in unsigned arithmetics.  The C99
     83  1.10  rillig  * rationale talks about signed shifts, but does not provide any guarantee
     84  1.10  rillig  * either.  It merely suggests that platforms are free to use unsigned shifts
     85  1.10  rillig  * even if the operand type is signed.
     86  1.10  rillig  *
     87  1.10  rillig  * K&R provides more guarantees by saying: Right shifting a signed quantity
     88  1.10  rillig  * will fill with sign bits ("arithmetic shift") on some machines such as the
     89  1.12  rillig  * PDP-11, and with 0-bits ("logical shift") on others.
     90  1.10  rillig  *
     91  1.10  rillig  * https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html says:
     92  1.10  rillig  * Signed '>>' acts on negative numbers by sign extension.
     93  1.10  rillig  *
     94  1.10  rillig  * This means that at least in GCC mode, lint may decide to not warn about
     95  1.10  rillig  * these cases.
     96  1.10  rillig  */
     97  1.10  rillig void
     98  1.10  rillig shr_signed_ignoring_high_bits(int x)
     99  1.10  rillig {
    100  1.10  rillig 
    101  1.10  rillig 	/*
    102  1.10  rillig 	 * All sane platforms should define that 'x >> 0 == x', even if x is
    103  1.10  rillig 	 * negative.
    104  1.10  rillig 	 */
    105  1.10  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
    106  1.10  rillig 	if (x >> 0 != 0)
    107  1.10  rillig 		return;
    108  1.10  rillig 
    109  1.10  rillig 	/*
    110  1.10  rillig 	 * If x is negative, x >> 1 is nonzero, no matter whether the shift
    111  1.10  rillig 	 * is arithmetic or logical.
    112  1.10  rillig 	 */
    113  1.10  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
    114  1.10  rillig 	if (x >> 1 != 0)
    115  1.10  rillig 		return;
    116  1.10  rillig 
    117  1.10  rillig 	/*
    118  1.10  rillig 	 * The highest bit may be 0 or 1, the others should be well-defined
    119  1.10  rillig 	 * on all sane platforms, making it irrelevant whether the actual
    120  1.10  rillig 	 * shift operation is arithmetic or logical.
    121  1.10  rillig 	 */
    122  1.10  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
    123  1.10  rillig 	if (((x >> 1) & 1) != 0)
    124  1.10  rillig 		return;
    125  1.10  rillig 
    126  1.10  rillig 	/*
    127  1.10  rillig 	 * The result of this expression is the same with arithmetic and
    128  1.10  rillig 	 * logical shifts since the filled bits are masked out.
    129  1.10  rillig 	 */
    130  1.10  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
    131  1.10  rillig 	if (((x >> 31) & 1) != 0)
    132  1.10  rillig 		return;
    133  1.10  rillig 
    134  1.10  rillig 	/*
    135  1.10  rillig 	 * In this case, arithmetic shift results in 2 while logical shift
    136  1.10  rillig 	 * results in 0.  This difference is what this warning is about.
    137  1.10  rillig 	 */
    138  1.10  rillig 	/* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */
    139  1.10  rillig 	if (((x >> 31) & 2) != 0)
    140  1.10  rillig 		return;
    141  1.12  rillig 
    142  1.13  rillig 	/*
    143  1.13  rillig 	 * The result of '&' is guaranteed to be positive, so don't warn.
    144  1.13  rillig 	 * Code like this typically occurs in hexdump functions.
    145  1.13  rillig 	 */
    146  1.12  rillig 	if ((x & 0xf0) >> 4 != 0)
    147  1.12  rillig 		return;
    148  1.10  rillig }
    149