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 // 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 {

View File

@ -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:

View File

@ -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))
}
} }