checker: check div/mod by zero (#7256)

pull/7605/head
yuyi 2020-12-11 11:44:07 +08:00 committed by GitHub
parent 3eb1550b43
commit c4e76e6a59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 15 deletions

View File

@ -609,6 +609,27 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
return struct_init.typ
}
fn (mut c Checker) check_div_mod_by_zero(expr ast.Expr, op_kind token.Kind) {
match mut expr {
ast.FloatLiteral {
if expr.val.f64() == 0.0 {
oper := if op_kind == .div { 'division' } else { 'modulo' }
c.error('$oper by zero', expr.pos)
}
}
ast.IntegerLiteral {
if expr.val.int() == 0 {
oper := if op_kind == .div { 'division' } else { 'modulo' }
c.error('$oper by zero', expr.pos)
}
}
ast.CastExpr {
c.check_div_mod_by_zero(expr.expr, op_kind)
}
else {}
}
}
pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
// println('checker: infix expr(op $infix_expr.op.str())')
former_expected_type := c.expected_type
@ -757,21 +778,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
}
}
if infix_expr.op in [.div, .mod] {
match mut infix_expr.right {
ast.FloatLiteral {
if infix_expr.right.val.f64() == 0.0 {
oper := if infix_expr.op == .div { 'division' } else { 'modulo' }
c.error('$oper by zero', infix_expr.right.pos)
}
}
ast.IntegerLiteral {
if infix_expr.right.val.int() == 0 {
oper := if infix_expr.op == .div { 'division' } else { 'modulo' }
c.error('$oper by zero', infix_expr.right.pos)
}
}
else {}
}
c.check_div_mod_by_zero(infix_expr.right, infix_expr.op)
}
return_type = promoted_type
}

View File

@ -0,0 +1,40 @@
vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:2:21: error: division by zero
1 | fn main() {
2 | println(u64(1)/u64(0))
| ^
3 | println(u64(1)%u64(0))
4 |
vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:3:21: error: modulo by zero
1 | fn main() {
2 | println(u64(1)/u64(0))
3 | println(u64(1)%u64(0))
| ^
4 |
5 | println(u32(1)/u32(0x0))
vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:5:21: error: division by zero
3 | println(u64(1)%u64(0))
4 |
5 | println(u32(1)/u32(0x0))
| ~~~
6 | println(u32(1)%u32(0x0))
7 |
vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:6:21: error: modulo by zero
4 |
5 | println(u32(1)/u32(0x0))
6 | println(u32(1)%u32(0x0))
| ~~~
7 |
8 | println(u16(1)/u16(0b0))
vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:8:21: error: division by zero
6 | println(u32(1)%u32(0x0))
7 |
8 | println(u16(1)/u16(0b0))
| ~~~
9 | println(u16(1)%u16(0b0))
10 | }
vlib/v/checker/tests/div_mod_by_cast_zero_int_err.vv:9:21: error: modulo by zero
7 |
8 | println(u16(1)/u16(0b0))
9 | println(u16(1)%u16(0b0))
| ~~~
10 | }

View File

@ -0,0 +1,10 @@
fn main() {
println(u64(1)/u64(0))
println(u64(1)%u64(0))
println(u32(1)/u32(0x0))
println(u32(1)%u32(0x0))
println(u16(1)/u16(0b0))
println(u16(1)%u16(0b0))
}

View File

@ -0,0 +1,12 @@
vlib/v/checker/tests/division_by_cast_zero_float_err.vv:2:23: error: division by zero
1 | fn main() {
2 | println(f32(1.0)/f32(0.0))
| ~~~
3 | println(f64(1.0)/f64(0.0))
4 | }
vlib/v/checker/tests/division_by_cast_zero_float_err.vv:3:23: error: division by zero
1 | fn main() {
2 | println(f32(1.0)/f32(0.0))
3 | println(f64(1.0)/f64(0.0))
| ~~~
4 | }

View File

@ -0,0 +1,4 @@
fn main() {
println(f32(1.0)/f32(0.0))
println(f64(1.0)/f64(0.0))
}