1
0
mirror of https://github.com/golang/go synced 2024-07-03 08:51:14 +00:00

cmd/compile: generalize fix for lvalue-init evaluation

The previous fix to ensure early evaluation of lvalue-init statements
(CL 312632) added it after we'd already peeled away any array-OINDEX
expressions. But those might have init statements too, so we need to
do this earlier actually and perhaps more than once.

Longer term, lvalue expressions shouldn't have init statements anyway.
But rsc and I both spent a while looking into this earlier in the dev
cycle and couldn't come up with anything reasonable.

Fixes #45706.

Change-Id: I2d19c5ba421b3f019c62eec45774c84cf04b30ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/313011
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Matthew Dempsky 2021-04-23 12:18:59 -07:00
parent 768a39975d
commit 691e1b84c1
2 changed files with 16 additions and 3 deletions

View File

@ -322,6 +322,13 @@ func ascompatee(op ir.Op, nl, nr []ir.Node) []ir.Node {
// Save subexpressions needed on left side.
// Drill through non-dereferences.
for {
// If an expression has init statements, they must be evaluated
// before any of its saved sub-operands (#45706).
// TODO(mdempsky): Disallow init statements on lvalues.
init := ir.TakeInit(l)
walkStmtList(init)
early.Append(init...)
switch ll := l.(type) {
case *ir.IndexExpr:
if ll.X.Type().IsArray() {
@ -341,9 +348,6 @@ func ascompatee(op ir.Op, nl, nr []ir.Node) []ir.Node {
break
}
walkStmtList(l.Init())
early.Append(ir.TakeInit(l)...)
var name *ir.Name
switch l.Op() {
default:

View File

@ -14,3 +14,12 @@ func g() {
for i, *(arr[f()]) = range []int{} {
}
}
func h() {
var x int
var f func() int
var arr []int
var arr2 [][0]rune
for arr[x], arr2[arr[f()]][x] = range "" {
}
}