forked from TrueCloudLab/neoneo-go
compiler: inline expressions with type conversions, fix #1879
Don't count `string(data)` or `[]byte(data)` as function calls.
This commit is contained in:
parent
6b3afe9131
commit
1d6d7206e9
4 changed files with 48 additions and 9 deletions
|
@ -869,12 +869,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
|
|||
|
||||
switch fun := n.Fun.(type) {
|
||||
case *ast.Ident:
|
||||
var pkgName string
|
||||
if len(c.pkgInfoInline) != 0 {
|
||||
pkgName = c.pkgInfoInline[len(c.pkgInfoInline)-1].Pkg.Path()
|
||||
}
|
||||
f, ok = c.funcs[c.getIdentName(pkgName, fun.Name)]
|
||||
|
||||
f, ok = c.getFuncFromIdent(fun)
|
||||
isBuiltin = isGoBuiltin(fun.Name)
|
||||
if !ok && !isBuiltin {
|
||||
name = fun.Name
|
||||
|
@ -1956,6 +1951,16 @@ func (c *codegen) newFunc(decl *ast.FuncDecl) *funcScope {
|
|||
return f
|
||||
}
|
||||
|
||||
func (c *codegen) getFuncFromIdent(fun *ast.Ident) (*funcScope, bool) {
|
||||
var pkgName string
|
||||
if len(c.pkgInfoInline) != 0 {
|
||||
pkgName = c.pkgInfoInline[len(c.pkgInfoInline)-1].Pkg.Path()
|
||||
}
|
||||
|
||||
f, ok := c.funcs[c.getIdentName(pkgName, fun.Name)]
|
||||
return f, ok
|
||||
}
|
||||
|
||||
// getFuncNameFromSelector returns fully-qualified function name from the selector expression.
|
||||
// Second return value is true iff this was a method call, not foreign package call.
|
||||
func (c *codegen) getFuncNameFromSelector(e *ast.SelectorExpr) (string, bool) {
|
||||
|
|
|
@ -140,9 +140,22 @@ func (c *codegen) processNotify(f *funcScope, args []ast.Expr) {
|
|||
func (c *codegen) hasCalls(expr ast.Expr) bool {
|
||||
var has bool
|
||||
ast.Inspect(expr, func(n ast.Node) bool {
|
||||
_, ok := n.(*ast.CallExpr)
|
||||
if ok {
|
||||
has = true
|
||||
ce, ok := n.(*ast.CallExpr)
|
||||
if !has && ok {
|
||||
isFunc := true
|
||||
fun, ok := ce.Fun.(*ast.Ident)
|
||||
if ok {
|
||||
_, isFunc = c.getFuncFromIdent(fun)
|
||||
} else {
|
||||
var sel *ast.SelectorExpr
|
||||
sel, ok = ce.Fun.(*ast.SelectorExpr)
|
||||
if ok {
|
||||
name, _ := c.getFuncNameFromSelector(sel)
|
||||
_, isFunc = c.funcs[name]
|
||||
fun = sel.Sel
|
||||
}
|
||||
}
|
||||
has = isFunc || fun.Obj != nil && (fun.Obj.Kind == ast.Var || fun.Obj.Kind == ast.Fun)
|
||||
}
|
||||
return !has
|
||||
})
|
||||
|
|
|
@ -48,6 +48,8 @@ func checkCallCount(t *testing.T, src string, expectedCall, expectedInitSlot, ex
|
|||
func TestInline(t *testing.T) {
|
||||
srcTmpl := `package foo
|
||||
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline"
|
||||
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/foo"
|
||||
var _ = foo.Dummy
|
||||
type pair struct { a, b int }
|
||||
type triple struct {
|
||||
a int
|
||||
|
@ -157,6 +159,22 @@ func TestInline(t *testing.T) {
|
|||
checkCallCount(t, src, 0, 1, 2)
|
||||
eval(t, src, big.NewInt(7))
|
||||
})
|
||||
t.Run("foreign package call", func(t *testing.T) {
|
||||
src := fmt.Sprintf(srcTmpl, `return inline.Sum(foo.Bar(), foo.Dummy+1)`)
|
||||
checkCallCount(t, src, 1, 1, 1)
|
||||
eval(t, src, big.NewInt(3))
|
||||
})
|
||||
}
|
||||
|
||||
func TestIssue1879(t *testing.T) {
|
||||
src := `package foo
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
func Main() int {
|
||||
data := "main is called"
|
||||
runtime.Log("log " + string(data))
|
||||
return 42
|
||||
}`
|
||||
checkCallCount(t, src, 0, 1, 1)
|
||||
}
|
||||
|
||||
func TestInlineInLoop(t *testing.T) {
|
||||
|
|
3
pkg/compiler/testdata/foo/foo.go
vendored
3
pkg/compiler/testdata/foo/foo.go
vendored
|
@ -5,6 +5,9 @@ func NewBar() int {
|
|||
return 10
|
||||
}
|
||||
|
||||
// Dummy is dummy constant.
|
||||
var Dummy = 1
|
||||
|
||||
// Foo is a type.
|
||||
type Foo struct{}
|
||||
|
||||
|
|
Loading…
Reference in a new issue