go.tools/ssa/interp: fix bug: recovered panic without NRPs should return zero values.
+ test. R=gri CC=golang-dev https://golang.org/cl/38040043
This commit is contained in:
parent
d063887ea0
commit
100638985b
|
|
@ -532,9 +532,13 @@ func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function,
|
||||||
// After a normal return, fr.result contains the result of the call
|
// After a normal return, fr.result contains the result of the call
|
||||||
// and fr.block is nil.
|
// and fr.block is nil.
|
||||||
//
|
//
|
||||||
// After a recovered panic, fr.result is undefined and fr.block
|
// A recovered panic in a function without named return parameters
|
||||||
// contains the block at which to resume control, which may be
|
// (NRPs) becomes a normal return of the zero value of the function's
|
||||||
// nil for a normal return.
|
// result type.
|
||||||
|
//
|
||||||
|
// After a recovered panic in a function with NRPs, fr.result is
|
||||||
|
// undefined and fr.block contains the block at which to resume
|
||||||
|
// control.
|
||||||
//
|
//
|
||||||
func runFrame(fr *frame) {
|
func runFrame(fr *frame) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
@ -550,7 +554,10 @@ func runFrame(fr *frame) {
|
||||||
fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
|
fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
|
||||||
}
|
}
|
||||||
fr.runDefers()
|
fr.runDefers()
|
||||||
fr.block = fr.fn.Recover // recovered panic
|
fr.block = fr.fn.Recover
|
||||||
|
if fr.block == nil {
|
||||||
|
fr.result = zero(fr.fn.Signature.Results())
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,15 @@ func zero(t types.Type) value {
|
||||||
s[i] = zero(t.Field(i).Type())
|
s[i] = zero(t.Field(i).Type())
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
case *types.Tuple:
|
||||||
|
if t.Len() == 1 {
|
||||||
|
return zero(t.At(0).Type())
|
||||||
|
}
|
||||||
|
s := make(tuple, t.Len())
|
||||||
|
for i := range s {
|
||||||
|
s[i] = zero(t.At(i).Type())
|
||||||
|
}
|
||||||
|
return s
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
return chan value(nil)
|
return chan value(nil)
|
||||||
case *types.Map:
|
case *types.Map:
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package main
|
||||||
|
|
||||||
// Tests of panic/recover.
|
// Tests of panic/recover.
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
func fortyTwo() (r int) {
|
func fortyTwo() (r int) {
|
||||||
r = 42
|
r = 42
|
||||||
// The next two statements simulate a 'return' statement.
|
// The next two statements simulate a 'return' statement.
|
||||||
|
|
@ -9,8 +11,24 @@ func fortyTwo() (r int) {
|
||||||
panic(nil)
|
panic(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func zero() int {
|
||||||
|
defer func() { recover() }()
|
||||||
|
panic(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func zeroEmpty() (int, string) {
|
||||||
|
defer func() { recover() }()
|
||||||
|
panic(1)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if r := fortyTwo(); r != 42 {
|
if r := fortyTwo(); r != 42 {
|
||||||
panic(r)
|
panic(r)
|
||||||
}
|
}
|
||||||
|
if r := zero(); r != 0 {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
if r, s := zeroEmpty(); r != 0 || s != "" {
|
||||||
|
panic(fmt.Sprint(r, s))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue