case OAS2: // x,y = a,b
if n.List.Len() == n.Rlist.Len() {
rs := n.Rlist.Slice()
+ where := n
for i, n := range n.List.Slice() {
- e.escassignWhyWhere(n, rs[i], "assign-pair", n)
+ e.escassignWhyWhere(n, rs[i], "assign-pair", where)
}
}
// esccall already done on n.Rlist.First(). tie it's Retval to n.List
case OAS2FUNC: // x,y = f()
rs := e.nodeEscState(n.Rlist.First()).Retval.Slice()
+ where := n
for i, n := range n.List.Slice() {
if i >= len(rs) {
break
}
- e.escassignWhyWhere(n, rs[i], "assign-pair-func-call", n)
+ e.escassignWhyWhere(n, rs[i], "assign-pair-func-call", where)
}
if n.List.Len() != len(rs) {
Fatalf("esc oas2func")
_, _ = s1, s2
}
+func leakParams(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2 level=0$" "from ~r2 \(return\) at escape_because.go:129$" "leaking param: p2 to result ~r3 level=0$" "from ~r3 \(return\) at escape_because.go:129$"
+ return p1, p2
+}
+
+func leakThroughOAS2() {
+ // See #26987.
+ i := 0 // ERROR "moved to heap: i$"
+ j := 0 // ERROR "moved to heap: j$"
+ sink, sink = &i, &j // ERROR "&i escapes to heap$" "from sink \(assign-pair\) at escape_because.go:136$" "from &i \(interface-converted\) at escape_because.go:136$" "&j escapes to heap$" "from &j \(interface-converted\) at escape_because.go:136"
+}
+
+func leakThroughOAS2FUNC() {
+ // See #26987.
+ i := 0 // ERROR "moved to heap: i$"
+ j := 0
+ sink, _ = leakParams(&i, &j) // ERROR "&i escapes to heap$" "&j does not escape$" "from .out0 \(passed-to-and-returned-from-call\) at escape_because.go:143$" "from sink \(assign-pair-func-call\) at escape_because.go:143$"
+}
+
// The list below is all of the why-escapes messages seen building the escape analysis tests.
/*
for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done