summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/c-typeck.c19
-rw-r--r--gcc/gimple-low.c8
-rw-r--r--gcc/gimplify.c19
-rw-r--r--gcc/tree-cfg.c2
-rw-r--r--gcc/tree-inline.c16
6 files changed, 75 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7c07cc430f8..b97af9a6f31 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2005-01-20 Ian Lance Taylor <ian@airs.com>
+
+ PR tree-optimization/13000
+ * tree-inline.c: Include "tree-flow.h".
+ (expand_call_inline): If warn_return_type, warn if non-void inline
+ function falls through.
+ * tree-cfg.c (execute_warn_function_return): Don't warn about
+ control reaching end if TREE_NO_WARNING is set. Set
+ TREE_NO_WARNING.
+ * gimple-low.c (block_may_fallthru): Don't assume that SWITCH_EXPR
+ has been lowered.
+ * gimplify.c (shortcut_cond_expr): Don't emit a jump over the else
+ branch if we don't need one.
+ * c-typeck.c: Include "tree-flow.h"
+ (c_finish_bc_stmt): Don't add a goto if the current statement
+ list doesn't fall through to the current point.
+
2005-01-21 Roger Sayle <roger@eyesopen.com>
PR rtl-optimization/576
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 186cb62bd2a..a4e4bc9df26 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -43,6 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "tree-iterator.h"
#include "tree-gimple.h"
+#include "tree-flow.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
@@ -6762,10 +6763,23 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
tree
c_finish_bc_stmt (tree *label_p, bool is_break)
{
+ bool skip;
tree label = *label_p;
+ /* In switch statements break is sometimes stylistically used after
+ a return statement. This can lead to spurious warnings about
+ control reaching the end of a non-void function when it is
+ inlined. Note that we are calling block_may_fallthru with
+ language specific tree nodes; this works because
+ block_may_fallthru returns true when given something it does not
+ understand. */
+ skip = !block_may_fallthru (cur_stmt_list);
+
if (!label)
- *label_p = label = create_artificial_label ();
+ {
+ if (!skip)
+ *label_p = label = create_artificial_label ();
+ }
else if (TREE_CODE (label) != LABEL_DECL)
{
if (is_break)
@@ -6775,6 +6789,9 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
return NULL_TREE;
}
+ if (skip)
+ return NULL_TREE;
+
return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
}
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index eb495288eee..17ba0393c25 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -278,11 +278,17 @@ block_may_fallthru (tree block)
case GOTO_EXPR:
case RETURN_EXPR:
case RESX_EXPR:
- case SWITCH_EXPR:
/* Easy cases. If the last statement of the block implies
control transfer, then we can't fall through. */
return false;
+ case SWITCH_EXPR:
+ /* If SWITCH_LABELS is set, this is lowered, and represents a
+ branch to a selected label and hence can not fall through.
+ Otherwise SWITCH_BODY is set, and the switch can fall
+ through. */
+ return SWITCH_LABELS (stmt) != NULL_TREE;
+
case COND_EXPR:
if (block_may_fallthru (COND_EXPR_THEN (stmt)))
return true;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 12822c47055..60d35724aaf 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1911,7 +1911,7 @@ shortcut_cond_expr (tree expr)
tree true_label, false_label, end_label, t;
tree *true_label_p;
tree *false_label_p;
- bool emit_end, emit_false;
+ bool emit_end, emit_false, jump_over_else;
bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
@@ -2013,6 +2013,16 @@ shortcut_cond_expr (tree expr)
emit_end = (end_label == NULL_TREE);
emit_false = (false_label == NULL_TREE);
+ /* 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_);
+
pred = shortcut_cond_r (pred, true_label_p, false_label_p);
expr = NULL;
@@ -2021,8 +2031,11 @@ shortcut_cond_expr (tree expr)
append_to_statement_list (then_, &expr);
if (else_se)
{
- t = build_and_jump (&end_label);
- append_to_statement_list (t, &expr);
+ if (jump_over_else)
+ {
+ t = build_and_jump (&end_label);
+ append_to_statement_list (t, &expr);
+ }
if (emit_false)
{
t = build1 (LABEL_EXPR, void_type_node, false_label);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 483b2dd81bd..93dfc343f82 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -5677,6 +5677,7 @@ execute_warn_function_return (void)
/* If we see "return;" in some basic block, then we do reach the end
without returning a value. */
else if (warn_return_type
+ && !TREE_NO_WARNING (cfun->decl)
&& EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (cfun->decl))))
{
@@ -5697,6 +5698,7 @@ execute_warn_function_return (void)
locus = &cfun->function_end_locus;
warning ("%Hcontrol reaches end of non-void function", locus);
#endif
+ TREE_NO_WARNING (cfun->decl) = 1;
break;
}
}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 247c6873e4d..b46276a4e4c 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "cgraph.h"
#include "intl.h"
#include "tree-mudflap.h"
+#include "tree-flow.h"
#include "function.h"
#include "diagnostic.h"
#include "debug.h"
@@ -1607,9 +1608,22 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
function itself. */
{
struct cgraph_node *old_node = id->current_node;
+ tree copy;
id->current_node = edge->callee;
- append_to_statement_list (copy_body (id), &BIND_EXPR_BODY (expr));
+ copy = copy_body (id);
+
+ if (warn_return_type
+ && !TREE_NO_WARNING (fn)
+ && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
+ && block_may_fallthru (copy))
+ {
+ warning ("control may reach end of non-void function %qD being inlined",
+ fn);
+ TREE_NO_WARNING (fn) = 1;
+ }
+
+ append_to_statement_list (copy, &BIND_EXPR_BODY (expr));
id->current_node = old_node;
}
inlined_body = &BIND_EXPR_BODY (expr);