From f12f871432ece2a940841e03877cbb1862d54b25 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 30 Nov 2021 18:03:21 +0300 Subject: [PATCH] compiler: use new defer stack for inlined functions, fix #2281 Inlined functions shouldn't care about outer scope defer statements, they can't. --- pkg/compiler/defer_test.go | 18 ++++++++++++++++++ pkg/compiler/inline.go | 4 ++++ 2 files changed, 22 insertions(+) diff --git a/pkg/compiler/defer_test.go b/pkg/compiler/defer_test.go index 5d6784da1..37e43c6d8 100644 --- a/pkg/compiler/defer_test.go +++ b/pkg/compiler/defer_test.go @@ -50,6 +50,24 @@ func TestDefer(t *testing.T) { func f() { a += 2 }` eval(t, src, big.NewInt(10)) }) + t.Run("DeferAfterInterop", func(t *testing.T) { + src := `package main + + import ( + "github.com/nspcc-dev/neo-go/pkg/interop/storage" + ) + + func Main() { + defer func() { + }() + storage.GetContext() + }` + vm := vmAndCompile(t, src) + err := vm.Run() + require.NoError(t, err) + require.Equal(t, 0, vm.Estack().Len(), "stack contains unexpected items") + }) + t.Run("MultipleDefers", func(t *testing.T) { src := `package main var a int diff --git a/pkg/compiler/inline.go b/pkg/compiler/inline.go index 31329ddae..702ef46e2 100644 --- a/pkg/compiler/inline.go +++ b/pkg/compiler/inline.go @@ -99,6 +99,8 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) { c.pkgInfoInline = append(c.pkgInfoInline, pkg) oldMap := c.importMap + oldDefers := c.scope.deferStack + c.scope.deferStack = nil c.fillImportMap(f.file, pkg.Pkg) ast.Inspect(f.decl, c.scope.analyzeVoidCalls) ast.Walk(c, f.decl.Body) @@ -107,6 +109,8 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) { emit.Opcodes(c.prog.BinWriter, opcode.DROP) } } + c.processDefers() + c.scope.deferStack = oldDefers c.importMap = oldMap c.pkgInfoInline = c.pkgInfoInline[:len(c.pkgInfoInline)-1] }