checker: prompt error on implicit int overflow by literal (#6410)
parent
34884c1631
commit
5086fd537c
|
@ -182,10 +182,7 @@ fn test_int_decl() {
|
|||
assert typeof(x3) == 'int'
|
||||
assert typeof(x4) == 'int'
|
||||
assert typeof(x5) == 'int'
|
||||
// integers are always 'int' by default
|
||||
x6 := 989898932113111
|
||||
x7 := u64(-321314588900011)
|
||||
assert typeof(x6) == 'int'
|
||||
assert typeof(x7) == 'u64'
|
||||
}
|
||||
|
||||
|
|
|
@ -178,8 +178,8 @@ fn test_mt19937_u64_in_range() {
|
|||
}
|
||||
|
||||
fn test_mt19937_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for seed in seeds {
|
||||
mut rng := mt19937.MT19937RNG{}
|
||||
rng.seed(seed)
|
||||
|
|
|
@ -168,8 +168,8 @@ fn test_musl_u64_in_range() {
|
|||
}
|
||||
|
||||
fn test_musl_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for seed in seeds {
|
||||
mut rng := musl.MuslRNG{}
|
||||
rng.seed(seed)
|
||||
|
|
|
@ -169,8 +169,8 @@ fn test_pcg32_u64_in_range() {
|
|||
}
|
||||
|
||||
fn test_pcg32_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for seed in seeds {
|
||||
mut rng := pcg32.PCG32RNG{}
|
||||
rng.seed(seed)
|
||||
|
|
|
@ -100,8 +100,8 @@ fn test_rand_i64_in_range() {
|
|||
}
|
||||
|
||||
fn test_rand_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for _ in 0 .. rnd_count {
|
||||
value := rand.int31()
|
||||
assert value >= 0
|
||||
|
|
|
@ -168,8 +168,8 @@ fn test_splitmix64_u64_in_range() {
|
|||
}
|
||||
|
||||
fn test_splitmix64_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for seed in seeds {
|
||||
mut rng := splitmix64.SplitMix64RNG{}
|
||||
rng.seed(seed)
|
||||
|
|
|
@ -237,8 +237,8 @@ fn test_sys_rng_i64_in_range() {
|
|||
}
|
||||
|
||||
fn test_sys_rng_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for seed in seeds {
|
||||
seed_data := [seed]
|
||||
mut rng := sys.SysRNG{}
|
||||
|
|
|
@ -168,8 +168,8 @@ fn test_wyrand_u64_in_range() {
|
|||
}
|
||||
|
||||
fn test_wyrand_int31() {
|
||||
max_u31 := 0x7FFFFFFF
|
||||
sign_mask := 0x80000000
|
||||
max_u31 := int(0x7FFFFFFF)
|
||||
sign_mask := int(0x80000000)
|
||||
for seed in seeds {
|
||||
mut rng := wyrand.WyRandRNG{}
|
||||
rng.seed(seed)
|
||||
|
|
|
@ -12,8 +12,8 @@ import v.errors
|
|||
const (
|
||||
max_nr_errors = 300
|
||||
match_exhaustive_cutoff_limit = 10
|
||||
enum_min = int(0x80000000)
|
||||
enum_max = 0x7FFFFFFF
|
||||
int_min = int(0x80000000)
|
||||
int_max = 0x7FFFFFFF
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -1682,7 +1682,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
|||
match field.expr as field_expr {
|
||||
ast.IntegerLiteral {
|
||||
val := field_expr.val.i64()
|
||||
if val < enum_min || val > enum_max {
|
||||
if val < int_min || val > int_max {
|
||||
c.error('enum value `$val` overflows int', field_expr.pos)
|
||||
} else if !decl.is_multi_allowed && int(val) in seen {
|
||||
c.error('enum value `$val` already exists', field_expr.pos)
|
||||
|
@ -1707,7 +1707,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
|||
} else {
|
||||
if seen.len > 0 {
|
||||
last := seen[seen.len - 1]
|
||||
if last == enum_max {
|
||||
if last == int_max {
|
||||
c.error('enum value overflows', field.pos)
|
||||
}
|
||||
seen << last + 1
|
||||
|
@ -1805,6 +1805,29 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
|||
right_type := assign_stmt.right_types[i]
|
||||
if is_decl {
|
||||
left_type = c.table.mktyp(right_type)
|
||||
if left_type == table.int_type {
|
||||
mut expr := right
|
||||
mut negative := false
|
||||
if right is ast.PrefixExpr {
|
||||
expr = right.right
|
||||
if right.op == .minus {
|
||||
negative = true
|
||||
}
|
||||
}
|
||||
if expr is ast.IntegerLiteral {
|
||||
mut is_large := false
|
||||
if expr.val.len > 8 {
|
||||
val := expr.val.i64()
|
||||
if (!negative && val > int_max) || (negative && -val < int_min) {
|
||||
is_large = true
|
||||
}
|
||||
}
|
||||
if is_large {
|
||||
c.error('overflow in implicit type `int`, use explicit type casting instead',
|
||||
expr.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
// we are unwrapping here instead if check_expr_opt_call currently
|
||||
if left_type.has_flag(.optional) {
|
||||
left_type = left_type.clear_flag(.optional)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
vlib/v/checker/tests/overflow_int_err.vv:4:8: error: overflow in implicit type `int`, use explicit type casting instead
|
||||
2 | a := -2147483648
|
||||
3 | b := 2147483647
|
||||
4 | c := -2147483649
|
||||
| ~~~~~~~~~~
|
||||
5 | d := 2147483648
|
||||
6 | println(a)
|
||||
vlib/v/checker/tests/overflow_int_err.vv:5:7: error: overflow in implicit type `int`, use explicit type casting instead
|
||||
3 | b := 2147483647
|
||||
4 | c := -2147483649
|
||||
5 | d := 2147483648
|
||||
| ~~~~~~~~~~
|
||||
6 | println(a)
|
||||
7 | println(b)
|
|
@ -0,0 +1,10 @@
|
|||
fn main() {
|
||||
a := -2147483648
|
||||
b := 2147483647
|
||||
c := -2147483649
|
||||
d := 2147483648
|
||||
println(a)
|
||||
println(b)
|
||||
println(c)
|
||||
println(d)
|
||||
}
|
Loading…
Reference in New Issue