checker: prompt error on implicit int overflow by literal (#6410)

pull/6434/head
Henrixounez 2020-09-20 16:29:01 +02:00 committed by GitHub
parent 34884c1631
commit 5086fd537c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 65 additions and 21 deletions

View File

@ -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'
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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{}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,10 @@
fn main() {
a := -2147483648
b := 2147483647
c := -2147483649
d := 2147483648
println(a)
println(b)
println(c)
println(d)
}