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(x3) == 'int'
|
||||||
assert typeof(x4) == 'int'
|
assert typeof(x4) == 'int'
|
||||||
assert typeof(x5) == 'int'
|
assert typeof(x5) == 'int'
|
||||||
// integers are always 'int' by default
|
|
||||||
x6 := 989898932113111
|
|
||||||
x7 := u64(-321314588900011)
|
x7 := u64(-321314588900011)
|
||||||
assert typeof(x6) == 'int'
|
|
||||||
assert typeof(x7) == 'u64'
|
assert typeof(x7) == 'u64'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,8 +178,8 @@ fn test_mt19937_u64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_mt19937_int31() {
|
fn test_mt19937_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := mt19937.MT19937RNG{}
|
mut rng := mt19937.MT19937RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
|
|
|
@ -168,8 +168,8 @@ fn test_musl_u64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_musl_int31() {
|
fn test_musl_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := musl.MuslRNG{}
|
mut rng := musl.MuslRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
|
|
|
@ -169,8 +169,8 @@ fn test_pcg32_u64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_pcg32_int31() {
|
fn test_pcg32_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := pcg32.PCG32RNG{}
|
mut rng := pcg32.PCG32RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
|
|
|
@ -100,8 +100,8 @@ fn test_rand_i64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_rand_int31() {
|
fn test_rand_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for _ in 0 .. rnd_count {
|
for _ in 0 .. rnd_count {
|
||||||
value := rand.int31()
|
value := rand.int31()
|
||||||
assert value >= 0
|
assert value >= 0
|
||||||
|
|
|
@ -168,8 +168,8 @@ fn test_splitmix64_u64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_splitmix64_int31() {
|
fn test_splitmix64_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := splitmix64.SplitMix64RNG{}
|
mut rng := splitmix64.SplitMix64RNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
|
|
|
@ -237,8 +237,8 @@ fn test_sys_rng_i64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_sys_rng_int31() {
|
fn test_sys_rng_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
seed_data := [seed]
|
seed_data := [seed]
|
||||||
mut rng := sys.SysRNG{}
|
mut rng := sys.SysRNG{}
|
||||||
|
|
|
@ -168,8 +168,8 @@ fn test_wyrand_u64_in_range() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_wyrand_int31() {
|
fn test_wyrand_int31() {
|
||||||
max_u31 := 0x7FFFFFFF
|
max_u31 := int(0x7FFFFFFF)
|
||||||
sign_mask := 0x80000000
|
sign_mask := int(0x80000000)
|
||||||
for seed in seeds {
|
for seed in seeds {
|
||||||
mut rng := wyrand.WyRandRNG{}
|
mut rng := wyrand.WyRandRNG{}
|
||||||
rng.seed(seed)
|
rng.seed(seed)
|
||||||
|
|
|
@ -12,8 +12,8 @@ import v.errors
|
||||||
const (
|
const (
|
||||||
max_nr_errors = 300
|
max_nr_errors = 300
|
||||||
match_exhaustive_cutoff_limit = 10
|
match_exhaustive_cutoff_limit = 10
|
||||||
enum_min = int(0x80000000)
|
int_min = int(0x80000000)
|
||||||
enum_max = 0x7FFFFFFF
|
int_max = 0x7FFFFFFF
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1682,7 +1682,7 @@ pub fn (mut c Checker) enum_decl(decl ast.EnumDecl) {
|
||||||
match field.expr as field_expr {
|
match field.expr as field_expr {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
val := field_expr.val.i64()
|
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)
|
c.error('enum value `$val` overflows int', field_expr.pos)
|
||||||
} else if !decl.is_multi_allowed && int(val) in seen {
|
} else if !decl.is_multi_allowed && int(val) in seen {
|
||||||
c.error('enum value `$val` already exists', field_expr.pos)
|
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 {
|
} else {
|
||||||
if seen.len > 0 {
|
if seen.len > 0 {
|
||||||
last := seen[seen.len - 1]
|
last := seen[seen.len - 1]
|
||||||
if last == enum_max {
|
if last == int_max {
|
||||||
c.error('enum value overflows', field.pos)
|
c.error('enum value overflows', field.pos)
|
||||||
}
|
}
|
||||||
seen << last + 1
|
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]
|
right_type := assign_stmt.right_types[i]
|
||||||
if is_decl {
|
if is_decl {
|
||||||
left_type = c.table.mktyp(right_type)
|
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
|
// we are unwrapping here instead if check_expr_opt_call currently
|
||||||
if left_type.has_flag(.optional) {
|
if left_type.has_flag(.optional) {
|
||||||
left_type = left_type.clear_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