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