type CallExpr struct {
miniExpr
origNode
- X Node
- Args Nodes
- Rargs Nodes // TODO(rsc): Delete.
- Body Nodes // TODO(rsc): Delete.
- IsDDD bool
- Use CallUse
- NoInline bool
+ X Node
+ Args Nodes
+ Rargs Nodes // TODO(rsc): Delete.
+ KeepAlive []*Name // vars to be kept alive until call returns
+ IsDDD bool
+ Use CallUse
+ NoInline bool
}
func NewCallExpr(pos src.XPos, op Op, fun Node, args []Node) *CallExpr {
c.init = copyNodes(c.init)
c.Args = copyNodes(c.Args)
c.Rargs = copyNodes(c.Rargs)
- c.Body = copyNodes(c.Body)
+ c.KeepAlive = copyNames(c.KeepAlive)
return &c
}
func (n *CallExpr) doChildren(do func(Node) bool) bool {
if doNodes(n.Rargs, do) {
return true
}
- if doNodes(n.Body, do) {
+ if doNames(n.KeepAlive, do) {
return true
}
return false
}
editNodes(n.Args, edit)
editNodes(n.Rargs, edit)
- editNodes(n.Body, edit)
+ editNames(n.KeepAlive, edit)
}
func (n *CaseClause) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
}
}
+func copyNames(list []*Name) []*Name {
+ if list == nil {
+ return nil
+ }
+ c := make([]*Name, len(list))
+ copy(c, list)
+ return c
+}
+func doNames(list []*Name, do func(Node) bool) bool {
+ for _, x := range list {
+ if x != nil && do(x) {
+ return true
+ }
+ }
+ return false
+}
+func editNames(list []*Name, edit func(Node) Node) {
+ for i, x := range list {
+ if x != nil {
+ list[i] = edit(x).(*Name)
+ }
+ }
+}
+
func copyNodes(list []Node) []Node {
if list == nil {
return nil
s.vars[memVar] = call
}
// Insert OVARLIVE nodes
- s.stmtList(n.Body)
+ for _, name := range n.KeepAlive {
+ s.stmt(ir.NewUnaryExpr(n.Pos(), ir.OVARLIVE, name))
+ }
// Finish block for defers
if k == callDefer || k == callDeferStack {
case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
call := call.(*ir.CallExpr)
- if len(call.Body) > 0 {
+ if len(call.KeepAlive) > 0 {
n.Call = wrapCall(call, &init)
} else {
n.Call = walkExpr(call, &init)