mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: improve checking of a << b, when a and b are numbers (#12589)
This commit is contained in:
parent
fe37da31a8
commit
6d97b0a407
@ -99,7 +99,7 @@ But Vwill prevail for sure, V is the way!!
|
||||
txt1.create_texture()
|
||||
r := app.mouse_x % 255
|
||||
g := app.mouse_y % 255
|
||||
color := u32(r << 24) | u32(g << 16) | 0xFF
|
||||
color := u32(r) << 24 | u32(g) << 16 | 0xFF
|
||||
txt1.bmp.color = color
|
||||
txt1.draw_text_bmp(app.gg, app.mouse_x, app.mouse_y)
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ fn (nn int) str_l(max int) string {
|
||||
for n > 0 {
|
||||
n1 := int(n / 100)
|
||||
// calculate the digit_pairs start index
|
||||
d = ((int(n) - (n1 * 100)) << 1)
|
||||
d = int(u32(int(n) - (n1 * 100)) << 1)
|
||||
n = n1
|
||||
buf[index] = digit_pairs.str[d]
|
||||
index--
|
||||
@ -182,7 +182,7 @@ pub fn (nn i64) str() string {
|
||||
index--
|
||||
for n > 0 {
|
||||
n1 := n / i64(100)
|
||||
d = ((n - (n1 * i64(100))) << i64(1))
|
||||
d = (u32(n - (n1 * i64(100))) << i64(1))
|
||||
n = n1
|
||||
buf[index] = digit_pairs[d]
|
||||
index--
|
||||
|
@ -363,7 +363,7 @@ fn (mut m map) ensure_extra_metas(probe_count u32) {
|
||||
// not equivalent to the key of any other element already in the container.
|
||||
// If the key already exists, its value is changed to the value of the new element.
|
||||
fn (mut m map) set(key voidptr, value voidptr) {
|
||||
load_factor := f32(m.len << 1) / f32(m.even_index)
|
||||
load_factor := f32(u32(m.len) << 1) / f32(m.even_index)
|
||||
if load_factor > max_load_factor {
|
||||
m.expand()
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ pub fn get_str_intp_u64_format(fmt_type StrIntpType, in_width int, in_precision
|
||||
u64(0x7F) << 9
|
||||
}
|
||||
tail_zeros := if in_tail_zeros { u32(1) << 16 } else { u32(0) }
|
||||
base := u64((in_base & 0xf) << 27)
|
||||
base := u64(u32(in_base & 0xf) << 27)
|
||||
res := u64((u64(fmt_type) & 0x1F) | allign | upper_case | sign | precision | tail_zeros | (u64(width & 0x3FF) << 17) | base | (u64(in_pad_ch) << 31))
|
||||
return res
|
||||
}
|
||||
@ -147,7 +147,7 @@ pub fn get_str_intp_u32_format(fmt_type StrIntpType, in_width int, in_precision
|
||||
u32(0x7F) << 9
|
||||
}
|
||||
tail_zeros := if in_tail_zeros { u32(1) << 16 } else { u32(0) }
|
||||
base := u32((in_base & 0xf) << 27)
|
||||
base := u32(u32(in_base & 0xf) << 27)
|
||||
res := u32((u32(fmt_type) & 0x1F) | allign | upper_case | sign | precision | tail_zeros | (u32(width & 0x3FF) << 17) | base | (u32(in_pad_ch & 1) << 31))
|
||||
return res
|
||||
}
|
||||
|
@ -71,15 +71,15 @@ pub fn (_rune string) utf32_code() int {
|
||||
// TODO should be
|
||||
// res := int( rune[0] << rune.len)
|
||||
b = b << _rune.len
|
||||
mut res := int(b)
|
||||
mut res := u32(b)
|
||||
mut shift := 6 - _rune.len
|
||||
for i := 1; i < _rune.len; i++ {
|
||||
c := int(_rune[i])
|
||||
res = res << shift
|
||||
c := u32(_rune[i])
|
||||
res = u32(res) << shift
|
||||
res |= c & 63 // 0x3f
|
||||
shift = 6
|
||||
}
|
||||
return res
|
||||
return int(res)
|
||||
}
|
||||
|
||||
// Calculate length to read from the first byte
|
||||
|
@ -69,10 +69,10 @@ fn encrypt_block_generic(xk []u32, mut dst []byte, src []byte) {
|
||||
s3 = t3
|
||||
}
|
||||
// Last round uses s-box directly and XORs to produce output.
|
||||
s0 = s_box0[t0 >> 24] << 24 | s_box0[t1 >> 16 & 0xff] << 16 | u32(s_box0[t2 >> 8 & 0xff] << 8) | s_box0[t3 & u32(0xff)]
|
||||
s1 = s_box0[t1 >> 24] << 24 | s_box0[t2 >> 16 & 0xff] << 16 | u32(s_box0[t3 >> 8 & 0xff] << 8) | s_box0[t0 & u32(0xff)]
|
||||
s2 = s_box0[t2 >> 24] << 24 | s_box0[t3 >> 16 & 0xff] << 16 | u32(s_box0[t0 >> 8 & 0xff] << 8) | s_box0[t1 & u32(0xff)]
|
||||
s3 = s_box0[t3 >> 24] << 24 | s_box0[t0 >> 16 & 0xff] << 16 | u32(s_box0[t1 >> 8 & 0xff] << 8) | s_box0[t2 & u32(0xff)]
|
||||
s0 = u32(s_box0[t0 >> 24]) << 24 | u32(s_box0[t1 >> 16 & 0xff]) << 16 | u32(s_box0[t2 >> 8 & 0xff]) << 8 | u32(s_box0[t3 & u32(0xff)])
|
||||
s1 = u32(s_box0[t1 >> 24]) << 24 | u32(s_box0[t2 >> 16 & 0xff]) << 16 | u32(s_box0[t3 >> 8 & 0xff]) << 8 | u32(s_box0[t0 & u32(0xff)])
|
||||
s2 = u32(s_box0[t2 >> 24]) << 24 | u32(s_box0[t3 >> 16 & 0xff]) << 16 | u32(s_box0[t0 >> 8 & 0xff]) << 8 | u32(s_box0[t1 & u32(0xff)])
|
||||
s3 = u32(s_box0[t3 >> 24]) << 24 | u32(s_box0[t0 >> 16 & 0xff]) << 16 | u32(s_box0[t1 >> 8 & 0xff]) << 8 | u32(s_box0[t2 & u32(0xff)])
|
||||
s0 ^= xk[k + 0]
|
||||
s1 ^= xk[k + 1]
|
||||
s2 ^= xk[k + 2]
|
||||
@ -116,10 +116,10 @@ fn decrypt_block_generic(xk []u32, mut dst []byte, src []byte) {
|
||||
s3 = t3
|
||||
}
|
||||
// Last round uses s-box directly and XORs to produce output.
|
||||
s0 = u32(s_box1[t0 >> 24]) << 24 | u32(s_box1[t3 >> 16 & 0xff]) << 16 | u32(s_box1[t2 >> 8 & 0xff] << 8) | u32(s_box1[t1 & u32(0xff)])
|
||||
s1 = u32(s_box1[t1 >> 24]) << 24 | u32(s_box1[t0 >> 16 & 0xff]) << 16 | u32(s_box1[t3 >> 8 & 0xff] << 8) | u32(s_box1[t2 & u32(0xff)])
|
||||
s2 = u32(s_box1[t2 >> 24]) << 24 | u32(s_box1[t1 >> 16 & 0xff]) << 16 | u32(s_box1[t0 >> 8 & 0xff] << 8) | u32(s_box1[t3 & u32(0xff)])
|
||||
s3 = u32(s_box1[t3 >> 24]) << 24 | u32(s_box1[t2 >> 16 & 0xff]) << 16 | u32(s_box1[t1 >> 8 & 0xff] << 8) | u32(s_box1[t0 & u32(0xff)])
|
||||
s0 = u32(s_box1[t0 >> 24]) << 24 | u32(s_box1[t3 >> 16 & 0xff]) << 16 | u32(s_box1[t2 >> 8 & 0xff]) << 8 | u32(s_box1[t1 & u32(0xff)])
|
||||
s1 = u32(s_box1[t1 >> 24]) << 24 | u32(s_box1[t0 >> 16 & 0xff]) << 16 | u32(s_box1[t3 >> 8 & 0xff]) << 8 | u32(s_box1[t2 & u32(0xff)])
|
||||
s2 = u32(s_box1[t2 >> 24]) << 24 | u32(s_box1[t1 >> 16 & 0xff]) << 16 | u32(s_box1[t0 >> 8 & 0xff]) << 8 | u32(s_box1[t3 & u32(0xff)])
|
||||
s3 = u32(s_box1[t3 >> 24]) << 24 | u32(s_box1[t2 >> 16 & 0xff]) << 16 | u32(s_box1[t1 >> 8 & 0xff]) << 8 | u32(s_box1[t0 & u32(0xff)])
|
||||
s0 ^= xk[k + 0]
|
||||
s1 ^= xk[k + 1]
|
||||
s2 ^= xk[k + 2]
|
||||
@ -133,7 +133,7 @@ fn decrypt_block_generic(xk []u32, mut dst []byte, src []byte) {
|
||||
|
||||
// Apply s_box0 to each byte in w.
|
||||
fn subw(w u32) u32 {
|
||||
return u32(s_box0[w >> 24]) << 24 | u32(s_box0[w >> 16 & 0xff] << 16) | u32(s_box0[w >> 8 & 0xff] << 8) | u32(s_box0[w & u32(0xff)])
|
||||
return u32(s_box0[w >> 24]) << 24 | u32(s_box0[w >> 16 & 0xff]) << 16 | u32(s_box0[w >> 8 & 0xff]) << 8 | u32(s_box0[w & u32(0xff)])
|
||||
}
|
||||
|
||||
// Rotate
|
||||
|
@ -29,7 +29,7 @@ fn block_generic(mut dig Digest, p_ []byte) {
|
||||
// rounds below if needed for speed.
|
||||
for i in 0 .. 16 {
|
||||
j := i * 4
|
||||
w[i] = u32(p[j] << 24) | u32(p[j + 1] << 16) | u32(p[j + 2] << 8) | u32(p[j + 3])
|
||||
w[i] = u32(p[j]) << 24 | u32(p[j + 1]) << 16 | u32(p[j + 2]) << 8 | u32(p[j + 3])
|
||||
}
|
||||
mut a := h0
|
||||
mut b := h1
|
||||
|
@ -95,7 +95,7 @@ fn block_generic(mut dig Digest, p_ []byte) {
|
||||
// rounds below if needed for speed.
|
||||
for i in 0 .. 16 {
|
||||
j := i * 4
|
||||
w[i] = u32(p[j] << 24) | u32(p[j + 1] << 16) | u32(p[j + 2] << 8) | u32(p[j + 3])
|
||||
w[i] = u32(p[j]) << 24 | u32(p[j + 1]) << 16 | u32(p[j + 2]) << 8 | u32(p[j + 3])
|
||||
}
|
||||
for i := 16; i < 64; i++ {
|
||||
v1 := w[i - 2]
|
||||
|
@ -46,7 +46,7 @@ pub fn get_uchar(s string, index int) int {
|
||||
if ch_len > 1 && ch_len < 5 {
|
||||
mut lword := 0
|
||||
for i := 0; i < ch_len; i++ {
|
||||
lword = (lword << 8) | int(s[index + i])
|
||||
lword = int(u32(lword) << 8 | u32(s[index + i]))
|
||||
}
|
||||
|
||||
// 2 byte utf-8
|
||||
@ -416,7 +416,7 @@ fn up_low(s string, upper_flag bool) string {
|
||||
mut lword := 0
|
||||
|
||||
for i := 0; i < ch_len; i++ {
|
||||
lword = (lword << 8) | int(s[index + i])
|
||||
lword = int(u32(lword) << 8 | u32(s[index + i]))
|
||||
}
|
||||
|
||||
// println("#${index} ($lword)")
|
||||
|
@ -88,7 +88,7 @@ pub fn (x Mat4) get_e(elem_index int) f32 {
|
||||
// Get an element of the matrix using [0..3][0..3] indexes, two dimension
|
||||
pub fn (x Mat4) get_f(index_col int, index_row int) f32 {
|
||||
unsafe {
|
||||
return x.e[(index_row << 2) + index_col]
|
||||
return x.e[int(u32(index_row) << 2) + index_col]
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ pub fn (mut x Mat4) set_e(index int, value f32) {
|
||||
// Set an element of the matrix using [0..3][0..3] indexes, two dimension
|
||||
pub fn (mut x Mat4) set_f(index_col int, index_row int, value f32) {
|
||||
unsafe {
|
||||
x.e[(index_row << 2) + index_col] = value
|
||||
x.e[int(u32(index_row) << 2) + index_col] = value
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,21 +187,21 @@ pub fn (c Color) str() string {
|
||||
// see https://developer.apple.com/documentation/coreimage/ciformat
|
||||
[inline]
|
||||
pub fn (c Color) rgba8() int {
|
||||
return (int(c.r) << 24) + (int(c.g) << 16) + (int(c.b) << 8) + int(c.a)
|
||||
return int(u32(c.r) << 24 | u32(c.g) << 16 | u32(c.b) << 8 | u32(c.a))
|
||||
}
|
||||
|
||||
// bgra8 - convert a color value to an int in the BGRA8 order.
|
||||
// see https://developer.apple.com/documentation/coreimage/ciformat
|
||||
[inline]
|
||||
pub fn (c Color) bgra8() int {
|
||||
return (int(c.b) << 24) + (int(c.g) << 16) + (int(c.r) << 8) + int(c.a)
|
||||
return int(u32(c.b) << 24 | u32(c.g) << 16 | u32(c.r) << 8 | u32(c.a))
|
||||
}
|
||||
|
||||
// abgr8 - convert a color value to an int in the ABGR8 order.
|
||||
// see https://developer.apple.com/documentation/coreimage/ciformat
|
||||
[inline]
|
||||
pub fn (c Color) abgr8() int {
|
||||
return (int(c.a) << 24) + (int(c.b) << 16) + (int(c.g) << 8) + int(c.r)
|
||||
return int(u32(c.a) << 24 | u32(c.b) << 16 | u32(c.g) << 8 | u32(c.r))
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -11,9 +11,9 @@ const (
|
||||
mask = 0x7FF
|
||||
shift = 64 - 11 - 1
|
||||
bias = 1023
|
||||
normalize_smallest_mask = (u64(1) << 52)
|
||||
sign_mask = (u64(1) << 63)
|
||||
frac_mask = ((u64(1) << u64(shift)) - u64(1))
|
||||
normalize_smallest_mask = u64(u64(1) << 52)
|
||||
sign_mask = u64(0x8000000000000000) // (u64(1) << 63)
|
||||
frac_mask = u64((u64(1) << u64(shift)) - u64(1))
|
||||
)
|
||||
|
||||
// inf returns positive infinity if sign >= 0, negative infinity if sign < 0.
|
||||
|
@ -14,8 +14,8 @@ mut:
|
||||
text string
|
||||
}
|
||||
|
||||
fn (mut s ChunkScanner) read_chunk_size() int {
|
||||
mut n := 0
|
||||
fn (mut s ChunkScanner) read_chunk_size() u32 {
|
||||
mut n := u32(0)
|
||||
for {
|
||||
if s.pos >= s.text.len {
|
||||
break
|
||||
@ -25,7 +25,7 @@ fn (mut s ChunkScanner) read_chunk_size() int {
|
||||
break
|
||||
}
|
||||
n = n << 4
|
||||
n += int(unhex(c))
|
||||
n += u32(unhex(c))
|
||||
s.pos++
|
||||
}
|
||||
return n
|
||||
@ -46,9 +46,9 @@ fn (mut s ChunkScanner) skip_crlf() {
|
||||
s.pos += 2
|
||||
}
|
||||
|
||||
fn (mut s ChunkScanner) read_chunk(chunksize int) string {
|
||||
fn (mut s ChunkScanner) read_chunk(chunksize u32) string {
|
||||
startpos := s.pos
|
||||
s.pos += chunksize
|
||||
s.pos += int(chunksize)
|
||||
return s.text[startpos..s.pos]
|
||||
}
|
||||
|
||||
|
@ -252,8 +252,8 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
|
||||
if frame.payload_len == 126 && bytes_read == u64(websocket.extended_payload16_end_byte) {
|
||||
frame.header_len += 2
|
||||
frame.payload_len = 0
|
||||
frame.payload_len |= buffer[2] << 8
|
||||
frame.payload_len |= buffer[3]
|
||||
frame.payload_len |= int(u32(buffer[2]) << 8)
|
||||
frame.payload_len |= int(buffer[3])
|
||||
frame.frame_size = frame.header_len + frame.payload_len
|
||||
if !frame.has_mask {
|
||||
break
|
||||
|
@ -177,7 +177,7 @@ pub fn (mut ws Client) listen() ? {
|
||||
ws.close(1002, 'close payload cannot be 1 byte') ?
|
||||
return error('close payload cannot be 1 byte')
|
||||
}
|
||||
code := (int(msg.payload[0]) << 8) + int(msg.payload[1])
|
||||
code := u16(msg.payload[0]) << 8 | u16(msg.payload[1])
|
||||
if code in invalid_close_codes {
|
||||
ws.close(1002, 'invalid close code: $code') ?
|
||||
return error('invalid close code: $code')
|
||||
|
@ -767,6 +767,11 @@ pub mut:
|
||||
right_type Type
|
||||
auto_locked string
|
||||
or_block OrExpr
|
||||
//
|
||||
ct_left_value_evaled bool
|
||||
ct_left_value ComptTimeConstValue = empty_comptime_const_expr()
|
||||
ct_right_value_evaled bool
|
||||
ct_right_value ComptTimeConstValue = empty_comptime_const_expr()
|
||||
}
|
||||
|
||||
// ++, --
|
||||
|
@ -135,7 +135,7 @@ pub fn (t Type) atomic_typename() string {
|
||||
}
|
||||
|
||||
pub fn sharetype_from_flags(is_shared bool, is_atomic bool) ShareType {
|
||||
return ShareType((int(is_atomic) << 1) | int(is_shared))
|
||||
return ShareType(int(u32(is_atomic) << 1) | int(is_shared))
|
||||
}
|
||||
|
||||
pub fn (t Type) share() ShareType {
|
||||
@ -183,7 +183,7 @@ pub fn (t Type) set_nr_muls(nr_muls int) Type {
|
||||
if nr_muls < 0 || nr_muls > 255 {
|
||||
panic('set_nr_muls: nr_muls must be between 0 & 255')
|
||||
}
|
||||
return int(t) & 0xff00ffff | (nr_muls << 16)
|
||||
return int(t) & 0xff00ffff | int(u32(nr_muls) << 16)
|
||||
}
|
||||
|
||||
// increments nr_muls on `t` and return it
|
||||
@ -193,7 +193,7 @@ pub fn (t Type) ref() Type {
|
||||
if nr_muls == 255 {
|
||||
panic('ref: nr_muls is already at max of 255')
|
||||
}
|
||||
return int(t) & 0xff00ffff | ((nr_muls + 1) << 16)
|
||||
return int(t) & 0xff00ffff | int(u32(nr_muls + 1) << 16)
|
||||
}
|
||||
|
||||
// decrement nr_muls on `t` and return it
|
||||
@ -203,7 +203,7 @@ pub fn (t Type) deref() Type {
|
||||
if nr_muls == 0 {
|
||||
panic('deref: type `$t` is not a pointer')
|
||||
}
|
||||
return int(t) & 0xff00ffff | ((nr_muls - 1) << 16)
|
||||
return int(t) & 0xff00ffff | int(u32(nr_muls - 1) << 16)
|
||||
}
|
||||
|
||||
// set `flag` on `t` and return `t`
|
||||
@ -320,7 +320,7 @@ pub fn new_type_ptr(idx int, nr_muls int) Type {
|
||||
if nr_muls < 0 || nr_muls > 255 {
|
||||
panic('new_type_ptr: nr_muls must be between 0 & 255')
|
||||
}
|
||||
return (nr_muls << 16) | u16(idx)
|
||||
return (u32(nr_muls) << 16) | u16(idx)
|
||||
}
|
||||
|
||||
[inline]
|
||||
@ -438,14 +438,15 @@ pub const (
|
||||
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx,
|
||||
byte_type_idx, u8_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx,
|
||||
usize_type_idx, int_literal_type_idx, rune_type_idx]
|
||||
signed_integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx,
|
||||
isize_type_idx]
|
||||
unsigned_integer_type_idxs = [byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx,
|
||||
usize_type_idx]
|
||||
signed_integer_type_idxs = [char_type_idx, i8_type_idx, i16_type_idx, int_type_idx,
|
||||
i64_type_idx, isize_type_idx]
|
||||
unsigned_integer_type_idxs = [byte_type_idx, u8_type_idx, u16_type_idx, u32_type_idx,
|
||||
u64_type_idx, usize_type_idx]
|
||||
float_type_idxs = [f32_type_idx, f64_type_idx, float_literal_type_idx]
|
||||
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx,
|
||||
byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx, usize_type_idx,
|
||||
f32_type_idx, f64_type_idx, int_literal_type_idx, float_literal_type_idx, rune_type_idx]
|
||||
byte_type_idx, char_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx,
|
||||
usize_type_idx, f32_type_idx, f64_type_idx, int_literal_type_idx, float_literal_type_idx,
|
||||
rune_type_idx]
|
||||
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
||||
string_type_idxs = [string_type_idx]
|
||||
)
|
||||
|
@ -90,7 +90,7 @@ pub fn (mut b Builder) front_stages(v_files []string) ? {
|
||||
timers.show('PARSE')
|
||||
timers.show_if_exists('PARSE stmt')
|
||||
if b.pref.only_check_syntax {
|
||||
return error('stop_after_parser')
|
||||
return error_with_code('stop_after_parser', 9999)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,8 +104,11 @@ pub fn (mut b Builder) middle_stages() ? {
|
||||
b.checker.check_files(b.parsed_files)
|
||||
util.timing_measure('CHECK')
|
||||
b.print_warnings_and_errors()
|
||||
if b.checker.should_abort {
|
||||
return error('too many errors/warnings/notices')
|
||||
}
|
||||
if b.pref.check_only {
|
||||
return error('stop_after_checker')
|
||||
return error_with_code('stop_after_checker', 9999)
|
||||
}
|
||||
util.timing_start('TRANSFORM')
|
||||
b.transformer.transform_files(b.parsed_files)
|
||||
|
@ -6,7 +6,12 @@ import v.util
|
||||
import v.gen.c
|
||||
|
||||
pub fn (mut b Builder) gen_c(v_files []string) string {
|
||||
b.front_and_middle_stages(v_files) or { return '' }
|
||||
b.front_and_middle_stages(v_files) or {
|
||||
if err.code != 9999 {
|
||||
verror(err.msg)
|
||||
}
|
||||
return ''
|
||||
}
|
||||
// TODO: move gen.cgen() to c.gen()
|
||||
util.timing_start('C GEN')
|
||||
res := c.gen(b.parsed_files, b.table, b.pref)
|
||||
|
@ -176,25 +176,113 @@ pub fn (mut c Checker) check_matching_function_symbols(got_type_sym &ast.TypeSym
|
||||
return true
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut c Checker) check_shift(left_type ast.Type, right_type ast.Type, left_pos token.Position, right_pos token.Position) ast.Type {
|
||||
fn (mut c Checker) check_shift(mut node ast.InfixExpr, left_type ast.Type, right_type ast.Type) ast.Type {
|
||||
if !left_type.is_int() {
|
||||
left_sym := c.table.get_type_symbol(left_type)
|
||||
// maybe it's an int alias? TODO move this to is_int() ?
|
||||
sym := c.table.get_type_symbol(left_type)
|
||||
if sym.kind == .alias && (sym.info as ast.Alias).parent_type.is_int() {
|
||||
if left_sym.kind == .alias && (left_sym.info as ast.Alias).parent_type.is_int() {
|
||||
return left_type
|
||||
}
|
||||
if c.pref.translated && left_type == ast.bool_type {
|
||||
// allow `bool << 2` in translated C code
|
||||
return ast.int_type
|
||||
}
|
||||
c.error('invalid operation: shift on type `$sym.name`', left_pos)
|
||||
c.error('invalid operation: shift on type `$left_sym.name`', node.left.position())
|
||||
return ast.void_type
|
||||
} else if !right_type.is_int() {
|
||||
c.error('cannot shift non-integer type `${c.table.get_type_symbol(right_type).name}` into type `${c.table.get_type_symbol(left_type).name}`',
|
||||
right_pos)
|
||||
}
|
||||
if !right_type.is_int() {
|
||||
left_sym := c.table.get_type_symbol(left_type)
|
||||
right_sym := c.table.get_type_symbol(right_type)
|
||||
c.error('cannot shift non-integer type `$right_sym.name` into type `$left_sym.name`',
|
||||
node.right.position())
|
||||
return ast.void_type
|
||||
}
|
||||
// At this point, it is guaranteed that we have a `number1 << number2`, or `number1 >> number2`, or `number1 >>> number2`:
|
||||
if !node.ct_left_value_evaled {
|
||||
if lval := c.eval_comptime_const_expr(node.left, 0) {
|
||||
node.ct_left_value_evaled = true
|
||||
node.ct_left_value = lval
|
||||
}
|
||||
}
|
||||
if !node.ct_right_value_evaled {
|
||||
if rval := c.eval_comptime_const_expr(node.right, 0) {
|
||||
node.ct_right_value_evaled = true
|
||||
node.ct_right_value = rval
|
||||
}
|
||||
}
|
||||
// if node.ct_left_value_evaled && node.ct_right_value_evaled {
|
||||
// c.note('>>> node.ct_left_value: $node.ct_left_value | node.ct_right_value: $node.ct_right_value', node.pos)
|
||||
// }
|
||||
match node.op {
|
||||
.left_shift, .right_shift, .unsigned_right_shift {
|
||||
// The following code tries to disallow C UBs and IDs at the V level.
|
||||
// From the C++ standart (see https://pvs-studio.com/en/docs/warnings/v610/):
|
||||
// 1. The type of the result is that of the promoted left operand.
|
||||
// The behavior is undefined (UB), if the right operand is negative,
|
||||
// or greater than or equal to the length in bits of the promoted left operand.
|
||||
// 2. The value of E1 << E2 is E1 left-shifted E2 bit positions;
|
||||
// vacated bits are zero-filled. If E1 has an unsigned type,
|
||||
// the value of the result is E1 * 2^E2, reduced modulo one more
|
||||
// than the maximum value representable in the result type.
|
||||
// Otherwise, if E1 has a signed type and non-negative value,
|
||||
// and E1*2^E2 is representable in the result type, then that is
|
||||
// the resulting value; otherwise, the behavior is undefined (UB).
|
||||
// 3. The value of E1 >> E2 is E1 right-shifted E2 bit positions.
|
||||
// If E1 has an unsigned type, or if E1 has a signed type and a
|
||||
// non-negative value, the value of the result is the integral
|
||||
// part of the quotient of E1/2^E2. If E1 has a signed type and
|
||||
// a negative value, the resulting value is implementation-defined (ID).
|
||||
left_sym_final := c.table.get_final_type_symbol(left_type)
|
||||
left_type_final := ast.Type(left_sym_final.idx)
|
||||
if node.op == .left_shift && left_type_final.is_signed() {
|
||||
c.note('shifting a value from a signed type `$left_sym_final.name` can change the sign',
|
||||
node.left.position())
|
||||
}
|
||||
if node.ct_right_value_evaled {
|
||||
if node.ct_right_value !is ast.EmptyExpr {
|
||||
ival := node.ct_right_value.i64() or { -999 }
|
||||
if ival < 0 {
|
||||
c.error('invalid negative shift count', node.right.position())
|
||||
return left_type
|
||||
}
|
||||
moffset := match left_type_final {
|
||||
ast.char_type { 7 }
|
||||
ast.i8_type { 7 }
|
||||
ast.i16_type { 15 }
|
||||
ast.int_type { 31 }
|
||||
ast.i64_type { 63 }
|
||||
//
|
||||
ast.byte_type { 7 }
|
||||
ast.u8_type { 7 }
|
||||
ast.u16_type { 15 }
|
||||
ast.u32_type { 31 }
|
||||
ast.u64_type { 63 }
|
||||
else { 64 }
|
||||
}
|
||||
if ival > moffset {
|
||||
c.error('shift count for type `$left_sym_final.name` too large (maximum: $moffset bits)',
|
||||
node.right.position())
|
||||
return left_type
|
||||
}
|
||||
if node.ct_left_value_evaled {
|
||||
if lval := node.ct_left_value.i64() {
|
||||
if lval < 0 {
|
||||
c.error('invalid bitshift of a negative number', node.left.position())
|
||||
return left_type
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// c.note('can not evaluate "$node.right" at comptime, err: $err', node.pos)
|
||||
return left_type
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
c.error('unknown shift operator: $node.op', node.pos)
|
||||
return left_type
|
||||
}
|
||||
}
|
||||
return left_type
|
||||
}
|
||||
|
||||
@ -339,7 +427,6 @@ pub fn (mut c Checker) check_expected(got ast.Type, expected ast.Type) ? {
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (c &Checker) expected_msg(got ast.Type, expected ast.Type) string {
|
||||
exps := c.table.type_to_str(expected)
|
||||
gots := c.table.type_to_str(got)
|
||||
|
@ -1370,11 +1370,11 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||
c.error('cannot append `$right_sym.name` to `$left_sym.name`', right_pos)
|
||||
return ast.void_type
|
||||
} else {
|
||||
return c.check_shift(left_type, right_type, left_pos, right_pos)
|
||||
return c.check_shift(mut node, left_type, right_type)
|
||||
}
|
||||
}
|
||||
.right_shift {
|
||||
return c.check_shift(left_type, right_type, left_pos, right_pos)
|
||||
return c.check_shift(mut node, left_type, right_type)
|
||||
}
|
||||
.unsigned_right_shift {
|
||||
modified_left_type := if !left_type.is_int() {
|
||||
@ -1418,7 +1418,7 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||
or_block: node.or_block
|
||||
}
|
||||
|
||||
return c.check_shift(left_type, right_type, left_pos, right_pos)
|
||||
return c.check_shift(mut node, left_type, right_type)
|
||||
}
|
||||
.key_is, .not_is {
|
||||
right_expr := node.right
|
||||
@ -3700,7 +3700,7 @@ pub fn (mut c Checker) const_decl(mut node ast.ConstDecl) {
|
||||
c.const_decl = field.name
|
||||
c.const_deps << field.name
|
||||
mut typ := c.check_expr_opt_call(field.expr, c.expr(field.expr))
|
||||
if ct_value := eval_comptime_const_expr(field.expr, 0) {
|
||||
if ct_value := c.eval_comptime_const_expr(field.expr, 0) {
|
||||
field.comptime_expr_value = ct_value
|
||||
if ct_value is u64 {
|
||||
typ = ast.u64_type
|
||||
@ -4539,7 +4539,7 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
}
|
||||
ast.Ident {
|
||||
if init_expr.obj is ast.ConstField {
|
||||
if comptime_value := eval_comptime_const_expr(init_expr.obj.expr,
|
||||
if comptime_value := c.eval_comptime_const_expr(init_expr.obj.expr,
|
||||
0)
|
||||
{
|
||||
fixed_size = comptime_value.i64() or { fixed_size }
|
||||
@ -4549,7 +4549,7 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
}
|
||||
}
|
||||
ast.InfixExpr {
|
||||
if comptime_value := eval_comptime_const_expr(init_expr, 0) {
|
||||
if comptime_value := c.eval_comptime_const_expr(init_expr, 0) {
|
||||
fixed_size = comptime_value.i64() or { fixed_size }
|
||||
}
|
||||
}
|
||||
@ -5294,6 +5294,9 @@ fn (mut c Checker) stmts_ending_with_expression(stmts []ast.Stmt) {
|
||||
}
|
||||
c.scope_returns = false
|
||||
}
|
||||
if c.should_abort {
|
||||
return
|
||||
}
|
||||
}
|
||||
c.stmt_level--
|
||||
if unreachable.line_nr >= 0 {
|
||||
@ -8590,12 +8593,49 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Position) ? {
|
||||
}
|
||||
|
||||
// comptime const eval
|
||||
fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue {
|
||||
fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue {
|
||||
if nlevel > 100 {
|
||||
// protect against a too deep comptime eval recursion
|
||||
return none
|
||||
}
|
||||
match expr {
|
||||
ast.ParExpr {
|
||||
return c.eval_comptime_const_expr(expr.expr, nlevel + 1)
|
||||
}
|
||||
// ast.EnumVal {
|
||||
// c.note('>>>>>>>> expr: $expr', expr.pos)
|
||||
// return expr.val.i64()
|
||||
// }
|
||||
ast.SizeOf {
|
||||
xtype := expr.typ
|
||||
if xtype.is_real_pointer() {
|
||||
if c.pref.m64 {
|
||||
return 8 // 64bit platform
|
||||
}
|
||||
return 4 // 32bit platform
|
||||
}
|
||||
if int(xtype) == xtype.idx() {
|
||||
match xtype {
|
||||
ast.char_type { return 1 }
|
||||
ast.i8_type { return 1 }
|
||||
ast.i16_type { return 2 }
|
||||
ast.int_type { return 4 }
|
||||
ast.i64_type { return 8 }
|
||||
//
|
||||
ast.byte_type { return 1 }
|
||||
ast.u8_type { return 1 }
|
||||
ast.u16_type { return 2 }
|
||||
ast.u32_type { return 4 }
|
||||
ast.u64_type { return 8 }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
ast.FloatLiteral {
|
||||
x := expr.val.f64()
|
||||
return x
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
x := expr.val.u64()
|
||||
if x > 9223372036854775807 {
|
||||
@ -8616,11 +8656,11 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
ast.Ident {
|
||||
if expr.obj is ast.ConstField {
|
||||
// an existing constant?
|
||||
return eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
||||
return c.eval_comptime_const_expr(expr.obj.expr, nlevel + 1)
|
||||
}
|
||||
}
|
||||
ast.CastExpr {
|
||||
cast_expr_value := eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
||||
cast_expr_value := c.eval_comptime_const_expr(expr.expr, nlevel + 1) or { return none }
|
||||
if expr.typ == ast.i8_type {
|
||||
return cast_expr_value.i8() or { return none }
|
||||
}
|
||||
@ -8655,8 +8695,8 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
}
|
||||
}
|
||||
ast.InfixExpr {
|
||||
left := eval_comptime_const_expr(expr.left, nlevel + 1) ?
|
||||
right := eval_comptime_const_expr(expr.right, nlevel + 1) ?
|
||||
left := c.eval_comptime_const_expr(expr.left, nlevel + 1) ?
|
||||
right := c.eval_comptime_const_expr(expr.right, nlevel + 1) ?
|
||||
if left is string && right is string {
|
||||
match expr.op {
|
||||
.plus {
|
||||
@ -8676,8 +8716,9 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
.xor { return i64(left) ^ i64(right) }
|
||||
.pipe { return i64(left) | i64(right) }
|
||||
.amp { return i64(left) & i64(right) }
|
||||
.left_shift { return i64(left) << i64(right) }
|
||||
.right_shift { return i64(left) >> i64(right) }
|
||||
.left_shift { return i64(u64(left) << i64(right)) }
|
||||
.right_shift { return i64(u64(left) >> i64(right)) }
|
||||
.unsigned_right_shift { return i64(u64(left) >>> i64(right)) }
|
||||
else { return none }
|
||||
}
|
||||
} else if left is i64 && right is u64 {
|
||||
@ -8690,8 +8731,9 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
.xor { return i64(left) ^ i64(right) }
|
||||
.pipe { return i64(left) | i64(right) }
|
||||
.amp { return i64(left) & i64(right) }
|
||||
.left_shift { return i64(left) << i64(right) }
|
||||
.right_shift { return i64(left) >> i64(right) }
|
||||
.left_shift { return i64(u64(left) << i64(right)) }
|
||||
.right_shift { return i64(u64(left) >> i64(right)) }
|
||||
.unsigned_right_shift { return i64(u64(left) >>> i64(right)) }
|
||||
else { return none }
|
||||
}
|
||||
} else if left is u64 && right is u64 {
|
||||
@ -8706,6 +8748,7 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
.amp { return left & right }
|
||||
.left_shift { return left << right }
|
||||
.right_shift { return left >> right }
|
||||
.unsigned_right_shift { return left >>> right }
|
||||
else { return none }
|
||||
}
|
||||
} else if left is i64 && right is i64 {
|
||||
@ -8718,8 +8761,9 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
.xor { return left ^ right }
|
||||
.pipe { return left | right }
|
||||
.amp { return left & right }
|
||||
.left_shift { return left << right }
|
||||
.right_shift { return left >> right }
|
||||
.left_shift { return i64(u64(left) << right) }
|
||||
.right_shift { return i64(u64(left) >> right) }
|
||||
.unsigned_right_shift { return i64(u64(left) >>> right) }
|
||||
else { return none }
|
||||
}
|
||||
} else if left is byte && right is byte {
|
||||
@ -8734,10 +8778,15 @@ fn eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.ComptTimeConstValue
|
||||
.amp { return left & right }
|
||||
.left_shift { return left << right }
|
||||
.right_shift { return left >> right }
|
||||
.unsigned_right_shift { return left >>> right }
|
||||
else { return none }
|
||||
}
|
||||
}
|
||||
}
|
||||
// ast.ArrayInit {}
|
||||
// ast.PrefixExpr {
|
||||
// c.note('prefixexpr: $expr', expr.pos)
|
||||
// }
|
||||
else {
|
||||
// eprintln('>>> nlevel: $nlevel | another $expr.type_name() | $expr ')
|
||||
return none
|
||||
|
@ -1,49 +0,0 @@
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:4:2: error: unused expression
|
||||
2 | mut a := 12
|
||||
3 | mut arr := []int{}
|
||||
4 | a << 1
|
||||
| ~~~~~~
|
||||
5 | if true {
|
||||
6 | a << 2
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:6:3: error: unused expression
|
||||
4 | a << 1
|
||||
5 | if true {
|
||||
6 | a << 2
|
||||
| ~~~~~~
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:10:2: error: unused expression
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
| ~~~~~~
|
||||
11 | println(a)
|
||||
12 | 5 << 9
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:12:2: error: unused expression
|
||||
10 | a << 1
|
||||
11 | println(a)
|
||||
12 | 5 << 9
|
||||
| ~~~~~~
|
||||
13 | for i in 0 .. 10 {
|
||||
14 | z := i << 5
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:15:3: error: unused expression
|
||||
13 | for i in 0 .. 10 {
|
||||
14 | z := i << 5
|
||||
15 | i << 5
|
||||
| ~~~~~~
|
||||
16 | println(z)
|
||||
17 | }
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:33:3: error: unused expression
|
||||
31 | //
|
||||
32 | x := if true {
|
||||
33 | a << 1
|
||||
| ~~~~~~
|
||||
34 | 999
|
||||
35 | } else {
|
||||
vlib/v/checker/tests/left_shift_op_expr_not_used.vv:37:3: error: unused expression
|
||||
35 | } else {
|
||||
36 | println('---')
|
||||
37 | a << 9999
|
||||
| ~~~~~~~~~
|
||||
38 | println('---')
|
||||
39 | 555
|
@ -1,6 +1,6 @@
|
||||
vlib/v/checker/tests/selector_expr_optional_err.vv:4:46: error: cannot access fields of an optional, handle the error with `or {...}` or propagate it with `?`
|
||||
2 |
|
||||
3 | fn main() {
|
||||
4 | println(http.get('https://httpbin.org/').status_code)
|
||||
| ~~~~~~~~~~~
|
||||
5 | }
|
||||
vlib/v/checker/tests/selector_expr_optional_err.vv:10:16: error: cannot access fields of an optional, handle the error with `or {...}` or propagate it with `?`
|
||||
8 |
|
||||
9 | fn main() {
|
||||
10 | println(abc().status_code)
|
||||
| ~~~~~~~~~~~
|
||||
11 | }
|
||||
|
@ -1,5 +1,11 @@
|
||||
import net.http
|
||||
struct HttpResult {
|
||||
status_code int
|
||||
}
|
||||
|
||||
fn abc() ?HttpResult {
|
||||
return HttpResult{}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println(http.get('https://httpbin.org/').status_code)
|
||||
println(abc().status_code)
|
||||
}
|
||||
|
133
vlib/v/checker/tests/shift_ops_expressions.out
Normal file
133
vlib/v/checker/tests/shift_ops_expressions.out
Normal file
@ -0,0 +1,133 @@
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:4:2: notice: shifting a value from a signed type `int` can change the sign
|
||||
2 | mut a := 12
|
||||
3 | mut arr := []int{}
|
||||
4 | a << 1
|
||||
| ^
|
||||
5 | if true {
|
||||
6 | a << 2
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:6:3: notice: shifting a value from a signed type `int` can change the sign
|
||||
4 | a << 1
|
||||
5 | if true {
|
||||
6 | a << 2
|
||||
| ^
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:8:17: notice: shifting a value from a signed type `int` can change the sign
|
||||
6 | a << 2
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
| ^
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:8:17: notice: shifting a value from a signed type `int` can change the sign
|
||||
6 | a << 2
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
| ^
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:8:35: notice: shifting a value from a signed type `int` can change the sign
|
||||
6 | a << 2
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
| ^
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:8:35: notice: shifting a value from a signed type `int` can change the sign
|
||||
6 | a << 2
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
| ^
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:10:2: notice: shifting a value from a signed type `int` can change the sign
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
| ^
|
||||
11 | println(a)
|
||||
12 | 5 << 9
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:33:3: notice: shifting a value from a signed type `int` can change the sign
|
||||
31 | //
|
||||
32 | x := if true {
|
||||
33 | a << 1
|
||||
| ^
|
||||
34 | 999
|
||||
35 | } else {
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:37:3: notice: shifting a value from a signed type `int` can change the sign
|
||||
35 | } else {
|
||||
36 | println('---')
|
||||
37 | a << 9999
|
||||
| ^
|
||||
38 | println('---')
|
||||
39 | 555
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:4:2: error: unused expression
|
||||
2 | mut a := 12
|
||||
3 | mut arr := []int{}
|
||||
4 | a << 1
|
||||
| ~~~~~~
|
||||
5 | if true {
|
||||
6 | a << 2
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:6:3: error: unused expression
|
||||
4 | a << 1
|
||||
5 | if true {
|
||||
6 | a << 2
|
||||
| ~~~~~~
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:8:22: error: shift count for type `int` too large (maximum: 31 bits)
|
||||
6 | a << 2
|
||||
7 | }
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
| ~~~
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:10:2: error: unused expression
|
||||
8 | c := if true { a << 111 } else { a << 333 }
|
||||
9 | println(c)
|
||||
10 | a << 1
|
||||
| ~~~~~~
|
||||
11 | println(a)
|
||||
12 | 5 << 9
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:12:2: error: unused expression
|
||||
10 | a << 1
|
||||
11 | println(a)
|
||||
12 | 5 << 9
|
||||
| ~~~~~~
|
||||
13 | for i in 0 .. 10 {
|
||||
14 | z := i << 5
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:15:3: error: unused expression
|
||||
13 | for i in 0 .. 10 {
|
||||
14 | z := i << 5
|
||||
15 | i << 5
|
||||
| ~~~~~~
|
||||
16 | println(z)
|
||||
17 | }
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:33:3: error: unused expression
|
||||
31 | //
|
||||
32 | x := if true {
|
||||
33 | a << 1
|
||||
| ~~~~~~
|
||||
34 | 999
|
||||
35 | } else {
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:37:8: error: shift count for type `int` too large (maximum: 31 bits)
|
||||
35 | } else {
|
||||
36 | println('---')
|
||||
37 | a << 9999
|
||||
| ~~~~
|
||||
38 | println('---')
|
||||
39 | 555
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:50:23: error: shift count for type `int` too large (maximum: 31 bits)
|
||||
48 | rr >> 2
|
||||
49 | }
|
||||
50 | c := if true { rr >> 111 } else { rr >> 333 }
|
||||
| ~~~
|
||||
51 | println(c)
|
||||
52 | rr >> 1
|
||||
vlib/v/checker/tests/shift_ops_expressions.vv:66:9: error: shift count for type `int` too large (maximum: 31 bits)
|
||||
64 | } else {
|
||||
65 | println('---')
|
||||
66 | rr >> 9999
|
||||
| ~~~~
|
||||
67 | println('---')
|
||||
68 | 555
|
@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
fn left_shifts() {
|
||||
mut a := 12
|
||||
mut arr := []int{}
|
||||
a << 1
|
||||
@ -40,3 +40,37 @@ fn main() {
|
||||
}
|
||||
println(x)
|
||||
}
|
||||
|
||||
fn right_shifts() {
|
||||
mut rr := 12
|
||||
rr >> 1
|
||||
if true {
|
||||
rr >> 2
|
||||
}
|
||||
c := if true { rr >> 111 } else { rr >> 333 }
|
||||
println(c)
|
||||
rr >> 1
|
||||
println(rr)
|
||||
5 >> 9
|
||||
for i in 0 .. 10 {
|
||||
z := i >> 5
|
||||
i >> 5
|
||||
println(z)
|
||||
}
|
||||
//
|
||||
x := if true {
|
||||
rr >> 1
|
||||
999
|
||||
} else {
|
||||
println('---')
|
||||
rr >> 9999
|
||||
println('---')
|
||||
555
|
||||
}
|
||||
println(x)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
left_shifts()
|
||||
right_shifts()
|
||||
}
|
@ -2220,7 +2220,7 @@ struct SumtypeCastingFn {
|
||||
|
||||
fn (mut g Gen) get_sumtype_casting_fn(got_ ast.Type, exp_ ast.Type) string {
|
||||
got, exp := got_.idx(), exp_.idx()
|
||||
i := got | (exp << 16)
|
||||
i := got | int(u32(exp) << 16)
|
||||
got_cname, exp_cname := g.table.get_type_symbol(got).cname, g.table.get_type_symbol(exp).cname
|
||||
fn_name := '${got_cname}_to_sumtype_$exp_cname'
|
||||
if got == exp || g.sumtype_definitions[i] {
|
||||
@ -2961,6 +2961,16 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
}
|
||||
}
|
||||
// `a := 1` | `a,b := 1,2`
|
||||
if assign_stmt.right.len < assign_stmt.left.len {
|
||||
g.checker_bug('assign_stmt.right.len < assign_stmt.left.len', assign_stmt.pos)
|
||||
}
|
||||
if assign_stmt.right_types.len < assign_stmt.left.len {
|
||||
g.checker_bug('assign_stmt.right_types.len < assign_stmt.left.len', assign_stmt.pos)
|
||||
}
|
||||
if assign_stmt.left_types.len < assign_stmt.left.len {
|
||||
g.checker_bug('assign_stmt.left_types.len < assign_stmt.left.len', assign_stmt.pos)
|
||||
}
|
||||
|
||||
for i, left in assign_stmt.left {
|
||||
mut is_auto_heap := false
|
||||
mut var_type := assign_stmt.left_types[i]
|
||||
|
@ -58,7 +58,7 @@ fn (mut g Gen) mov_arm(reg Arm64Register, val u64) {
|
||||
g.write32(0xd2800020)
|
||||
g.println('mov x0, 1')
|
||||
} else if r >= 0 && r <= 16 {
|
||||
g.write32(0xd2800000 + int(r) + (int(val) << 5))
|
||||
g.write32(int(u32(0xd2800000 + int(r) + int(val)) << 5))
|
||||
g.println('mov x$r, $val')
|
||||
} else {
|
||||
g.n_error('mov_arm unsupported values')
|
||||
@ -143,7 +143,7 @@ fn (mut g Gen) gen_arm64_helloworld() {
|
||||
}
|
||||
|
||||
fn (mut g Gen) adr(r Arm64Register, delta int) {
|
||||
g.write32(0x10000000 | int(r) | (delta << 4))
|
||||
g.write32(int(0x10000000 | int(r) | int(u32(delta) << 4)))
|
||||
g.println('adr $r, $delta')
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,8 @@ fn (mut g Gen) write16(n int) {
|
||||
}
|
||||
|
||||
fn (mut g Gen) read32_at(at int) int {
|
||||
return int(g.buf[at] | (g.buf[at + 1] << 8) | (g.buf[at + 2] << 16) | (g.buf[at + 3] << 24))
|
||||
return int(u32(g.buf[at]) | (u32(g.buf[at + 1]) << 8) | (u32(g.buf[at + 2]) << 16) | (u32(g.buf[
|
||||
at + 3]) << 24))
|
||||
}
|
||||
|
||||
fn (mut g Gen) write32(n int) {
|
||||
|
@ -1808,11 +1808,14 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||
} else if !p.pref.translated && !p.pref.is_fmt
|
||||
&& tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock, .key_select] {
|
||||
for node in left {
|
||||
if node !is ast.CallExpr && (is_top_level || p.tok.kind != .rcbr)
|
||||
&& node !is ast.PostfixExpr && !(node is ast.InfixExpr
|
||||
&& (node as ast.InfixExpr).op in [.left_shift, .arrow]) && node !is ast.ComptimeCall
|
||||
if (is_top_level || p.tok.kind != .rcbr) && node !is ast.CallExpr
|
||||
&& node !is ast.PostfixExpr && node !is ast.ComptimeCall
|
||||
&& node !is ast.SelectorExpr && node !is ast.DumpExpr {
|
||||
return p.error_with_pos('expression evaluated but not used', node.position())
|
||||
is_complex_infix_expr := node is ast.InfixExpr
|
||||
&& (node as ast.InfixExpr).op in [.left_shift, .right_shift, .unsigned_right_shift, .arrow]
|
||||
if !is_complex_infix_expr {
|
||||
return p.error_with_pos('expression evaluated but not used', node.position())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -481,7 +481,7 @@ pub fn (t Transformer) infix_expr(original ast.InfixExpr) ast.Expr {
|
||||
}
|
||||
.left_shift {
|
||||
return ast.IntegerLiteral{
|
||||
val: (left_val << right_val).str()
|
||||
val: (u32(left_val) << right_val).str()
|
||||
pos: pos
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ fn (mut bmp BitMap) format_texture() {
|
||||
x[i + 1] = g
|
||||
x[i + 2] = b
|
||||
// alpha
|
||||
x[i + 3] = byte((a * data) >> 8)
|
||||
x[i + 3] = byte(u16(a * data) >> 8)
|
||||
} else {
|
||||
x[i + 0] = b_r
|
||||
x[i + 1] = b_g
|
||||
|
@ -501,7 +501,7 @@ fn (mut tf TTF_File) get_i8() i8 {
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) get_u16() u16 {
|
||||
x := u16(tf.buf[tf.pos] << u16(8)) | u16(tf.buf[tf.pos + 1])
|
||||
x := u16(tf.buf[tf.pos]) << 8 | u16(tf.buf[tf.pos + 1])
|
||||
tf.pos += 2
|
||||
return x
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user