cmd/compile: mark anonymous receiver parameters as non-escaping

This was already done for normal parameters, and the same logic
applies for receiver parameters too.

Updates #24305.

Change-Id: Ia2a46f68d14e8fb62004ff0da1db0f065a95a1b7
Reviewed-on: https://go-review.googlesource.com/99335
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Matthew Dempsky 2018-03-07 15:10:27 -08:00
parent 8b8625a328
commit 88466e93a4
3 changed files with 29 additions and 10 deletions

View File

@ -2259,16 +2259,18 @@ func (e *EscState) esctag(fn *Node) {
// Unnamed parameters are unused and therefore do not escape.
// (Unnamed parameters are not in the Dcl list in the loop above
// so we need to mark them separately.)
for _, f := range fn.Type.Params().Fields().Slice() {
if !types.Haspointers(f.Type) { // don't bother tagging for scalars
continue
}
if f.Note == uintptrEscapesTag {
// Note is already set in the loop above.
continue
}
if f.Sym == nil || f.Sym.IsBlank() {
f.Note = mktag(EscNone)
for _, fs := range types.RecvsParams {
for _, f := range fs(fn.Type).Fields().Slice() {
if !types.Haspointers(f.Type) { // don't bother tagging for scalars
continue
}
if f.Note == uintptrEscapesTag {
// Note is already set in the loop above.
continue
}
if f.Sym == nil || f.Sym.IsBlank() {
f.Note = mktag(EscNone)
}
}
}
}

View File

@ -726,6 +726,11 @@ var RecvsParamsResults = [3]func(*Type) *Type{
(*Type).Recvs, (*Type).Params, (*Type).Results,
}
// RecvsParams is like RecvsParamsResults, but omits result parameters.
var RecvsParams = [2]func(*Type) *Type{
(*Type).Recvs, (*Type).Params,
}
// ParamsResults is like RecvsParamsResults, but omits receiver parameters.
var ParamsResults = [2]func(*Type) *Type{
(*Type).Params, (*Type).Results,

View File

@ -163,3 +163,15 @@ func f13() {
f12(&x) // ERROR "&x does not escape"
runtime.KeepAlive(&x) // ERROR "&x does not escape"
}
// Test for issue 24305 (passing to unnamed receivers does not escape).
type U int
func (*U) M() {}
func (_ *U) N() {}
func _() {
var u U
u.M() // ERROR "u does not escape"
u.N() // ERROR "u does not escape"
}