The Go defer/panic/recover handling works through a little dance that includes comparing return addresses to see if a particular call to recover should pick up a particular call to panic. This dance only works if the appropriate functions are not inlined. I messed up the condition for whether the functions could be inlined, such that it usually worked but broke at -O3. This patch fixes the problem. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r b740d140ea5f go/gogo-tree.cc --- a/go/gogo-tree.cc Tue Sep 13 14:32:18 2011 -0700 +++ b/go/gogo-tree.cc Wed Sep 14 11:30:56 2011 -0700 @@ -1159,8 +1159,11 @@ // If a function calls the predeclared recover function, we // can't inline it, because recover behaves differently in a - // function passed directly to defer. - if (this->calls_recover_ && !this->is_recover_thunk_) + // function passed directly to defer. If this is a recover + // thunk that we built to test whether a function can be + // recovered, we can't inline it, because that will mess up + // our return address comparison. + if (this->calls_recover_ || this->is_recover_thunk_) DECL_UNINLINABLE(decl) = 1; // If this is a thunk created to call a function which calls