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:
Matthew Dempsky 2020-11-18 12:50:46 -08:00
parent 5b0ec1a6ac
commit 35693d037f
2 changed files with 34 additions and 0 deletions

View file

@ -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)

View 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 }