summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-06-11 17:00:17 -0400
committerRuss Cox <rsc@golang.org>2014-06-11 17:00:17 -0400
commitd77639d287bafeaa77f7687514bb946cbc801472 (patch)
tree0c4797e2f40e09823ce3a835c2f9af033190d665
parentd04c3728c80df739eb0a59566f75ebe265ed8d69 (diff)
downloadgo-d77639d287bafeaa77f7687514bb946cbc801472.tar.gz
[release-branch.go1.3] cmd/gc: two escape analysis fixes
??? CL 108860043 / f153208c0a0e cmd/gc: fix escape analysis for &x inside switch x := v.(type) 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 issue 8176. LGTM=iant R=iant CC=golang-codereviews https://codereview.appspot.com/108860043 ??? ??? CL 108870044 / 331dbd4a6334 cmd/gc: fix &result escaping into result There is a hierarchy of location defined by loop depth: -1 = the heap 0 = function results 1 = local variables (and parameters) 2 = local variable declared inside a loop 3 = local variable declared inside a loop inside a loop etc In general if an address from loopdepth n is assigned to something in loop depth m < n, that indicates an extended lifetime of some form that requires a heap allocation. Function results can be local variables too, though, and so they don't actually fit into the hierarchy very well. Treat the address of a function result as level 1 so that if it is written back into a result, the address is treated as escaping. Fixes issue 8185 . LGTM=iant R=iant CC=golang-codereviews https://codereview.appspot.com/108870044 ??? LGTM=r R=golang-codereviews, r CC=bradfitz, golang-codereviews, iant https://codereview.appspot.com/107930044
-rw-r--r--src/cmd/gc/esc.c27
-rw-r--r--test/escape2.go22
2 files changed, 47 insertions, 2 deletions
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index a75517813..78624d7cb 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -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,13 +670,24 @@ 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.
+ // 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) {
switch(n->left->class) {
case PAUTO:
+ if(n->left->escloopdepth != 0)
+ n->escloopdepth = n->left->escloopdepth;
+ break;
case PPARAM:
case PPARAMOUT:
- n->escloopdepth = n->left->escloopdepth;
+ // PPARAM is loop depth 1 always.
+ // PPARAMOUT is loop depth 0 for writes
+ // but considered loop depth 1 for address-of,
+ // so that writing the address of one result
+ // to another (or the same) result makes the
+ // first result move to the heap.
+ n->escloopdepth = 1;
break;
}
}
diff --git a/test/escape2.go b/test/escape2.go
index 8cb3b6df6..28251aa98 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -1468,3 +1468,25 @@ 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)
+}
+
+// issue 8185 - &result escaping into result
+
+func f() (x int, y *int) { // ERROR "moved to heap: x"
+ y = &x // ERROR "&x escapes to heap"
+ return
+}
+
+func g() (x interface{}) { // ERROR "moved to heap: x"
+ x = &x // ERROR "&x escapes to heap"
+ return
+}