compiler: do not emit RET twice for nested BlockStmt
When function finishes with `*ast.BlockStmt`, last return in that block should be looked for.
This commit is contained in:
parent
6445e4be91
commit
1f238ce6fd
2 changed files with 11 additions and 5 deletions
|
@ -175,10 +175,16 @@ func (f funcUsage) funcUsed(name string) bool {
|
|||
}
|
||||
|
||||
// lastStmtIsReturn checks if last statement of the declaration was return statement..
|
||||
func lastStmtIsReturn(decl *ast.FuncDecl) (b bool) {
|
||||
if l := len(decl.Body.List); l != 0 {
|
||||
_, ok := decl.Body.List[l-1].(*ast.ReturnStmt)
|
||||
return ok
|
||||
func lastStmtIsReturn(body *ast.BlockStmt) (b bool) {
|
||||
if l := len(body.List); l != 0 {
|
||||
switch inner := body.List[l-1].(type) {
|
||||
case *ast.BlockStmt:
|
||||
return lastStmtIsReturn(inner)
|
||||
case *ast.ReturnStmt:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -440,7 +440,7 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl, pkg *types.
|
|||
// If we have reached the end of the function without encountering `return` statement,
|
||||
// we should clean alt.stack manually.
|
||||
// This can be the case with void and named-return functions.
|
||||
if !isInit && !isDeploy && !lastStmtIsReturn(decl) {
|
||||
if !isInit && !isDeploy && !lastStmtIsReturn(decl.Body) {
|
||||
c.saveSequencePoint(decl.Body)
|
||||
emit.Opcodes(c.prog.BinWriter, opcode.RET)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue