Hi, somehow gcc gets confused in its control flow analysis when a default case in a switch has a throw and break, and a variable with user defined dtor. struct A { ~A() { } }; bool check( int x ) { A z; switch( x ) { case 0: return false; default: throw "X"; break; } } When I either remove the break or the variable z, the warning will not issued anymore.
This is a regression, there's no warning from 3.4
void foo (void) __attribute__((noreturn)); struct A { ~A () {} }; bool check (int x) { A z; switch (x) { case 0: return false; default: foo (); break; } } warns the same.
Or: void foo (void) __attribute__((noreturn)); void bar (void); struct A { ~A () {} }; bool check (int x) { A z; switch (x) { case 0: return false; default: foo (); bar (); } } The problem is related to pass ordering. EH lowering is done before CFG cleanups, so if there is code after a noreturn spot (whether throw or noreturn function, endless loop etc. doesn't matter), when trying to lower try .. finally EH will see gimple_seq_may_fallthru to be true because of the extra code after it hiding that it in fact can't fall thru. We end up then with: switch (x) <default: <D.2213>, case 0: <D.2212>> <D.2212>: D.2216 = 0; finally_tmp.0 = 0; goto <D.2220>; <D.2213>: foo (); bar (); finally_tmp.0 = 1; <D.2220>: A::~A (&z); switch (finally_tmp.0) <default: <D.2223>, default: <D.2223>, case 1: <D.2221>> where D.2221 falls thru to exit without returning a value, while D.2223 doesn't. Then cfg cleanup during cfg pass cleans that up to: finally_tmp.0 = 0; A::~A (&z); switch (finally_tmp.0) <default: <L12>, case 1: <L11>> after finding out that foo is noreturn and can't fallthru. But there is no constant propagation and switch optimization pass that would simplify switch (0) <default: something; case 1: somethingelse> into goto something; scheduled before the pass_warn_function_return is scheduled. As we aren't in SSA form at that point, doing it wouldn't be very easy.
There is a machinery in gimple-low.c for this (and a pending patch at http://gcc.gnu.org/ml/gcc-patches/2012-07/msg00817.html for another issue). Maybe it can be enhanced to handle this as well.
I don't see how. The thing is, e.g. lower_stmt resets data->cannot_fallthru on most of the statements, even if it got changed to reset it only on GIMPLE_LABELs (or few selected others), such that say a noreturn call which sets data->cannot_fallthru followed by assignment or another call would keep cannot_fallthru set even when it is currently cleared, on GIMPLE_LABELs we'd need to reset anyway, as we don't have the CFG yet and don't have info how many gotos or other control transfer stmts to each GIMPLE_LABEL there are (and the values of cannot_fallthru at those points). So even just the break; after the __cxa_throw which got gimplified into goto <somelabel>; <somelabel>: would reset cannot_fallthru. And the gimplifier doesn't see break; but already the goto
Created attachment 28744 [details] gcc48-pr54046.patch Actually, with a langhook we can already at the C++ FE level get rid of the warning for most of the cases, similarly how we don't warn for g++.dg/warn/Wreturn-type-7.C (PR20681).
Author: jakub Date: Fri Nov 23 16:04:03 2012 New Revision: 193762 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=193762 Log: PR c++/54046 * Makefile.in (gimple-low.o): Depend on langhooks.h. * gimple-low.c: Include langhooks.c. (block_may_fallthru): Handle TARGET_EXPR and ERROR_MARK, by default call lang_hooks.block_may_fallthru. * langhooks.h (struct lang_hooks): Add block_may_fallthru langhook. * langhooks-def.h (LANG_HOOKS_BLOCK_MAY_FALLTHRU): Define. (LANG_HOOKS_INITIALIZER): Use it. * cp-objcp-common.h (LANG_HOOKS_BLOCK_MAY_FALLTHRU): Redefine. * cp-objcp-common.c (cxx_block_may_fallthru): New function. * cp-tree.h (cxx_block_may_fallthru): New prototype. * g++.dg/warn/Wreturn-type-8.C: New test. Added: trunk/gcc/testsuite/g++.dg/warn/Wreturn-type-8.C Modified: trunk/gcc/ChangeLog trunk/gcc/Makefile.in trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-objcp-common.c trunk/gcc/cp/cp-objcp-common.h trunk/gcc/cp/cp-tree.h trunk/gcc/gimple-low.c trunk/gcc/langhooks-def.h trunk/gcc/langhooks.h trunk/gcc/testsuite/ChangeLog
Author: jakub Date: Fri Feb 1 14:02:33 2013 New Revision: 195651 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195651 Log: Backported from mainline 2012-11-23 Jakub Jelinek <jakub@redhat.com> PR c++/54046 * Makefile.in (gimple-low.o): Depend on langhooks.h. * gimple-low.c: Include langhooks.c. (block_may_fallthru): Handle TARGET_EXPR and ERROR_MARK, by default call lang_hooks.block_may_fallthru. * langhooks.h (struct lang_hooks): Add block_may_fallthru langhook. * langhooks-def.h (LANG_HOOKS_BLOCK_MAY_FALLTHRU): Define. (LANG_HOOKS_INITIALIZER): Use it. * cp-objcp-common.h (LANG_HOOKS_BLOCK_MAY_FALLTHRU): Redefine. * cp-objcp-common.c (cxx_block_may_fallthru): New function. * cp-tree.h (cxx_block_may_fallthru): New prototype. * g++.dg/warn/Wreturn-type-8.C: New test. Added: branches/gcc-4_7-branch/gcc/testsuite/g++.dg/warn/Wreturn-type-8.C Modified: branches/gcc-4_7-branch/gcc/ChangeLog branches/gcc-4_7-branch/gcc/Makefile.in branches/gcc-4_7-branch/gcc/cp/ChangeLog branches/gcc-4_7-branch/gcc/cp/cp-objcp-common.c branches/gcc-4_7-branch/gcc/cp/cp-objcp-common.h branches/gcc-4_7-branch/gcc/cp/cp-tree.h branches/gcc-4_7-branch/gcc/gimple-low.c branches/gcc-4_7-branch/gcc/langhooks-def.h branches/gcc-4_7-branch/gcc/langhooks.h branches/gcc-4_7-branch/gcc/testsuite/ChangeLog
Fixed for 4.7.3+.