Commit 20c7e415 authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: fix escape analysis bug.

It used to not mark parameters as escaping if only one of the
fields it points to leaks out of the function. This causes
problems when importing from another package.

Fixes #4964.

R=rsc, lvd, dvyukov, daniel.morsing
CC=golang-dev
https://golang.org/cl/7648045
parent 2924638d
......@@ -1033,7 +1033,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
switch(src->op) {
case ONAME:
if(src->class == PPARAM && leaks && src->esc != EscHeap) {
if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) {
src->esc = EscScope;
if(debug['m'])
warnl(src->lineno, "leaking param: %hN", src);
......
......@@ -80,7 +80,9 @@ func foo12(yyy **int) { // ERROR "leaking param: yyy"
xxx = yyy
}
func foo13(yyy **int) { // ERROR "yyy does not escape"
// Must treat yyy as leaking because *yyy leaks, and the escape analysis
// summaries in exported metadata do not distinguish these two cases.
func foo13(yyy **int) { // ERROR "leaking param: yyy"
*xxx = *yyy
}
......@@ -299,7 +301,8 @@ func (f *Foo) foo45() { // ERROR "f does not escape"
F.x = f.x
}
func (f *Foo) foo46() { // ERROR "f does not escape"
// See foo13 above for explanation of why f leaks.
func (f *Foo) foo46() { // ERROR "leaking param: f"
F.xx = f.xx
}
......
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
var global, global2 *int
type T struct {
Pointer *int
}
func dontinline() {}
func Store(t *T) {
global = t.Pointer
dontinline()
}
func Store2(t *T) {
global2 = t.Pointer
dontinline()
}
func Get() *int {
return global
}
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "./a"
func F() {
// store 1 in a.global
x, y := 1, 2
t := a.T{Pointer: &x}
a.Store(&t)
_ = y
}
func G() {
// store 4 in a.global2
x, y := 3, 4
t := a.T{Pointer: &y}
a.Store2(&t)
_ = x
}
func main() {
F()
G()
p := a.Get()
n := *p
if n != 1 {
println(n, "!= 1")
panic("n != 1")
}
}
// rundir
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 4964: exported escape analysis result is not enough
// for cross package analysis.
package ignored
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