From 449eefdb19c58df9303ee5b9fe62fe18876eb2f9 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 31 Oct 2024 09:18:32 +0100 Subject: [PATCH] compiler: allow deferred panic This is rare, but apparently some programs do this: defer panic("...") This is emitted in the IR as a builtin function. --- compiler/compiler.go | 4 ++++ testdata/recover.go | 15 +++++++++++++++ testdata/recover.txt | 4 ++++ 3 files changed, 23 insertions(+) diff --git a/compiler/compiler.go b/compiler/compiler.go index 752e4a5c6..981993fe7 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1680,6 +1680,10 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c result = b.CreateSelect(cmp, result, arg, "") } return result, nil + case "panic": + // This is rare, but happens in "defer panic()". + b.createRuntimeInvoke("_panic", argValues, "") + return llvm.Value{}, nil case "print", "println": for i, value := range argValues { if i >= 1 && callName == "println" { diff --git a/testdata/recover.go b/testdata/recover.go index ced90cfae..c7c02c94a 100644 --- a/testdata/recover.go +++ b/testdata/recover.go @@ -19,6 +19,9 @@ func main() { println("\n# panic replace") panicReplace() + + println("\n# defer panic") + deferPanic() } func recoverSimple() { @@ -89,6 +92,18 @@ func panicReplace() { panic("panic 1") } +func deferPanic() { + defer func() { + printitf("recovered from deferred call:", recover()) + }() + + // This recover should not do anything. + defer recover() + + defer panic("deferred panic") + println("defer panic") +} + func printitf(msg string, itf interface{}) { switch itf := itf.(type) { case string: diff --git a/testdata/recover.txt b/testdata/recover.txt index d27649855..357505881 100644 --- a/testdata/recover.txt +++ b/testdata/recover.txt @@ -23,3 +23,7 @@ recovered: panic panic 1 panic 2 recovered: panic 2 + +# defer panic +defer panic +recovered from deferred call: deferred panic