aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2016-06-06 16:00:33 -0400
committerCherry Zhang <cherryyz@google.com>2016-06-08 20:35:53 +0000
commitf3689d138256c36dbe0004459f79d570f5345f74 (patch)
treef4badbfd58ed9af987b32a9770c168a93c384c87
parent0324a3f828d3a2f48751df2bbd54ad20499e598a (diff)
downloadgo-f3689d138256c36dbe0004459f79d570f5345f74.tar.xz
cmd/compile: nilcheck interface value in go/defer interface call for SSA
This matches the behavior of the legacy backend. Fixes #15975 (if this is the intended behavior) Change-Id: Id277959069b8b8bf9958fa8f2cbc762c752a1a19 Reviewed-on: https://go-review.googlesource.com/23820 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/ssa.go3
-rw-r--r--test/fixedbugs/issue15975.go36
2 files changed, 39 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index d27ac4392f..c0e6045216 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -2573,6 +2573,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
}
i := s.expr(fn.Left)
itab := s.newValue1(ssa.OpITab, Types[TUINTPTR], i)
+ if k != callNormal {
+ s.nilCheck(itab)
+ }
itabidx := fn.Xoffset + 3*int64(Widthptr) + 8 // offset of fun field in runtime.itab
itab = s.newValue1I(ssa.OpOffPtr, Types[TUINTPTR], itabidx, itab)
if k == callNormal {
diff --git a/test/fixedbugs/issue15975.go b/test/fixedbugs/issue15975.go
new file mode 100644
index 0000000000..56a50e1176
--- /dev/null
+++ b/test/fixedbugs/issue15975.go
@@ -0,0 +1,36 @@
+// run
+
+// 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 main
+
+var fail bool
+
+type Closer interface {
+ Close()
+}
+
+func nilInterfaceDeferCall() {
+ var x Closer
+ defer x.Close()
+ // if it panics when evaluating x.Close, it should not reach here
+ fail = true
+}
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("did not panic")
+ }
+ }()
+ f()
+}
+
+func main() {
+ shouldPanic(nilInterfaceDeferCall)
+ if fail {
+ panic("fail")
+ }
+}