Commit ba97d52b authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: fix escape analysis bug with variable capture in loops.

Fixes #3975.

R=rsc, lvd
CC=golang-dev, remy
https://golang.org/cl/6475061
parent 3efc4821
...@@ -543,6 +543,7 @@ esc(EscState *e, Node *n) ...@@ -543,6 +543,7 @@ esc(EscState *e, Node *n)
continue; continue;
a = nod(OADDR, ll->n->closure, N); a = nod(OADDR, ll->n->closure, N);
a->lineno = ll->n->lineno; a->lineno = ll->n->lineno;
a->escloopdepth = e->loopdepth;
typecheck(&a, Erv); typecheck(&a, Erv);
escassign(e, n, a); escassign(e, n, a);
} }
......
...@@ -18,15 +18,15 @@ var allptr = make([]*int, 0, 100) ...@@ -18,15 +18,15 @@ var allptr = make([]*int, 0, 100)
func noalias(p, q *int, s string) { func noalias(p, q *int, s string) {
n := len(allptr) n := len(allptr)
*p = -(n+1) *p = -(n + 1)
*q = -(n+2) *q = -(n + 2)
allptr = allptr[0:n+2] allptr = allptr[0 : n+2]
allptr[n] = p allptr[n] = p
allptr[n+1] = q allptr[n+1] = q
n += 2 n += 2
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
if allptr[i] != nil && *allptr[i] != -(i+1) { if allptr[i] != nil && *allptr[i] != -(i+1) {
println("aliased pointers", -(i+1), *allptr[i], "after", s) println("aliased pointers", -(i + 1), *allptr[i], "after", s)
allptr[i] = nil allptr[i] = nil
bad = true bad = true
} }
...@@ -141,15 +141,27 @@ func for_escapes2(x int, y int) (*int, *int) { ...@@ -141,15 +141,27 @@ func for_escapes2(x int, y int) (*int, *int) {
return p[0], p[1] return p[0], p[1]
} }
func for_escapes3(x int, y int) (*int, *int) {
var f [2]func() *int
n := 0
for i := x; n < 2; i = y {
p := new(int)
*p = i
f[n] = func() *int { return p }
n++
}
return f[0](), f[1]()
}
func out_escapes(i int) (x int, p *int) { func out_escapes(i int) (x int, p *int) {
x = i x = i
p = &x // ERROR "address of out parameter" p = &x // ERROR "address of out parameter"
return return
} }
func out_escapes_2(i int) (x int, p *int) { func out_escapes_2(i int) (x int, p *int) {
x = i x = i
return x, &x // ERROR "address of out parameter" return x, &x // ERROR "address of out parameter"
} }
func defer1(i int) (x int) { func defer1(i int) (x int) {
...@@ -187,6 +199,9 @@ func main() { ...@@ -187,6 +199,9 @@ func main() {
p, q = for_escapes2(103, 104) p, q = for_escapes2(103, 104)
chkalias(p, q, 103, "for_escapes2") chkalias(p, q, 103, "for_escapes2")
p, q = for_escapes3(105, 106)
chk(p, q, 105, "for_escapes3")
_, p = out_escapes(15) _, p = out_escapes(15)
_, q = out_escapes(16) _, q = out_escapes(16)
chk(p, q, 15, "out_escapes") chk(p, q, 15, "out_escapes")
......
...@@ -540,6 +540,19 @@ func foo74() { ...@@ -540,6 +540,19 @@ func foo74() {
} }
} }
// issue 3975
func foo74b() {
var array [3]func()
s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape"
for i, v := range s {
vv := v // ERROR "moved to heap: vv"
// actually just escapes its scope
array[i] = func() { // ERROR "func literal escapes to heap"
println(vv) // ERROR "&vv escapes to heap"
}
}
}
func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y" func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y"
return y return y
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment