mirror of
https://github.com/golang/go
synced 2024-11-26 07:38:00 -07:00
cmd/compile: fix miscompilation during inlining
When inlining a function call expression, it's possible that the function callee subexpression has side effects that need to be preserved. This used to not be an issue, because inlining wouldn't recognize these as inlinable anyway. But golang.org/cl/266199 extended the inlining logic to recognize more cases, but did not notice that the actual inlining code was discarding side effects. Issue identified by danscales@. Fixes #42703. Change-Id: I95f8fc076b6ca4e9362e80ec26dad9d87a5bc44a Reviewed-on: https://go-review.googlesource.com/c/go/+/271219 Reviewed-by: Dan Scales <danscales@google.com> Trust: Dan Scales <danscales@google.com> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
5b0ec1a6ac
commit
35693d037f
@ -963,6 +963,21 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||
|
||||
ninit := n.Ninit
|
||||
|
||||
// For normal function calls, the function callee expression
|
||||
// may contain side effects (e.g., added by addinit during
|
||||
// inlconv2expr or inlconv2list). Make sure to preserve these,
|
||||
// if necessary (#42703).
|
||||
if n.Op == OCALLFUNC {
|
||||
callee := n.Left
|
||||
for callee.Op == OCONVNOP {
|
||||
ninit.AppendNodes(&callee.Ninit)
|
||||
callee = callee.Left
|
||||
}
|
||||
if callee.Op != ONAME && callee.Op != OCLOSURE {
|
||||
Fatalf("unexpected callee expression: %v", callee)
|
||||
}
|
||||
}
|
||||
|
||||
// Make temp names to use instead of the originals.
|
||||
inlvars := make(map[*Node]*Node)
|
||||
|
||||
|
19
test/fixedbugs/issue42703.go
Normal file
19
test/fixedbugs/issue42703.go
Normal file
@ -0,0 +1,19 @@
|
||||
// run
|
||||
|
||||
// Copyright 2020 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 main
|
||||
|
||||
var ok [2]bool
|
||||
|
||||
func main() {
|
||||
f()()
|
||||
if !ok[0] || !ok[1] {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
||||
|
||||
func f() func() { ok[0] = true; return g }
|
||||
func g() { ok[1] = true }
|
Loading…
Reference in New Issue
Block a user