From 691e1b84c11d038060807f9c79107996ca2f19ae Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 23 Apr 2021 12:18:59 -0700 Subject: [PATCH] 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 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/walk/assign.go | 10 +++++++--- test/fixedbugs/issue45706.go | 9 +++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go index 3abf2a060c..6d697a53ae 100644 --- a/src/cmd/compile/internal/walk/assign.go +++ b/src/cmd/compile/internal/walk/assign.go @@ -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: diff --git a/test/fixedbugs/issue45706.go b/test/fixedbugs/issue45706.go index facf488b3d..6518dbf090 100644 --- a/test/fixedbugs/issue45706.go +++ b/test/fixedbugs/issue45706.go @@ -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 "" { + } +}