mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parser: advanced division by zero check (#5629)
This commit is contained in:
parent
1efbb83060
commit
f03688e443
@ -547,14 +547,6 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||
}
|
||||
}
|
||||
}
|
||||
if infix_expr.op in [.div, .mod] {
|
||||
if (infix_expr.right is ast.IntegerLiteral &&
|
||||
infix_expr.right.str() == '0') ||
|
||||
(infix_expr.right is ast.FloatLiteral && infix_expr.right.str().f64() == 0.0) {
|
||||
oper := if infix_expr.op == .div { 'division' } else { 'modulo' }
|
||||
c.error('$oper by zero', right_pos)
|
||||
}
|
||||
}
|
||||
return_type = promoted_type
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,28 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
p.expecting_type = true
|
||||
}
|
||||
right = p.expr(precedence)
|
||||
|
||||
if op in [.div, .mod] {
|
||||
oper := if op == .div { 'division' } else { 'modulo' }
|
||||
match right {
|
||||
ast.FloatLiteral {
|
||||
if it.val.f64() == 0.0 {
|
||||
p.error_with_pos('$oper by zero', right.pos)
|
||||
}
|
||||
}
|
||||
ast.Ident {
|
||||
if p.is_var_zero(right.name) {
|
||||
p.error_with_pos('$oper by zero', right.pos)
|
||||
}
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
if it.val.int() == 0 {
|
||||
p.error_with_pos('$oper by zero', right.pos)
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
return ast.InfixExpr{
|
||||
left: left
|
||||
right: right
|
||||
@ -247,6 +269,26 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) is_var_zero(name string) bool {
|
||||
var := p.scope.find_var(name) or {
|
||||
return false
|
||||
}
|
||||
match var.expr {
|
||||
ast.FloatLiteral {
|
||||
if it.val.f64() == 0.0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
ast.IntegerLiteral {
|
||||
if it.val.int() == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fn (mut p Parser) prefix_expr() ast.PrefixExpr {
|
||||
pos := p.tok.position()
|
||||
op := p.tok.kind
|
||||
|
5
vlib/v/parser/tests/division_by_zero_0b0_err.out
Normal file
5
vlib/v/parser/tests/division_by_zero_0b0_err.out
Normal file
@ -0,0 +1,5 @@
|
||||
vlib/v/parser/tests/division_by_zero_0b0_err.v:2:12: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | println(1/0b0)
|
||||
| ~~~
|
||||
3 | }
|
3
vlib/v/parser/tests/division_by_zero_0b0_err.vv
Normal file
3
vlib/v/parser/tests/division_by_zero_0b0_err.vv
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println(1/0b0)
|
||||
}
|
5
vlib/v/parser/tests/division_by_zero_0x0_err.out
Normal file
5
vlib/v/parser/tests/division_by_zero_0x0_err.out
Normal file
@ -0,0 +1,5 @@
|
||||
vlib/v/parser/tests/division_by_zero_0x0_err.v:2:12: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | println(1/0x0)
|
||||
| ~~~
|
||||
3 | }
|
3
vlib/v/parser/tests/division_by_zero_0x0_err.vv
Normal file
3
vlib/v/parser/tests/division_by_zero_0x0_err.vv
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println(1/0x0)
|
||||
}
|
6
vlib/v/parser/tests/division_by_zero_0x0_var_err.out
Normal file
6
vlib/v/parser/tests/division_by_zero_0x0_var_err.out
Normal file
@ -0,0 +1,6 @@
|
||||
vlib/v/parser/tests/division_by_zero_0x0_var_err.v:3:12: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | a := 0x0
|
||||
3 | println(1/a)
|
||||
| ^
|
||||
4 | }
|
4
vlib/v/parser/tests/division_by_zero_0x0_var_err.vv
Normal file
4
vlib/v/parser/tests/division_by_zero_0x0_var_err.vv
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
a := 0x0
|
||||
println(1/a)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/division_by_zero_float_err.v:2:14: error: division by zero
|
||||
vlib/v/parser/tests/division_by_zero_float_err.v:2:14: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | println(1.0/0.0)
|
||||
| ~~~
|
6
vlib/v/parser/tests/division_by_zero_float_var_err.out
Normal file
6
vlib/v/parser/tests/division_by_zero_float_var_err.out
Normal file
@ -0,0 +1,6 @@
|
||||
vlib/v/parser/tests/division_by_zero_float_var_err.v:3:14: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | a := 0.0
|
||||
3 | println(1.0/a)
|
||||
| ^
|
||||
4 | }
|
4
vlib/v/parser/tests/division_by_zero_float_var_err.vv
Normal file
4
vlib/v/parser/tests/division_by_zero_float_var_err.vv
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
a := 0.0
|
||||
println(1.0/a)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
vlib/v/checker/tests/division_by_zero_int_err.v:2:12: error: division by zero
|
||||
vlib/v/parser/tests/division_by_zero_int_err.v:2:12: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | println(1/0)
|
||||
| ^
|
6
vlib/v/parser/tests/division_by_zero_int_var_err.out
Normal file
6
vlib/v/parser/tests/division_by_zero_int_var_err.out
Normal file
@ -0,0 +1,6 @@
|
||||
vlib/v/parser/tests/division_by_zero_int_var_err.v:3:12: error: division by zero
|
||||
1 | fn main() {
|
||||
2 | a := 0
|
||||
3 | println(1/a)
|
||||
| ^
|
||||
4 | }
|
4
vlib/v/parser/tests/division_by_zero_int_var_err.vv
Normal file
4
vlib/v/parser/tests/division_by_zero_int_var_err.vv
Normal file
@ -0,0 +1,4 @@
|
||||
fn main() {
|
||||
a := 0
|
||||
println(1/a)
|
||||
}
|
Loading…
Reference in New Issue
Block a user