Commit 71282131 authored by Russ Cox's avatar Russ Cox

cmd/gc: fix escape analysis bug

The code assumed that the only choices were EscNone, EscScope, and EscHeap,
so that it makes sense to set EscScope only if the current setting is EscNone.
Now that we have the many variants of EscReturn, this logic is false, and it was
causing important EscScopes to be ignored in favor of EscReturn.

Fixes #4360.

R=ken2
CC=golang-dev, lvd
https://golang.org/cl/6816103
parent 1ebf2d85
...@@ -1005,8 +1005,8 @@ escwalk(EscState *e, int level, Node *dst, Node *src) ...@@ -1005,8 +1005,8 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
if((src->esc&EscMask) != EscReturn) if((src->esc&EscMask) != EscReturn)
src->esc = EscReturn; src->esc = EscReturn;
src->esc |= 1<<((dst->vargen-1) + EscBits); src->esc |= 1<<((dst->vargen-1) + EscBits);
goto recurse;
} }
goto recurse;
} }
} }
...@@ -1014,7 +1014,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src) ...@@ -1014,7 +1014,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
switch(src->op) { switch(src->op) {
case ONAME: case ONAME:
if(src->class == PPARAM && leaks && src->esc == EscNone) { if(src->class == PPARAM && leaks && src->esc != EscHeap) {
src->esc = EscScope; src->esc = EscScope;
if(debug['m']) if(debug['m'])
warnl(src->lineno, "leaking param: %hN", src); warnl(src->lineno, "leaking param: %hN", src);
......
...@@ -219,6 +219,8 @@ warnl(int line, char *fmt, ...) ...@@ -219,6 +219,8 @@ warnl(int line, char *fmt, ...)
va_start(arg, fmt); va_start(arg, fmt);
adderr(line, fmt, arg); adderr(line, fmt, arg);
va_end(arg); va_end(arg);
if(debug['m'])
flusherrors();
} }
void void
......
...@@ -117,3 +117,28 @@ func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaki ...@@ -117,3 +117,28 @@ func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaki
return p, q return p, q
} }
var global interface{}
type T1 struct {
X *int
}
type T2 struct {
Y *T1
}
func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
if p == nil {
k = T2{}
return
}
global = p // should make p leak always
return T2{p}
}
func f9() {
var j T1 // ERROR "moved to heap: j"
f8(&j) // ERROR "&j escapes to heap"
}
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