]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: fix escape analysis bug.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Fri, 15 Mar 2013 08:03:45 +0000 (09:03 +0100)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Fri, 15 Mar 2013 08:03:45 +0000 (09:03 +0100)
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

src/cmd/gc/esc.c
test/escape2.go
test/fixedbugs/issue4964.dir/a.go [new file with mode: 0644]
test/fixedbugs/issue4964.dir/b.go [new file with mode: 0644]
test/fixedbugs/issue4964.go [new file with mode: 0644]

index 46c06d10e458c174b96c9631eff06fdbfc3da034..7be7b534139c2cbfa39e221f9605e001398e611c 100644 (file)
@@ -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);
index 94816193385cceb9d7f10acf6d87de9573ff1d24..3473e4fa450779074912d478d4cf64296c8c56f3 100644 (file)
@@ -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
 }
 
diff --git a/test/fixedbugs/issue4964.dir/a.go b/test/fixedbugs/issue4964.dir/a.go
new file mode 100644 (file)
index 0000000..2b9e44e
--- /dev/null
@@ -0,0 +1,27 @@
+// 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
+}
diff --git a/test/fixedbugs/issue4964.dir/b.go b/test/fixedbugs/issue4964.dir/b.go
new file mode 100644 (file)
index 0000000..42a6f1d
--- /dev/null
@@ -0,0 +1,34 @@
+// 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")
+       }
+}
diff --git a/test/fixedbugs/issue4964.go b/test/fixedbugs/issue4964.go
new file mode 100644 (file)
index 0000000..8291d1b
--- /dev/null
@@ -0,0 +1,10 @@
+// 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