}
}
- // Big stuff escapes unconditionally
- // "Big" conditions that were scattered around in walk have been gathered here
+ // Big stuff and non-constant-sized stuff escapes unconditionally.
+ // "Big" conditions that were scattered around in walk have been
+ // gathered here.
if n.Esc != EscHeap && n.Type != nil &&
(n.Type.Width > maxStackVarSize ||
(n.Op == ONEW || n.Op == OPTRLIT) && n.Type.Elem().Width >= 1<<16 ||
n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
+
+ // isSmallMakeSlice returns false for non-constant len/cap.
+ // If that's the case, print a more accurate escape reason.
+ var msgVerb, escapeMsg string
+ if n.Op == OMAKESLICE && (!Isconst(n.Left, CTINT) || !Isconst(n.Right, CTINT)) {
+ msgVerb, escapeMsg = "has ", "non-constant size"
+ } else {
+ msgVerb, escapeMsg = "is ", "too large for stack"
+ }
+
if Debug['m'] > 2 {
- Warnl(n.Pos, "%v is too large for stack", n)
+ Warnl(n.Pos, "%v "+msgVerb+escapeMsg, n)
}
n.Esc = EscHeap
addrescapes(n)
- e.escassignSinkWhy(n, n, "too large for stack") // TODO category: tooLarge
+ e.escassignSinkWhy(n, n, escapeMsg) // TODO category: tooLarge
}
e.esc(n.Left, n)
b := make([]*string, 65537) // ERROR "make\(\[\]\*string, 65537\) escapes to heap"
b[0] = y
}
+
+func nonconstArray() {
+ n := 32
+ s1 := make([]int, n) // ERROR "make\(\[\]int, n\) escapes to heap"
+ s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap"
+ _, _ = s1, s2
+}
return b
}
+func f14() {
+ n := 32
+ s1 := make([]int, n) // ERROR "make\(\[\]int, n\) escapes to heap" "from make\(\[\]int, n\) \(non-constant size\)"
+ s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap" "from make\(\[\]int, 0, n\) \(non-constant size\)"
+ _, _ = s1, s2
+}
+
// 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