]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/gc: fix escape analysis for &x inside switch x := v.(type)
authorRuss Cox <rsc@golang.org>
Wed, 11 Jun 2014 15:48:47 +0000 (11:48 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 11 Jun 2014 15:48:47 +0000 (11:48 -0400)
The analysis for &x was using the loop depth on x set
during x's declaration. A type switch creates a list of
implicit declarations that were not getting initialized
with loop depths.

Fixes #8176.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/108860043

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

index a75517813d554237f189dd2fb9c3287271c93d8c..9d7dc1149c718bcdb63a21b9a3d23e2e4bfc47aa 100644 (file)
@@ -442,6 +442,18 @@ esc(EscState *e, Node *n, Node *up)
        if(n->op == OFOR || n->op == ORANGE)
                e->loopdepth++;
 
+       // type switch variables have no ODCL.
+       // process type switch as declaration.
+       // must happen before processing of switch body,
+       // so before recursion.
+       if(n->op == OSWITCH && n->ntest && n->ntest->op == OTYPESW) {
+               for(ll=n->list; ll; ll=ll->next) {  // cases
+                       // ll->n->nname is the variable per case
+                       if(ll->n->nname)
+                               ll->n->nname->escloopdepth = e->loopdepth;
+               }
+       }
+
        esc(e, n->left, n);
        esc(e, n->right, n);
        esc(e, n->ntest, n);
@@ -658,8 +670,10 @@ esc(EscState *e, Node *n, Node *up)
                // current loop depth is an upper bound on actual loop depth
                // of addressed value.
                n->escloopdepth = e->loopdepth;
-               // for &x, use loop depth of x.
-               if(n->left->op == ONAME) {
+               // for &x, use loop depth of x if known.
+               // it should always be known, but if not, be conservative
+               // and keep the current loop depth.
+               if(n->left->op == ONAME && (n->left->escloopdepth != 0 || n->left->class == PPARAMOUT)) {
                        switch(n->left->class) {
                        case PAUTO:
                        case PPARAM:
index 8cb3b6df663651ff631740ec7a3de73339408272..f00741dc2f622157e50815ef85d83f5671461c6c 100644 (file)
@@ -1468,3 +1468,13 @@ func foo152() {
        v := NewV(u)
        println(v)
 }
+
+// issue 8176 - &x in type switch body not marked as escaping
+
+func foo153(v interface{}) *int { // ERROR "leaking param: v"
+       switch x := v.(type) {
+       case int: // ERROR "moved to heap: x"
+               return &x // ERROR "&x escapes to heap"
+       }
+       panic(0)
+}