From 01ccaefe2f7db6d9d08401449ebe4d2ab51b2ed4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Oct 2020 10:43:45 +0300 Subject: [PATCH] compiler: refactor void calls processing Call result is not used only if it occurs inside a `ExprStmt`. Otherwise (`IfStmt`, `BinExpr`...) it is used. Fix #1495. --- pkg/compiler/func_scope.go | 70 ++---------------------------- pkg/compiler/function_call_test.go | 9 ++++ 2 files changed, 13 insertions(+), 66 deletions(-) diff --git a/pkg/compiler/func_scope.go b/pkg/compiler/func_scope.go index 0b72c0aed..f7923fe95 100644 --- a/pkg/compiler/func_scope.go +++ b/pkg/compiler/func_scope.go @@ -90,73 +90,11 @@ func (c *codegen) getFuncNameFromDecl(pkgPath string, decl *ast.FuncDecl) string // analyzeVoidCalls checks for functions that are not assigned // and therefore we need to cleanup the return value from the stack. func (c *funcScope) analyzeVoidCalls(node ast.Node) bool { - switch n := node.(type) { - case *ast.AssignStmt: - for i := 0; i < len(n.Rhs); i++ { - switch n.Rhs[i].(type) { - case *ast.CallExpr: - return false - } - } - case *ast.ReturnStmt: - if len(n.Results) > 0 { - switch n.Results[0].(type) { - case *ast.CallExpr: - return false - } - } - case *ast.TypeAssertExpr: - ce, ok := n.X.(*ast.CallExpr) + est, ok := node.(*ast.ExprStmt) + if ok { + ce, ok := est.X.(*ast.CallExpr) if ok { - c.voidCalls[ce] = false - } - case *ast.BinaryExpr: - return false - case *ast.RangeStmt: - ce, ok := n.X.(*ast.CallExpr) - if ok { - c.voidCalls[ce] = false - } - case *ast.UnaryExpr: - ce, ok := n.X.(*ast.CallExpr) - if ok { - c.voidCalls[ce] = false - } - case *ast.IfStmt: - // we can't just return `false`, because we still need to process body - ce, ok := n.Cond.(*ast.CallExpr) - if ok { - c.voidCalls[ce] = false - } - case *ast.SwitchStmt: - ce, ok := n.Tag.(*ast.CallExpr) - if ok { - c.voidCalls[ce] = false - } - case *ast.CaseClause: - for _, e := range n.List { - ce, ok := e.(*ast.CallExpr) - if ok { - c.voidCalls[ce] = false - } - } - case *ast.CallExpr: - _, ok := c.voidCalls[n] - if !ok { - c.voidCalls[n] = true - } - return false - case *ast.CompositeLit: - for _, e := range n.Elts { - switch val := e.(type) { - case *ast.CallExpr: // slice - c.voidCalls[val] = false - case *ast.KeyValueExpr: // struct and map - ce, ok := val.Value.(*ast.CallExpr) - if ok { - c.voidCalls[ce] = false - } - } + c.voidCalls[ce] = true } } return true diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index 1de9f3ae4..2f8d6ea01 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -86,6 +86,15 @@ func TestNotAssignedFunctionCall(t *testing.T) { }` eval(t, src, big.NewInt(42)) }) + t.Run("VarDecl", func(t *testing.T) { + src := `package foo + func foo() []int { return []int{1} } + func Main() int { + var x = foo() + return len(x) + }` + eval(t, src, big.NewInt(1)) + }) } func TestMultipleFunctionCalls(t *testing.T) {