diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c index 7c7095c8209..2fdbd998702 100644 --- a/src/cmd/gc/esc.c +++ b/src/cmd/gc/esc.c @@ -615,15 +615,15 @@ esc(EscState *e, Node *n, Node *up) for(ll=n->list; ll; ll=ll->next) escassign(e, n, ll->n->right); break; - + case OPTRLIT: n->esc = EscNone; // until proven otherwise e->noesc = list(e->noesc, n); n->escloopdepth = e->loopdepth; - // Contents make it to memory, lose track. - escassign(e, &e->theSink, n->left); + // Link OSTRUCTLIT to OPTRLIT; if OPTRLIT escapes, OSTRUCTLIT elements do too. + escassign(e, n, n->left); break; - + case OCALLPART: n->esc = EscNone; // until proven otherwise e->noesc = list(e->noesc, n); @@ -730,6 +730,7 @@ escassign(EscState *e, Node *dst, Node *src) case OCONVNOP: case OMAPLIT: case OSTRUCTLIT: + case OPTRLIT: case OCALLPART: break; diff --git a/test/escape2.go b/test/escape2.go index 6a46ce86abd..357ce4a8a85 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -1492,3 +1492,30 @@ func g() (x interface{}) { // ERROR "moved to heap: x" x = &x // ERROR "&x escapes to heap" return } + +var sink interface{} + +type Lit struct { + p *int +} + +func ptrlitNoescape() { + // Both literal and element do not escape. + i := 0 + x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i does not escape" + _ = x +} + +func ptrlitNoEscape2() { + // Literal does not escape, but element does. + i := 0 // ERROR "moved to heap: i" + x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap" + sink = *x +} + +func ptrlitEscape() { + // Both literal and element escape. + i := 0 // ERROR "moved to heap: i" + x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap" + sink = x +} diff --git a/test/escape2n.go b/test/escape2n.go index 002a78ea50d..3e9bb709c9a 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -1492,3 +1492,30 @@ func g() (x interface{}) { // ERROR "moved to heap: x" x = &x // ERROR "&x escapes to heap" return } + +var sink interface{} + +type Lit struct { + p *int +} + +func ptrlitNoescape() { + // Both literal and element do not escape. + i := 0 + x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i does not escape" + _ = x +} + +func ptrlitNoEscape2() { + // Literal does not escape, but element does. + i := 0 // ERROR "moved to heap: i" + x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap" + sink = *x +} + +func ptrlitEscape() { + // Both literal and element escape. + i := 0 // ERROR "moved to heap: i" + x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap" + sink = x +}