forked from aniani/vim
patch 8.2.5004: right shift on negative number does not work as documented
Problem: Right shift on negative number does not work as documented. Solution: Use a uvarnumber_T type cast.
This commit is contained in:
parent
a061f34191
commit
338bf58eba
@ -1138,9 +1138,10 @@ expr6 >> expr6 bitwise right shift *expr->>*
|
||||
*E1282* *E1283*
|
||||
The "<<" and ">>" operators can be used to perform bitwise left or right shift
|
||||
of the left operand by the number of bits specified by the right operand. The
|
||||
operands must be positive numbers. The topmost bit (sign bit) is always
|
||||
cleared for ">>". If the right operand (shift amount) is more than the
|
||||
maximum number of bits in a number (|v:numbersize|) the result is zero.
|
||||
operands are used as positive numbers. When shifting right with ">>" the
|
||||
topmost bit (somtimes called the sign bit) is cleared. If the right operand
|
||||
(shift amount) is more than the maximum number of bits in a number
|
||||
(|v:numbersize|) the result is zero.
|
||||
|
||||
|
||||
expr6 and expr7 *expr6* *expr7* *E1036* *E1051*
|
||||
@ -1417,6 +1418,10 @@ number number constant *expr-number*
|
||||
Decimal, Hexadecimal (starting with 0x or 0X), Binary (starting with 0b or 0B)
|
||||
and Octal (starting with 0, 0o or 0O).
|
||||
|
||||
Assuming 64 bit numbers are used (see |v:numbersize|) an unsigned number is
|
||||
truncated to 0x7fffffffffffffff or 9223372036854775807. You can use -1 to get
|
||||
0xffffffffffffffff.
|
||||
|
||||
*floating-point-format*
|
||||
Floating point numbers can be written in two forms:
|
||||
|
||||
|
@ -2002,6 +2002,7 @@ vim_str2nr(
|
||||
}
|
||||
else
|
||||
{
|
||||
// prevent a larg unsigned number to become negative
|
||||
if (un > VARNUM_MAX)
|
||||
un = VARNUM_MAX;
|
||||
*nptr = (varnumber_T)un;
|
||||
|
@ -3091,12 +3091,8 @@ eval5(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
|
||||
rettv->vval.v_number =
|
||||
rettv->vval.v_number << var2.vval.v_number;
|
||||
else
|
||||
{
|
||||
rettv->vval.v_number =
|
||||
rettv->vval.v_number >> var2.vval.v_number;
|
||||
// clear the topmost sign bit
|
||||
rettv->vval.v_number &= ~((uvarnumber_T)1 << MAX_LSHIFT_BITS);
|
||||
}
|
||||
(uvarnumber_T)rettv->vval.v_number >> var2.vval.v_number;
|
||||
}
|
||||
|
||||
clear_tv(&var2);
|
||||
|
@ -958,6 +958,8 @@ func Test_bitwise_shift()
|
||||
call assert_equal(0, 0 >> 4)
|
||||
call assert_equal(0, 999999 >> 100)
|
||||
call assert_equal(0, 999999 << 100)
|
||||
call assert_equal(-1, -1 >> 0)
|
||||
call assert_equal(-1, -1 << 0)
|
||||
VAR a = 8
|
||||
VAR b = 2
|
||||
call assert_equal(2, a >> b)
|
||||
@ -976,6 +978,15 @@ func Test_bitwise_shift()
|
||||
for i in range(0, v:numbersize - 2)
|
||||
LET val = and(val, invert(1 << i))
|
||||
endfor
|
||||
#" -1 has all the bits set
|
||||
call assert_equal(-2, -1 << 1)
|
||||
call assert_equal(-4, -1 << 2)
|
||||
call assert_equal(-8, -1 << 3)
|
||||
if v:numbersize == 64
|
||||
call assert_equal(0x7fffffffffffffff, -1 >> 1)
|
||||
call assert_equal(0x3fffffffffffffff, -1 >> 2)
|
||||
call assert_equal(0x1fffffffffffffff, -1 >> 3)
|
||||
endif
|
||||
call assert_equal(0, val)
|
||||
#" multiple operators
|
||||
call assert_equal(16, 1 << 2 << 2)
|
||||
|
@ -734,6 +734,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
5004,
|
||||
/**/
|
||||
5003,
|
||||
/**/
|
||||
|
@ -4096,12 +4096,7 @@ exec_instructions(ectx_T *ectx)
|
||||
case EXPR_RSHIFT: if (arg2 > MAX_LSHIFT_BITS)
|
||||
res = 0;
|
||||
else
|
||||
{
|
||||
res = arg1 >> arg2;
|
||||
// clear the topmost sign bit
|
||||
res &= ~((uvarnumber_T)1
|
||||
<< MAX_LSHIFT_BITS);
|
||||
}
|
||||
res = (uvarnumber_T)arg1 >> arg2;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -2719,11 +2719,8 @@ compile_expr5(char_u **arg, cctx_T *cctx, ppconst_T *ppconst)
|
||||
else if (type == EXPR_LSHIFT)
|
||||
tv1->vval.v_number = tv1->vval.v_number << tv2->vval.v_number;
|
||||
else
|
||||
{
|
||||
tv1->vval.v_number = tv1->vval.v_number >> tv2->vval.v_number;
|
||||
// clear the topmost sign bit
|
||||
tv1->vval.v_number &= ~((uvarnumber_T)1 << MAX_LSHIFT_BITS);
|
||||
}
|
||||
tv1->vval.v_number =
|
||||
(uvarnumber_T)tv1->vval.v_number >> tv2->vval.v_number;
|
||||
clear_tv(tv2);
|
||||
--ppconst->pp_used;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user