lineno = lno
}
+// hasemptycvars returns true iff closure func_ has an
+// empty list of captured vars. OXXX nodes don't count.
+func hasemptycvars(func_ *Node) bool {
+ for _, v := range func_.Func.Cvars.Slice() {
+ if v.Op == OXXX {
+ continue
+ }
+ return false
+ }
+ return true
+}
+
+// closuredebugruntimecheck applies boilerplate checks for debug flags
+// and compiling runtime
+func closuredebugruntimecheck(r *Node) {
+ if Debug_closure > 0 {
+ if r.Esc == EscHeap {
+ Warnl(r.Lineno, "heap closure, captured vars = %v", r.Func.Cvars)
+ } else {
+ Warnl(r.Lineno, "stack closure, captured vars = %v", r.Func.Cvars)
+ }
+ }
+ if compiling_runtime > 0 && r.Esc == EscHeap {
+ yyerrorl(r.Lineno, "heap-allocated closure, not allowed in runtime.")
+ }
+}
+
func walkclosure(func_ *Node, init *Nodes) *Node {
// If no closure vars, don't bother wrapping.
- if len(func_.Func.Cvars.Slice()) == 0 {
+ if hasemptycvars(func_) {
+ if Debug_closure > 0 {
+ Warnl(func_.Lineno, "closure converted to global")
+ }
return func_.Func.Closure.Func.Nname
+ } else {
+ closuredebugruntimecheck(func_)
}
// Create closure in the form of a composite literal.
)
var (
- Debug_append int
- Debug_panic int
- Debug_slice int
- Debug_wb int
+ Debug_append int
+ Debug_closure int
+ Debug_panic int
+ Debug_slice int
+ Debug_wb int
)
// Debug arguments.
val *int
}{
{"append", &Debug_append}, // print information about append compilation
+ {"closure", &Debug_closure}, // print information about closure compilation
{"disablenil", &Disable_checknil}, // disable nil checks
{"gcprog", &Debug_gcprog}, // print dump of GC programs
{"nil", &Debug_checknil}, // print information about nil checks
break
case OCLOSURE:
- if len(r.Func.Cvars.Slice()) == 0 {
+ if hasemptycvars(r) {
+ if Debug_closure > 0 {
+ Warnl(r.Lineno, "closure converted to global")
+ }
// Closures with no captured variables are globals,
// so the assignment can be done at link time.
n := *l
gdata(&n, r.Func.Closure.Func.Nname, Widthptr)
return true
+ } else {
+ closuredebugruntimecheck(r)
}
}
--- /dev/null
+// errorcheck -+
+
+// Copyright 2016 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 p
+
+func f(x int) func(int) int {
+ return func(y int) int { return x + y } // ERROR "heap-allocated closure, not allowed in runtime."
+}
+
+func g(x int) func(int) int { // ERROR "x escapes to heap, not allowed in runtime."
+ return func(y int) int { // ERROR "heap-allocated closure, not allowed in runtime."
+ x += y
+ return x + y
+ }
+}