Jakub, This patch fixes the problem reported in http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25973#c4 .
The test-case listed there is: ... struct Block { public: Block(); ~Block(); }; bool func( bool bar ) { Block block; bool foo = false; if( !foo || bar ) do { return true; } while( 0 ); else do { return false; } while( 0 ); } ... For O0, a spurious warning is generated: ... $ gcc -O0 -Wreturn-type block.C -S: block.C: In function ‘bool func(bool)’: block.C:17:1: warning: control reaches end of non-void function [-Wreturn-type] ... Basically the patch tries to handle DO_STMT in block_may_fallthru, but since it's a cp-tree.def tree, it's done via a language hook. Improving block_may_fallthru helps code in gimplify.c:shortcut_cond_expr() to prevent the superfluous warning: ... /* We only emit the jump over the else clause if we have to--if the then clause may fall through. Otherwise we can wind up with a useless jump and a useless label at the end of gimplified code, which will cause us to think that this conditional as a whole falls through even if it doesn't. If we then inline a function which ends with such a condition, that can cause us to issue an inappropriate warning about control reaching the end of a non-void function. */ jump_over_else = block_may_fallthru (then_); ... Bootstrapped and reg-tested on x86_64. OK for next stage1? Thanks, - Tom
Index: gcc/langhooks-def.h =================================================================== --- gcc/langhooks-def.h (revision 181172) +++ gcc/langhooks-def.h (working copy) @@ -79,6 +79,8 @@ extern tree lhd_omp_assignment (tree, tr struct gimplify_omp_ctx; extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *, tree); +extern bool lhd_tree_may_fallthru (const_tree); + #define LANG_HOOKS_NAME "GNU unknown" #define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier) @@ -118,6 +120,7 @@ extern void lhd_omp_firstprivatize_type_ #define LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS NULL #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP false #define LANG_HOOKS_DEEP_UNSHARING false +#define LANG_HOOKS_TREE_MAY_FALLTHRU lhd_tree_may_fallthru /* Attribute hooks. */ #define LANG_HOOKS_ATTRIBUTE_TABLE NULL @@ -309,7 +312,8 @@ extern void lhd_end_section (void); LANG_HOOKS_EH_RUNTIME_TYPE, \ LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS, \ LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \ - LANG_HOOKS_DEEP_UNSHARING \ + LANG_HOOKS_DEEP_UNSHARING, \ + LANG_HOOKS_TREE_MAY_FALLTHRU \ } #endif /* GCC_LANG_HOOKS_DEF_H */ Index: gcc/langhooks.h =================================================================== --- gcc/langhooks.h (revision 181172) +++ gcc/langhooks.h (working copy) @@ -473,6 +473,10 @@ struct lang_hooks gimplification. */ bool deep_unsharing; + /* Return false if we cannot continue executing the immediately + following tree. */ + bool (*tree_may_fallthru) (const_tree); + /* Whenever you add entries here, make sure you adjust langhooks-def.h and langhooks.c accordingly. */ }; Index: gcc/langhooks.c =================================================================== --- gcc/langhooks.c (revision 181172) +++ gcc/langhooks.c (working copy) @@ -657,3 +657,12 @@ lhd_end_section (void) saved_section = NULL; } } + +/* Return false if we cannot continue executing the tree immediately + following T. */ + +bool +lhd_tree_may_fallthru (const_tree t ATTRIBUTE_UNUSED) +{ + return true; +} Index: gcc/gimple-low.c =================================================================== --- gcc/gimple-low.c (revision 181172) +++ gcc/gimple-low.c (working copy) @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. #include "function.h" #include "diagnostic-core.h" #include "tree-pass.h" +#include "langhooks.h" /* The differences between High GIMPLE and Low GIMPLE are the following: @@ -680,8 +681,11 @@ block_may_fallthru (const_tree block) case CLEANUP_POINT_EXPR: return block_may_fallthru (TREE_OPERAND (stmt, 0)); - default: + case ERROR_MARK: return true; + + default: + return lang_hooks.tree_may_fallthru (stmt); } } Index: gcc/cp/cp-objcp-common.c =================================================================== --- gcc/cp/cp-objcp-common.c (revision 181172) +++ gcc/cp/cp-objcp-common.c (working copy) @@ -305,4 +305,21 @@ cp_common_init_ts (void) MARK_TS_TYPED (CTOR_INITIALIZER); } +/* Return false if we cannot continue executing the tree immediately + following T. */ + +bool +cp_tree_may_fallthru (const_tree t) +{ + switch (TREE_CODE (t)) + { + case DO_STMT: + /* If DO_BODY doesn't fall thru, then DO_STMT doesn't either. */ + return block_may_fallthru (DO_BODY (t)); + default: + break; + } + return true; +} + #include "gt-cp-cp-objcp-common.h" Index: gcc/cp/cp-objcp-common.h =================================================================== --- gcc/cp/cp-objcp-common.h (revision 181172) +++ gcc/cp/cp-objcp-common.h (working copy) @@ -29,6 +29,7 @@ extern tree objcp_tsubst_copy_and_build extern bool cp_function_decl_explicit_p (tree decl); extern void cp_common_init_ts (void); +extern bool cp_tree_may_fallthru (const_tree); /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, @@ -154,4 +155,7 @@ extern void cp_common_init_ts (void); #undef LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS #define LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS cp_protect_cleanup_actions +#undef LANG_HOOKS_TREE_MAY_FALLTHRU +#define LANG_HOOKS_TREE_MAY_FALLTHRU cp_tree_may_fallthru + #endif /* GCC_CP_OBJCP_COMMON */ Index: gcc/testsuite/g++.dg/pr51264-4.C =================================================================== --- /dev/null (new file) +++ gcc/testsuite/g++.dg/pr51264-4.C (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -Werror -Wreturn-type" } */ + +/* Test-case from http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25973#c4. */ + +struct Block +{ + public: + Block(); + ~Block(); +}; + +bool func( bool bar ) +{ + Block block; + bool foo = false; + + if( !foo || bar ) + do { return true; } while( 0 ); + else + do { return false; } while( 0 ); +}