http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51644
--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> 2011-12-21 09:51:45 UTC --- Caused by r181172 aka TREE_CLOBBER_P. The problem is that we have before *.cfg: __builtin_va_start (&args, 0); b (s, &args); __builtin_va_end (&args); finally_tmp.0 = 1; <D.2917>: args = {CLOBBER}; switch (finally_tmp.0) <default: <D.2921>, default: <D.2921>, case 1: <D.2918>> <D.2918>: goto <D.2919>; <D.2919>: return; <D.2920>: finally_tmp.0 = 0; goto <D.2917>; <D.2921>: resx 1 and *.cfg pass obviously optimizes away anything after the noreturn call: <bb 2>: __builtin_va_start (&args, 0); b (s, &args); <L5>: return; <L3>: finally_tmp.0 = 0; args = {CLOBBER}; switch (finally_tmp.0) <default: <L4>, case 1: <L5>> <L4>: resx 1 but the warn_function_return pass is immediately after that (and, this is -O0 anyway), so nothing optimizes the switch away into simple fall through into the resx 1 block. At -O and above we don't warn, because the *.eh pass before *.cfg pass optimizes this. So, IMHO to fix this, we need to do 2 things: 1) in decide_copy_try_finally reconsider if (!optimize) return ndests == 1; if finally contains only gimple_clobber_p stmts 2) estimate_num_insns should return 0 for gimple_clobber_p stmts