mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: check deferred nil interface call before wrapping it
Currently, for "defer i.M()" if i is nil it panics at the point of defer statement, not when deferred function is called. We need to do the nil check before wrapping it. Updates #40724. Change-Id: I62c669264668991f71999e2cf4610a9066247f9d Reviewed-on: https://go-review.googlesource.com/c/go/+/305549 Trust: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
4e1bf8ed38
commit
bd6628e62d
1 changed files with 11 additions and 0 deletions
|
|
@ -1602,6 +1602,17 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
|
||||||
n := callX.(*ir.SelectorExpr)
|
n := callX.(*ir.SelectorExpr)
|
||||||
n.X = mkArgCopy(n.X)
|
n.X = mkArgCopy(n.X)
|
||||||
methSelectorExpr = n
|
methSelectorExpr = n
|
||||||
|
if callX.Op() == ir.ODOTINTER {
|
||||||
|
// Currently for "defer i.M()" if i is nil it panics at the
|
||||||
|
// point of defer statement, not when deferred function is called.
|
||||||
|
// (I think there is an issue discussing what is the intended
|
||||||
|
// behavior but I cannot find it.)
|
||||||
|
// We need to do the nil check outside of the wrapper.
|
||||||
|
tab := typecheck.Expr(ir.NewUnaryExpr(base.Pos, ir.OITAB, n.X))
|
||||||
|
c := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, tab)
|
||||||
|
c.SetTypecheck(1)
|
||||||
|
o.append(c)
|
||||||
|
}
|
||||||
case !(callX.Op() == ir.ONAME && callX.(*ir.Name).Class == ir.PFUNC):
|
case !(callX.Op() == ir.ONAME && callX.(*ir.Name).Class == ir.PFUNC):
|
||||||
// Deal with "defer returnsafunc()(x, y)" (for
|
// Deal with "defer returnsafunc()(x, y)" (for
|
||||||
// example) by copying the callee expression.
|
// example) by copying the callee expression.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue