]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: fix escape analysis bug
authorRuss Cox <rsc@golang.org>
Wed, 7 Nov 2012 20:15:21 +0000 (15:15 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 7 Nov 2012 20:15:21 +0000 (15:15 -0500)
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

src/cmd/gc/esc.c
src/cmd/gc/subr.c
test/escape5.go

index f789386bc92ea4642d9d974fd5a6f81d68f3565f..f067cc5305371510049658d39461603695aea2cb 100644 (file)
@@ -1005,8 +1005,8 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
                                if((src->esc&EscMask) != EscReturn)
                                        src->esc = EscReturn;
                                src->esc |= 1<<((dst->vargen-1) + EscBits);
+                               goto recurse;
                        }
-                       goto recurse;
                }
        }
 
@@ -1014,7 +1014,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
 
        switch(src->op) {
        case ONAME:
-               if(src->class == PPARAM && leaks && src->esc == EscNone) {
+               if(src->class == PPARAM && leaks && src->esc != EscHeap) {
                        src->esc = EscScope;
                        if(debug['m'])
                                warnl(src->lineno, "leaking param: %hN", src);
index 142921153db3f93f51237495455e666daea8a5f5..71417bb0a0747298c194034ba17d32a7674c1e0f 100644 (file)
@@ -219,6 +219,8 @@ warnl(int line, char *fmt, ...)
        va_start(arg, fmt);
        adderr(line, fmt, arg);
        va_end(arg);
+       if(debug['m'])
+               flusherrors();
 }
 
 void
index 22c324f902fc4cb3b29cb626539908c7b05f47c2..6b327fe9e31ea997395f1538e265c04419435114 100644 (file)
@@ -117,3 +117,28 @@ func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaki
        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"
+}