From ddeae6b248e5130fe634047c3ca5964f5fa4e3dd Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Wed, 17 Feb 2021 17:49:40 -0800 Subject: [release-branch.go1.16] 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 #44358. Change-Id: I315f3853be436452883b1ce31da1bdffdf24d506 Reviewed-on: https://go-review.googlesource.com/c/go/+/293293 TryBot-Result: Go Bot Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le Reviewed-by: David Chase Reviewed-on: https://go-review.googlesource.com/c/go/+/296569 --- src/cmd/compile/internal/gc/inl.go | 18 +++++++++++++----- test/fixedbugs/issue44355.dir/a.go | 7 +++++++ test/fixedbugs/issue44355.dir/b.go | 9 +++++++++ test/fixedbugs/issue44355.go | 7 +++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 test/fixedbugs/issue44355.dir/a.go create mode 100644 test/fixedbugs/issue44355.dir/b.go create mode 100644 test/fixedbugs/issue44355.go diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 600d12b59b..a8cc01082a 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -1053,18 +1053,26 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { } } + // 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 inspectList(asNodes(fn.Func.Inl.Body), func(n *Node) bool { if n != nil && n.Op == ORETURN { nreturns++ + if n.List.Len() == 0 { + delayretvars = false // empty return statement (case 2) + } } return true }) - // 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 []*Node @@ -1074,7 +1082,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { m = inlvar(n) m = typecheck(m, ctxExpr) 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) diff --git a/test/fixedbugs/issue44355.dir/a.go b/test/fixedbugs/issue44355.dir/a.go new file mode 100644 index 0000000000..0f63c6fd98 --- /dev/null +++ b/test/fixedbugs/issue44355.dir/a.go @@ -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 } diff --git a/test/fixedbugs/issue44355.dir/b.go b/test/fixedbugs/issue44355.dir/b.go new file mode 100644 index 0000000000..09d5bde887 --- /dev/null +++ b/test/fixedbugs/issue44355.dir/b.go @@ -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() diff --git a/test/fixedbugs/issue44355.go b/test/fixedbugs/issue44355.go new file mode 100644 index 0000000000..d406838588 --- /dev/null +++ b/test/fixedbugs/issue44355.go @@ -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 -- cgit v1.2.3-54-g00ecf