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.
This commit is contained in:
parent
6849499f56
commit
01ccaefe2f
2 changed files with 13 additions and 66 deletions
|
@ -90,73 +90,11 @@ func (c *codegen) getFuncNameFromDecl(pkgPath string, decl *ast.FuncDecl) string
|
||||||
// analyzeVoidCalls checks for functions that are not assigned
|
// analyzeVoidCalls checks for functions that are not assigned
|
||||||
// and therefore we need to cleanup the return value from the stack.
|
// and therefore we need to cleanup the return value from the stack.
|
||||||
func (c *funcScope) analyzeVoidCalls(node ast.Node) bool {
|
func (c *funcScope) analyzeVoidCalls(node ast.Node) bool {
|
||||||
switch n := node.(type) {
|
est, ok := node.(*ast.ExprStmt)
|
||||||
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)
|
|
||||||
if ok {
|
if ok {
|
||||||
c.voidCalls[ce] = false
|
ce, ok := est.X.(*ast.CallExpr)
|
||||||
}
|
|
||||||
case *ast.BinaryExpr:
|
|
||||||
return false
|
|
||||||
case *ast.RangeStmt:
|
|
||||||
ce, ok := n.X.(*ast.CallExpr)
|
|
||||||
if ok {
|
if ok {
|
||||||
c.voidCalls[ce] = false
|
c.voidCalls[ce] = true
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -86,6 +86,15 @@ func TestNotAssignedFunctionCall(t *testing.T) {
|
||||||
}`
|
}`
|
||||||
eval(t, src, big.NewInt(42))
|
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) {
|
func TestMultipleFunctionCalls(t *testing.T) {
|
||||||
|
|
Loading…
Reference in a new issue