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:
Alan Donovan 2013-12-05 21:22:57 -05:00
parent d063887ea0
commit 100638985b
3 changed files with 38 additions and 4 deletions

View File

@ -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
// and fr.block is nil.
//
// After a recovered panic, fr.result is undefined and fr.block
// contains the block at which to resume control, which may be
// nil for a normal return.
// A recovered panic in a function without named return parameters
// (NRPs) becomes a normal return of the zero value of the function's
// 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) {
defer func() {
@ -550,7 +554,10 @@ func runFrame(fr *frame) {
fmt.Fprintf(os.Stderr, "Panicking: %T %v.\n", fr.panic, fr.panic)
}
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 {

View File

@ -235,6 +235,15 @@ func zero(t types.Type) value {
s[i] = zero(t.Field(i).Type())
}
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:
return chan value(nil)
case *types.Map:

View File

@ -2,6 +2,8 @@ package main
// Tests of panic/recover.
import "fmt"
func fortyTwo() (r int) {
r = 42
// The next two statements simulate a 'return' statement.
@ -9,8 +11,24 @@ func fortyTwo() (r int) {
panic(nil)
}
func zero() int {
defer func() { recover() }()
panic(1)
}
func zeroEmpty() (int, string) {
defer func() { recover() }()
panic(1)
}
func main() {
if r := fortyTwo(); r != 42 {
panic(r)
}
if r := zero(); r != 0 {
panic(r)
}
if r, s := zeroEmpty(); r != 0 || s != "" {
panic(fmt.Sprint(r, s))
}
}