]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/13000 ([unit-at-a-time] Using -O2 cannot detect missing retur...
authorIan Lance Taylor <ian@airs.com>
Fri, 21 Jan 2005 19:05:23 +0000 (19:05 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 21 Jan 2005 19:05:23 +0000 (19:05 +0000)
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.

From-SVN: r94024

gcc/ChangeLog
gcc/c-typeck.c
gcc/gimple-low.c
gcc/gimplify.c
gcc/tree-cfg.c
gcc/tree-inline.c

index 7c07cc430f8becbe0bd7f2be6bfe9558d1d935e9..b97af9a6f31740acc55156767e1d39e9f2f73b79 100644 (file)
@@ -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
index 186cb62bd2a01c841c88be71e845ec1f2026fda7..a4e4bc9df26efb1c08e7f3b8f7d8902d4dc2d6c9 100644 (file)
@@ -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));
 }
 
index eb495288eee539726190a584e80d751094c6e5a6..17ba0393c25bda78f8de13e00f740f3e60d995bd 100644 (file)
@@ -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;
index 12822c4705565772aa4dcffdb2cdc7ebf75989b4..60d35724aaffd9df1a0af3c3aa8f0603bc3ea34e 100644 (file)
@@ -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);
index 483b2dd81bd8107f7ec9fed19de284b3e297b2e5..93dfc343f8289255f3a42a9326e5ef35e22442e8 100644 (file)
@@ -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;
            }
        }
index 247c6873e4d465fced01fc87d263e8ea0458e299..b46276a4e4ce5190f93e12352b78672615bde117 100644 (file)
@@ -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);