]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: check deferred nil interface call before wrapping it
authorCherry Zhang <cherryyz@google.com>
Mon, 29 Mar 2021 17:44:08 +0000 (13:44 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 30 Mar 2021 00:47:22 +0000 (00:47 +0000)
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>
src/cmd/compile/internal/walk/order.go

index 95d245d0d7aec299be5459f3689d946c5a771a17..9e6c58054d3ad597b7b918413dabc9d0d0b71c7b 100644 (file)
@@ -1602,6 +1602,17 @@ func (o *orderState) wrapGoDefer(n *ir.GoDeferStmt) {
                        n := callX.(*ir.SelectorExpr)
                        n.X = mkArgCopy(n.X)
                        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):
                        // Deal with "defer returnsafunc()(x, y)" (for
                        // example) by copying the callee expression.