Commit 775ab8ee authored by Russ Cox's avatar Russ Cox

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 #8176.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/108860043
parent 3ad9df04
...@@ -442,6 +442,18 @@ esc(EscState *e, Node *n, Node *up) ...@@ -442,6 +442,18 @@ esc(EscState *e, Node *n, Node *up)
if(n->op == OFOR || n->op == ORANGE) if(n->op == OFOR || n->op == ORANGE)
e->loopdepth++; 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->left, n);
esc(e, n->right, n); esc(e, n->right, n);
esc(e, n->ntest, n); esc(e, n->ntest, n);
...@@ -658,8 +670,10 @@ esc(EscState *e, Node *n, Node *up) ...@@ -658,8 +670,10 @@ esc(EscState *e, Node *n, Node *up)
// current loop depth is an upper bound on actual loop depth // current loop depth is an upper bound on actual loop depth
// of addressed value. // of addressed value.
n->escloopdepth = e->loopdepth; n->escloopdepth = e->loopdepth;
// for &x, use loop depth of x. // for &x, use loop depth of x if known.
if(n->left->op == ONAME) { // 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) { switch(n->left->class) {
case PAUTO: case PAUTO:
case PPARAM: case PPARAM:
......
...@@ -1468,3 +1468,13 @@ func foo152() { ...@@ -1468,3 +1468,13 @@ func foo152() {
v := NewV(u) v := NewV(u)
println(v) 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)
}
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