go.tools/go/ssa: emit a recover block if the function's results are unnamed
It is easier for clients to recover from panics if the recover block is always present. Otherwise, the client has to work around the lack of a recover block by synthesizing a zero value return. LGTM=adonovan R=adonovan CC=golang-codereviews https://golang.org/cl/87210044
This commit is contained in:
parent
f0ff511183
commit
ce1e99a260
|
|
@ -1895,14 +1895,9 @@ start:
|
||||||
b.setCall(fn, s.Call, &v.Call)
|
b.setCall(fn, s.Call, &v.Call)
|
||||||
fn.emit(&v)
|
fn.emit(&v)
|
||||||
|
|
||||||
// A deferred call can cause recovery from panic.
|
// A deferred call can cause recovery from panic,
|
||||||
// If the panicking function has named results,
|
// and control resumes at the Recover block.
|
||||||
// control resumes at the Recover block to load those
|
|
||||||
// locals (which may be mutated by the deferred call)
|
|
||||||
// and return them.
|
|
||||||
if fn.namedResults != nil {
|
|
||||||
createRecoverBlock(fn)
|
createRecoverBlock(fn)
|
||||||
}
|
|
||||||
|
|
||||||
case *ast.ReturnStmt:
|
case *ast.ReturnStmt:
|
||||||
var results []Value
|
var results []Value
|
||||||
|
|
|
||||||
|
|
@ -555,9 +555,6 @@ func runFrame(fr *frame) {
|
||||||
}
|
}
|
||||||
fr.runDefers()
|
fr.runDefers()
|
||||||
fr.block = fr.fn.Recover
|
fr.block = fr.fn.Recover
|
||||||
if fr.block == nil {
|
|
||||||
fr.result = zero(fr.fn.Signature.Results())
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
|
||||||
|
|
@ -273,9 +273,9 @@ type Node interface {
|
||||||
// To iterate over the blocks in dominance order, use DomPreorder().
|
// To iterate over the blocks in dominance order, use DomPreorder().
|
||||||
//
|
//
|
||||||
// Recover is an optional second entry point to which control resumes
|
// Recover is an optional second entry point to which control resumes
|
||||||
// after a recovered panic. The Recover block may contain only a load
|
// after a recovered panic. The Recover block may contain only a return
|
||||||
// of the function's named return parameters followed by a return of
|
// statement, preceded by a load of the function's named return
|
||||||
// the loaded values.
|
// parameters, if any.
|
||||||
//
|
//
|
||||||
// A nested function (Parent()!=nil) that refers to one or more
|
// A nested function (Parent()!=nil) that refers to one or more
|
||||||
// lexically enclosing local variables ("free variables") has FreeVar
|
// lexically enclosing local variables ("free variables") has FreeVar
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue