The escape analysis models the flow of "content" of X with a
level of "indirection" (OIND node) of X. This content can be
pointer dereference, or slice/string element. For the latter
case, the type of the OIND node should be the element type of
the slice/string. This CL fixes this. In particular, this
matters when the element type is pointerless, where the data
flow should not cause any escape.
Fixes #15730.
Change-Id: Iba9f92898681625e7e3ddef76ae65d7cd61c41e0
Reviewed-on: https://go-review.googlesource.com/107597
Reviewed-by: David Chase <drchase@google.com>
e.nodeEscState(ind).Loopdepth = e.nodeEscState(n).Loopdepth
ind.Pos = n.Pos
t := n.Type
- if t.IsKind(types.Tptr) {
+ if t.IsKind(types.Tptr) || t.IsSlice() {
// This should model our own sloppy use of OIND to encode
- // decreasing levels of indirection; i.e., "indirecting" an array
- // might yield the type of an element. To be enhanced...
+ // decreasing levels of indirection; i.e., "indirecting" a slice
+ // yields the type of an element.
t = t.Elem()
+ } else if t.IsString() {
+ t = types.Types[TUINT8]
}
ind.Type = t
return ind
*z = 2
}
}
+
+// Issue 15730: copy causes unnecessary escape
+
+var sink []byte
+var sink2 []int
+var sink3 []*int
+
+func f15730a(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case string:
+ copy(sink, a)
+ }
+ }
+}
+
+func f15730b(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []int:
+ copy(sink2, a)
+ }
+ }
+}
+
+func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []*int:
+ // copy pointerful data should cause escape
+ copy(sink3, a)
+ }
+ }
+}