aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-02-17 17:49:40 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-02-25 19:57:49 +0000
commit6c3bcda866582b51842d71576a11c0fe1b647a22 (patch)
tree77bfaf1a42dfa7d91481989c4bcaad5880a2cea7
parent526ee96f4992ff3a1e1c219fe8dc9870098bacba (diff)
downloadgo-6c3bcda866582b51842d71576a11c0fe1b647a22.tar.gz
go-6c3bcda866582b51842d71576a11c0fe1b647a22.zip
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>
-rw-r--r--src/cmd/compile/internal/inline/inl.go20
-rw-r--r--test/fixedbugs/issue44355.dir/a.go7
-rw-r--r--test/fixedbugs/issue44355.dir/b.go9
-rw-r--r--test/fixedbugs/issue44355.go7
4 files changed, 37 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go
index fe6509e4c9..1703be74e9 100644
--- a/src/cmd/compile/internal/inline/inl.go
+++ b/src/cmd/compile/internal/inline/inl.go
@@ -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)
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