From a8f07310e3a08910dde2b7e9550848ec400753ad Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20M=C3=B6hrmann?= Date: Mon, 19 Dec 2016 00:06:46 +0100 Subject: [PATCH] cmd/compile: fix assignment order in string range loop MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Fixes #18376. Change-Id: I4fe24f479311cd4cd1bdad9a966b681e50e3d500 Reviewed-on: https://go-review.googlesource.com/35955 Reviewed-by: Keith Randall Run-TryBot: Martin Möhrmann TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/range.go | 31 ++++++++++++++++++++-------- test/range.go | 20 ++++++++++++++++++ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go index 99ecdd3cc5..d1ac5780a0 100644 --- a/src/cmd/compile/internal/gc/range.go +++ b/src/cmd/compile/internal/gc/range.go @@ -156,6 +156,10 @@ func walkrange(n *Node) { v2 = n.List.Second() } + if v1 == nil && v2 != nil { + Fatalf("walkrange: v2 != nil while v1 == nil") + } + // n.List has no meaning anymore, clear it // to avoid erroneous processing by racewalk. n.List.Set(nil) @@ -290,14 +294,14 @@ func walkrange(n *Node) { // // ha := a // for hv1 := 0; hv1 < len(ha); { - // v1 = hv1 + // hv1t := hv1 // hv2 := rune(ha[hv1]) // if hv2 < utf8.RuneSelf { // hv1++ // } else { // hv2, hv1 = decoderune(ha, hv1) // } - // v2 = hv2 + // v1, v2 = hv1t, hv2 // // original body // } @@ -305,6 +309,7 @@ func walkrange(n *Node) { ha := a hv1 := temp(Types[TINT]) + hv1t := temp(Types[TINT]) hv2 := temp(runetype) // hv1 := 0 @@ -314,18 +319,18 @@ func walkrange(n *Node) { n.Left = nod(OLT, hv1, nod(OLEN, ha, nil)) if v1 != nil { - // v1 = hv1 - body = append(body, nod(OAS, v1, hv1)) + // hv1t = hv1 + body = append(body, nod(OAS, hv1t, hv1)) } - // hv2 := ha[hv1] + // hv2 := rune(ha[hv1]) nind := nod(OINDEX, ha, hv1) nind.Bounded = true body = append(body, nod(OAS, hv2, conv(nind, runetype))) // if hv2 < utf8.RuneSelf nif := nod(OIF, nil, nil) - nif.Left = nod(OLT, nind, nodintconst(utf8.RuneSelf)) + nif.Left = nod(OLT, hv2, nodintconst(utf8.RuneSelf)) // hv1++ nif.Nbody.Set1(nod(OAS, hv1, nod(OADD, hv1, nodintconst(1)))) @@ -341,9 +346,17 @@ func walkrange(n *Node) { body = append(body, nif) - if v2 != nil { - // v2 = hv2 - body = append(body, nod(OAS, v2, hv2)) + if v1 != nil { + if v2 != nil { + // v1, v2 = hv1t, hv2 + a := nod(OAS2, nil, nil) + a.List.Set2(v1, v2) + a.Rlist.Set2(hv1t, hv2) + body = append(body, a) + } else { + // v1 = hv1t + body = append(body, nod(OAS, v1, hv1t)) + } } } diff --git a/test/range.go b/test/range.go index bae7a1c3c9..afdac57fa3 100644 --- a/test/range.go +++ b/test/range.go @@ -277,6 +277,26 @@ func teststring() { println("wrong sum ranging over makestring", s) panic("fail") } + + x := []rune{'a', 'b'} + i := 1 + for i, x[i] = range "c" { + break + } + if i != 0 || x[0] != 'a' || x[1] != 'c' { + println("wrong parallel assignment", i, x[0], x[1]) + panic("fail") + } + + y := []int{1, 2, 3} + r := rune(1) + for y[r], r = range "\x02" { + break + } + if r != 2 || y[0] != 1 || y[1] != 0 || y[2] != 3 { + println("wrong parallel assignment", r, y[0], y[1], y[2]) + panic("fail") + } } func teststring1() { -- 2.50.0