]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: generalize fix for lvalue-init evaluation
authorMatthew Dempsky <mdempsky@google.com>
Fri, 23 Apr 2021 19:18:59 +0000 (12:18 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 23 Apr 2021 20:57:54 +0000 (20:57 +0000)
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>
src/cmd/compile/internal/walk/assign.go
test/fixedbugs/issue45706.go

index 3abf2a060c8a03b672a4a3b3fc66a3225e392f04..6d697a53ae3aaa14442a21f9f4e15880bbfe75c2 100644 (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:
index facf488b3de9894eb6e79dcbee934a1e18edcc99..6518dbf090f62c48c38fb2deb41b406d94c41253 100644 (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 "" {
+       }
+}