checker: disallow 'small_unsigned == signed' (#13967)
parent
6718958058
commit
c780de6282
|
@ -161,7 +161,7 @@ fn test_bf_from_str() {
|
||||||
output := bitfield.from_str(input)
|
output := bitfield.from_str(input)
|
||||||
mut result := 1
|
mut result := 1
|
||||||
for i in 0 .. len {
|
for i in 0 .. len {
|
||||||
if input[i] != output.get_bit(i) + 48 {
|
if input[i] != byte(output.get_bit(i)) + 48 {
|
||||||
result = 0
|
result = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -775,7 +775,7 @@ fn test_byte_keys() {
|
||||||
m[i]++
|
m[i]++
|
||||||
assert m[i] == i + 1
|
assert m[i] == i + 1
|
||||||
}
|
}
|
||||||
assert m.len == byte_max
|
assert m.len == int(byte_max)
|
||||||
keys := m.keys()
|
keys := m.keys()
|
||||||
for i in byte(0) .. byte_max {
|
for i in byte(0) .. byte_max {
|
||||||
assert keys[i] == i
|
assert keys[i] == i
|
||||||
|
@ -827,7 +827,7 @@ fn test_u16_keys() {
|
||||||
m[i]++
|
m[i]++
|
||||||
assert m[i] == i + 1
|
assert m[i] == i + 1
|
||||||
}
|
}
|
||||||
assert m.len == end
|
assert m.len == int(end)
|
||||||
keys := m.keys()
|
keys := m.keys()
|
||||||
for i in u16(0) .. end {
|
for i in u16(0) .. end {
|
||||||
assert keys[i] == i
|
assert keys[i] == i
|
||||||
|
|
|
@ -763,7 +763,7 @@ fn test_byte_keys() {
|
||||||
m[i]++
|
m[i]++
|
||||||
assert m[i] == i + 1
|
assert m[i] == i + 1
|
||||||
}
|
}
|
||||||
assert m.len == byte_max
|
assert m.len == int(byte_max)
|
||||||
keys := m.keys()
|
keys := m.keys()
|
||||||
for i in byte(0) .. byte_max {
|
for i in byte(0) .. byte_max {
|
||||||
assert keys[i] == i
|
assert keys[i] == i
|
||||||
|
@ -815,7 +815,7 @@ fn test_u16_keys() {
|
||||||
m[i]++
|
m[i]++
|
||||||
assert m[i] == i + 1
|
assert m[i] == i + 1
|
||||||
}
|
}
|
||||||
assert m.len == end
|
assert m.len == int(end)
|
||||||
keys := m.keys()
|
keys := m.keys()
|
||||||
for i in u16(0) .. end {
|
for i in u16(0) .. end {
|
||||||
assert keys[i] == i
|
assert keys[i] == i
|
||||||
|
|
|
@ -1937,7 +1937,7 @@ pub fn (name string) match_glob(pattern string) bool {
|
||||||
mut is_inverted := false
|
mut is_inverted := false
|
||||||
mut inner_match := false
|
mut inner_match := false
|
||||||
mut inner_idx := bstart + 1
|
mut inner_idx := bstart + 1
|
||||||
mut inner_c := 0
|
mut inner_c := byte(0)
|
||||||
if inner_idx < plen {
|
if inner_idx < plen {
|
||||||
inner_c = pattern[inner_idx]
|
inner_c = pattern[inner_idx]
|
||||||
if inner_c == `^` {
|
if inner_c == `^` {
|
||||||
|
|
|
@ -173,7 +173,7 @@ pub fn (mut zentry Zip) crc32() u32 {
|
||||||
|
|
||||||
// write_entry compresses an input buffer for the current zip entry.
|
// write_entry compresses an input buffer for the current zip entry.
|
||||||
pub fn (mut zentry Zip) write_entry(data []byte) ? {
|
pub fn (mut zentry Zip) write_entry(data []byte) ? {
|
||||||
if (data[0] & 0xff) == -1 {
|
if int(data[0] & 0xff) == -1 {
|
||||||
return error('szip: cannot write entry')
|
return error('szip: cannot write entry')
|
||||||
}
|
}
|
||||||
res := C.zip_entry_write(zentry, data.data, data.len)
|
res := C.zip_entry_write(zentry, data.data, data.len)
|
||||||
|
|
|
@ -288,8 +288,8 @@ fn (mut ctx Context) parse_events() {
|
||||||
if !C.GetConsoleScreenBufferInfo(ctx.stdout_handle, &sb) {
|
if !C.GetConsoleScreenBufferInfo(ctx.stdout_handle, &sb) {
|
||||||
panic('could not get screenbuffer info')
|
panic('could not get screenbuffer info')
|
||||||
}
|
}
|
||||||
w := sb.srWindow.Right - sb.srWindow.Left + 1
|
w := int(sb.srWindow.Right - sb.srWindow.Left + 1)
|
||||||
h := sb.srWindow.Bottom - sb.srWindow.Top + 1
|
h := int(sb.srWindow.Bottom - sb.srWindow.Top + 1)
|
||||||
utf8 := '($ctx.window_width, $ctx.window_height) -> ($w, $h)'
|
utf8 := '($ctx.window_width, $ctx.window_height) -> ($w, $h)'
|
||||||
if w != ctx.window_width || h != ctx.window_height {
|
if w != ctx.window_width || h != ctx.window_height {
|
||||||
ctx.window_width, ctx.window_height = w, h
|
ctx.window_width, ctx.window_height = w, h
|
||||||
|
|
|
@ -9,7 +9,7 @@ import toml.util
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
digit_extras = [`_`, `.`, `x`, `o`, `b`, `e`, `E`]
|
digit_extras = [`_`, `.`, `x`, `o`, `b`, `e`, `E`]
|
||||||
end_of_text = 4294967295
|
end_of_text = u32(~0)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scanner contains the necessary fields for the state of the scan process.
|
// Scanner contains the necessary fields for the state of the scan process.
|
||||||
|
|
|
@ -374,6 +374,23 @@ pub fn (typ Type) is_unsigned() bool {
|
||||||
return typ.idx() in ast.unsigned_integer_type_idxs
|
return typ.idx() in ast.unsigned_integer_type_idxs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (typ Type) flip_signedness() Type {
|
||||||
|
r := match typ {
|
||||||
|
ast.i8_type { ast.byte_type }
|
||||||
|
ast.i16_type { ast.u16_type }
|
||||||
|
ast.int_type { ast.u32_type }
|
||||||
|
ast.isize_type { ast.usize_type }
|
||||||
|
ast.i64_type { ast.u64_type }
|
||||||
|
ast.byte_type { ast.i8_type }
|
||||||
|
ast.u16_type { ast.i16_type }
|
||||||
|
ast.u32_type { ast.int_type }
|
||||||
|
ast.usize_type { ast.isize_type }
|
||||||
|
ast.u64_type { ast.i64_type }
|
||||||
|
else { typ }
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (typ Type) is_int_literal() bool {
|
pub fn (typ Type) is_int_literal() bool {
|
||||||
return int(typ) == ast.int_literal_type_idx
|
return int(typ) == ast.int_literal_type_idx
|
||||||
|
@ -442,6 +459,9 @@ pub const (
|
||||||
i64_type_idx, isize_type_idx]
|
i64_type_idx, isize_type_idx]
|
||||||
unsigned_integer_type_idxs = [byte_type_idx, u8_type_idx, u16_type_idx, u32_type_idx,
|
unsigned_integer_type_idxs = [byte_type_idx, u8_type_idx, u16_type_idx, u32_type_idx,
|
||||||
u64_type_idx, usize_type_idx]
|
u64_type_idx, usize_type_idx]
|
||||||
|
// C will promote any type smaller than int to int in an expression
|
||||||
|
int_promoted_type_idxs = [char_type_idx, i8_type_idx, i16_type_idx, byte_type_idx,
|
||||||
|
u8_type_idx, u16_type_idx]
|
||||||
float_type_idxs = [f32_type_idx, f64_type_idx, float_literal_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,
|
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx,
|
||||||
byte_type_idx, char_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx,
|
byte_type_idx, char_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx,
|
||||||
|
|
|
@ -79,3 +79,9 @@ fn test_derive() {
|
||||||
assert t2.has_flag(ast.TypeFlag.generic) == true
|
assert t2.has_flag(ast.TypeFlag.generic) == true
|
||||||
assert t2.nr_muls() == 10
|
assert t2.nr_muls() == 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_flip_signedness() {
|
||||||
|
assert ast.i8_type.flip_signedness() == ast.byte_type
|
||||||
|
assert ast.u16_type.flip_signedness() == ast.i16_type
|
||||||
|
assert ast.isize_type.flip_signedness() == ast.usize_type
|
||||||
|
}
|
||||||
|
|
|
@ -626,6 +626,29 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||||
if is_mismatch {
|
if is_mismatch {
|
||||||
c.error('possible type mismatch of compared values of `$node.op` operation',
|
c.error('possible type mismatch of compared values of `$node.op` operation',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
|
} else if left_type in ast.integer_type_idxs && right_type in ast.integer_type_idxs {
|
||||||
|
is_left_type_signed := left_type in ast.signed_integer_type_idxs
|
||||||
|
is_right_type_signed := right_type in ast.signed_integer_type_idxs
|
||||||
|
if !is_left_type_signed && mut node.right is ast.IntegerLiteral {
|
||||||
|
if node.right.val.int() < 0 && left_type in ast.int_promoted_type_idxs {
|
||||||
|
lt := c.table.sym(left_type).name
|
||||||
|
c.error('`$lt` cannot be compared with negative value', node.right.pos)
|
||||||
|
}
|
||||||
|
} else if !is_right_type_signed && mut node.left is ast.IntegerLiteral {
|
||||||
|
if node.left.val.int() < 0 && right_type in ast.int_promoted_type_idxs {
|
||||||
|
rt := c.table.sym(right_type).name
|
||||||
|
c.error('negative value cannot be compared with `$rt`', node.left.pos)
|
||||||
|
}
|
||||||
|
} else if is_left_type_signed != is_right_type_signed
|
||||||
|
&& left_type.flip_signedness() != right_type {
|
||||||
|
// prevent e.g. `u16(-1) == int(-1)` which is false in C
|
||||||
|
if (is_right_type_signed && left_type in ast.int_promoted_type_idxs)
|
||||||
|
|| (is_left_type_signed && right_type in ast.int_promoted_type_idxs) {
|
||||||
|
lt := c.table.sym(left_type).name
|
||||||
|
rt := c.table.sym(right_type).name
|
||||||
|
c.error('`$lt` cannot be compared with `$rt`', node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_in, .not_in {
|
.key_in, .not_in {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
vlib/v/checker/tests/compare_unsigned_signed.vv:2:14: error: unsigned integer cannot be compared with negative value
|
||||||
|
1 | fn main() {
|
||||||
|
2 | if u32(1) < -1 {
|
||||||
|
| ~~
|
||||||
|
3 | println('unexpected')
|
||||||
|
4 | }
|
||||||
|
vlib/v/checker/tests/compare_unsigned_signed.vv:6:5: error: unsigned integer cannot be compared with negative value
|
||||||
|
4 | }
|
||||||
|
5 |
|
||||||
|
6 | if -1 > u32(1) {
|
||||||
|
| ~~
|
||||||
|
7 | println('unexpected')
|
||||||
|
8 | }
|
||||||
|
vlib/v/checker/tests/compare_unsigned_signed.vv:10:18: error: `byte` cannot be compared with negative value
|
||||||
|
8 | }
|
||||||
|
9 | // unsigned == literal
|
||||||
|
10 | _ = byte(-1) == -1 // false!
|
||||||
|
| ~~
|
||||||
|
11 | _ = -1 == u16(-1) // false!
|
||||||
|
12 |
|
||||||
|
vlib/v/checker/tests/compare_unsigned_signed.vv:11:6: error: negative value cannot be compared with `u16`
|
||||||
|
9 | // unsigned == literal
|
||||||
|
10 | _ = byte(-1) == -1 // false!
|
||||||
|
11 | _ = -1 == u16(-1) // false!
|
||||||
|
| ~~
|
||||||
|
12 |
|
||||||
|
13 | // unsigned == signed
|
||||||
|
vlib/v/checker/tests/compare_unsigned_signed.vv:14:14: error: `u16` cannot be compared with `int`
|
||||||
|
12 |
|
||||||
|
13 | // unsigned == signed
|
||||||
|
14 | _ = u16(-1) == int(-1)
|
||||||
|
| ~~
|
||||||
|
15 | _ = int(-1) != byte(-1)
|
||||||
|
16 | }
|
||||||
|
vlib/v/checker/tests/compare_unsigned_signed.vv:15:14: error: `int` cannot be compared with `byte`
|
||||||
|
13 | // unsigned == signed
|
||||||
|
14 | _ = u16(-1) == int(-1)
|
||||||
|
15 | _ = int(-1) != byte(-1)
|
||||||
|
| ~~
|
||||||
|
16 | }
|
|
@ -0,0 +1,16 @@
|
||||||
|
fn main() {
|
||||||
|
if u32(1) < -1 {
|
||||||
|
println('unexpected')
|
||||||
|
}
|
||||||
|
|
||||||
|
if -1 > u32(1) {
|
||||||
|
println('unexpected')
|
||||||
|
}
|
||||||
|
// unsigned == literal
|
||||||
|
_ = byte(-1) == -1 // false!
|
||||||
|
_ = -1 == u16(-1) // false!
|
||||||
|
|
||||||
|
// unsigned == signed
|
||||||
|
_ = u16(-1) == int(-1)
|
||||||
|
_ = int(-1) != byte(-1)
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv:2:14: error: unsigned integer cannot be compared with negative value
|
|
||||||
1 | fn main() {
|
|
||||||
2 | if u32(1) < -1 {
|
|
||||||
| ~~
|
|
||||||
3 | println('unexpected')
|
|
||||||
4 | }
|
|
||||||
vlib/v/checker/tests/infix_unsigned_and_signed_int_err.vv:6:5: error: unsigned integer cannot be compared with negative value
|
|
||||||
4 | }
|
|
||||||
5 |
|
|
||||||
6 | if -1 > u32(1) {
|
|
||||||
| ~~
|
|
||||||
7 | println('unexpected')
|
|
||||||
8 | }
|
|
|
@ -1,9 +0,0 @@
|
||||||
fn main() {
|
|
||||||
if u32(1) < -1 {
|
|
||||||
println('unexpected')
|
|
||||||
}
|
|
||||||
|
|
||||||
if -1 > u32(1) {
|
|
||||||
println('unexpected')
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -778,7 +778,7 @@ pub fn (mut bmp BitMap) draw_glyph(index u16) (int, int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == glyph.contour_ends[c] {
|
if count == int(glyph.contour_ends[c]) {
|
||||||
// dprintln("count == glyph.contour_ends[count]")
|
// dprintln("count == glyph.contour_ends[count]")
|
||||||
if s == 2 { // final point was off-curve. connect to start
|
if s == 2 { // final point was off-curve. connect to start
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue