]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: for loop init statement misanalyzed by escape analysis
authorDaniel Morsing <daniel.morsing@gmail.com>
Thu, 13 Feb 2014 19:04:43 +0000 (19:04 +0000)
committerDaniel Morsing <daniel.morsing@gmail.com>
Thu, 13 Feb 2014 19:04:43 +0000 (19:04 +0000)
Logically, the init statement is in the enclosing scopes loopdepth, not inside the for loop.

Fixes #7313.

LGTM=rsc
R=golang-codereviews, gobot, rsc
CC=golang-codereviews
https://golang.org/cl/62430043

src/cmd/gc/esc.c
test/escape2.go

index 99e4134a8cacd841bba9b5a359ec96137b1eef8f..c038dfc589ccd004e75ade5964dfd501aff73243 100644 (file)
@@ -423,6 +423,9 @@ esc(EscState *e, Node *n)
 
        lno = setlineno(n);
 
+       // ninit logically runs at a different loopdepth than the rest of the for loop.
+       esclist(e, n->ninit);
+
        if(n->op == OFOR || n->op == ORANGE)
                e->loopdepth++;
 
@@ -430,7 +433,6 @@ esc(EscState *e, Node *n)
        esc(e, n->right);
        esc(e, n->ntest);
        esc(e, n->nincr);
-       esclist(e, n->ninit);
        esclist(e, n->nbody);
        esclist(e, n->nelse);
        esclist(e, n->list);
index be89c2d84082b86e517e3a8ab9564b8122abf424..73342fd2bc6326cd32cd6b7bf23112134180016e 100644 (file)
@@ -1357,3 +1357,35 @@ func foo144() {
 //go:noescape
 
 func foo144b(*int)
+
+// issue 7313: for loop init should not be treated as "in loop"
+
+type List struct {
+       Next *List
+}
+
+func foo145(l List) { // ERROR "l does not escape"
+       var p *List
+       for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape"
+       }
+}
+
+func foo146(l List) { // ERROR "l does not escape"
+       var p *List
+       p = &l // ERROR "&l does not escape"
+       for ; p.Next != nil; p = p.Next {
+       }
+}
+
+func foo147(l List) { // ERROR "l does not escape"
+       var p *List
+       p = &l // ERROR "&l does not escape"
+       for p.Next != nil {
+               p = p.Next
+       }
+}
+
+func foo148(l List) { // ERROR " l does not escape"
+       for p := &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape"
+       }
+}