https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60406
--- Comment #18 from Ian Lance Taylor <ian at airs dot com> --- > Well, maybe it was only a problem with tail recursion, .... Note that because Go programs expect predictable results from runtime.Callers and other stack backtracing functions, the Go frontend disables tail recursion (go_langhook_post_options in gcc/go/go-lang.c). > Hm, so the patch penalises platforms that cannot deal with the 16 byte window? Yes, but, recall that on your system almost all tests pass using the code that is in the tree today, before your patch. The only tests that fail are the very challenging ones in recover.go, that stress test the panic/recover mechanism but are in no way representative of real code. The normal tests all works fine. So while there is a penalty, it is one that only occurs in rare cases. >>> func main() { defer foo(); panic("..."); } >>> func foo() { defer bar(); } >>> func bar() { recover(); } >> >> In this case, the call to recover in bar is supposed to return nil; >> it should not recover the panic. If you read the paragraph before >> the one you quote, you will see that recover only returns non-nil >> if it was called by a function that was deferred before the call to >> panic. > >I've read it but cannot see anything that would disallow recovery in this > situation. What exactly do you mean? The spec says "Suppose a function G defers a function D that calls recover and a panic occurs in a function on the same goroutine in which G is executing." The order is 1) G defers D; 2) a panic occurs. In your example above, this applies to main defers foo and then a panic occurs. It does not apply to foo defers bar, because there is no panic after foo defers bar (the panic has already occurred--that is why we are executing foo). Since there is no panic, the recover in bar returns nil. The recover.go file tests this pattern in, e.g., test1WithClosures.