This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Prevent 'control reaches end of non-void function' warning for DO_WHILE
- From: Tom de Vries <Tom_deVries at mentor dot com>
- To: Jakub Jelinek <jakub at redhat dot com>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 9 Dec 2011 09:38:55 +0100
- Subject: [PATCH] Prevent 'control reaches end of non-void function' warning for DO_WHILE
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 );
+}