summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Morsing <daniel.morsing@gmail.com>2014-02-13 19:04:43 +0000
committerDaniel Morsing <daniel.morsing@gmail.com>2014-02-13 19:04:43 +0000
commit0d4bf7eff89c6027adf6a408ca9481885305d178 (patch)
tree107f880028a2b15d7fcb593f55ec878a4b988048
parente08f64f3a4142e6066b4b015d82744e0a9b030fd (diff)
downloadgo-0d4bf7eff89c6027adf6a408ca9481885305d178.tar.gz
cmd/gc: for loop init statement misanalyzed by escape analysis
Logically, the init statement is in the enclosing scopes loopdepth, not inside the for loop. Fixes issue 7313. LGTM=rsc R=golang-codereviews, gobot, rsc CC=golang-codereviews https://codereview.appspot.com/62430043
-rw-r--r--src/cmd/gc/esc.c4
-rw-r--r--test/escape2.go32
2 files changed, 35 insertions, 1 deletions
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 99e4134a8..c038dfc58 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -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);
diff --git a/test/escape2.go b/test/escape2.go
index be89c2d84..73342fd2b 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -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"
+ }
+}