compiler: do not DROP unary expression value inside IF stmt

We dropped values from such calls because they where marked as unused
(consequently, were followed by DROP instructions). Example:

if !foo() {    <--- panic here
    ...
}

This commit prevents the following runtime error during script execution:
```
"error encountered at instruction ** (NOT): runtime error: invalid memory address or nil pointer dereference"

```
This commit is contained in:
Anna Shaleva 2020-10-12 16:46:01 +03:00
parent fe1f0a7245
commit dbce3c9a19
2 changed files with 34 additions and 0 deletions

View file

@ -112,6 +112,11 @@ func (c *funcScope) analyzeVoidCalls(node ast.Node) bool {
if ok { if ok {
c.voidCalls[ce] = false c.voidCalls[ce] = false
} }
case *ast.UnaryExpr:
ce, ok := n.X.(*ast.CallExpr)
if ok {
c.voidCalls[ce] = false
}
case *ast.IfStmt: case *ast.IfStmt:
// we can't just return `false`, because we still need to process body // we can't just return `false`, because we still need to process body
ce, ok := n.Cond.(*ast.CallExpr) ce, ok := n.Cond.(*ast.CallExpr)

View file

@ -121,3 +121,32 @@ func TestInitIF(t *testing.T) {
}) })
}) })
} }
func TestCallExpIF(t *testing.T) {
t.Run("Call", func(t *testing.T) {
src := `package foo
func someFunc() bool {
return true
}
func Main() int {
if someFunc() {
return 5
}
return 6
}`
eval(t, src, big.NewInt(5))
})
t.Run("CallWithUnaryExpression", func(t *testing.T) {
src := `package foo
func someFunc() bool {
return false
}
func Main() int {
if !someFunc() {
return 5
}
return 6
}`
eval(t, src, big.NewInt(5))
})
}