]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix assignment order in string range loop
authorMartin Möhrmann <moehrmann@google.com>
Sun, 18 Dec 2016 23:06:46 +0000 (00:06 +0100)
committerMartin Möhrmann <moehrmann@google.com>
Tue, 28 Feb 2017 08:23:52 +0000 (08:23 +0000)
Fixes #18376.

Change-Id: I4fe24f479311cd4cd1bdad9a966b681e50e3d500
Reviewed-on: https://go-review.googlesource.com/35955
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Martin Möhrmann <moehrmann@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/range.go
test/range.go

index 99ecdd3cc59f1d22ee39e955140fca09f65b8530..d1ac5780a0480edd402221ef9e9b88bf1afecb04 100644 (file)
@@ -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))
+                       }
                }
        }
 
index bae7a1c3c9dea2a6916b5469039ee4859de707a5..afdac57fa357fae4e45fd8f0ad8fef7c6ed484b3 100644 (file)
@@ -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() {