mirror of
https://github.com/golang/go
synced 2024-11-26 04:07:59 -07:00
cmd/compile: declare inlined result params early for empty returns
The code for delayed declaration of inlined result parameters only handles non-empty return statements. This is generally okay, because we already early declare if there are any (non-blank) named result parameters. But if a user writes a function with only blank result parameters and with exactly one return statement, which is empty, then they could end up hitting the dreaded "Value live at entry" ICE. This CL fixes the issue by ensuring we always early declare inlined result parameters if there are any empty return statements. Fixes #44355. Change-Id: I315f3853be436452883b1ce31da1bdffdf24d506 Reviewed-on: https://go-review.googlesource.com/c/go/+/293293 TryBot-Result: Go Bot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
526ee96f49
commit
6c3bcda866
@ -852,17 +852,25 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
|
||||
}
|
||||
}
|
||||
|
||||
// We can delay declaring+initializing result parameters if:
|
||||
// (1) there's exactly one "return" statement in the inlined function;
|
||||
// (2) it's not an empty return statement (#44355); and
|
||||
// (3) the result parameters aren't named.
|
||||
delayretvars := true
|
||||
|
||||
nreturns := 0
|
||||
ir.VisitList(ir.Nodes(fn.Inl.Body), func(n ir.Node) {
|
||||
if n != nil && n.Op() == ir.ORETURN {
|
||||
if n, ok := n.(*ir.ReturnStmt); ok {
|
||||
nreturns++
|
||||
if len(n.Results) == 0 {
|
||||
delayretvars = false // empty return statement (case 2)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// We can delay declaring+initializing result parameters if:
|
||||
// (1) there's only one "return" statement in the inlined
|
||||
// function, and (2) the result parameters aren't named.
|
||||
delayretvars := nreturns == 1
|
||||
if nreturns != 1 {
|
||||
delayretvars = false // not exactly one return statement (case 1)
|
||||
}
|
||||
|
||||
// temporaries for return values.
|
||||
var retvars []ir.Node
|
||||
@ -873,7 +881,7 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
|
||||
m = inlvar(n)
|
||||
m = typecheck.Expr(m).(*ir.Name)
|
||||
inlvars[n] = m
|
||||
delayretvars = false // found a named result parameter
|
||||
delayretvars = false // found a named result parameter (case 3)
|
||||
} else {
|
||||
// anonymous return values, synthesize names for use in assignment that replaces return
|
||||
m = retvar(t, i)
|
||||
|
7
test/fixedbugs/issue44355.dir/a.go
Normal file
7
test/fixedbugs/issue44355.dir/a.go
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved. Use of this
|
||||
// source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
package a
|
||||
|
||||
func F() (_ *int) { return nil }
|
9
test/fixedbugs/issue44355.dir/b.go
Normal file
9
test/fixedbugs/issue44355.dir/b.go
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved. Use of this
|
||||
// source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
package b
|
||||
|
||||
import "./a"
|
||||
|
||||
var _ = a.F()
|
7
test/fixedbugs/issue44355.go
Normal file
7
test/fixedbugs/issue44355.go
Normal file
@ -0,0 +1,7 @@
|
||||
// compiledir
|
||||
|
||||
// Copyright 2021 The Go Authors. All rights reserved. Use of this
|
||||
// source code is governed by a BSD-style license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
package ignored
|
Loading…
Reference in New Issue
Block a user