re PR c/10175 (-Wunreachable-code doesn't work for single lines)
authorRoger Sayle <roger@eyesopen.com>
Thu, 17 Apr 2003 01:22:51 +0000 (01:22 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Thu, 17 Apr 2003 01:22:51 +0000 (01:22 +0000)
2003-04-16  Roger Sayle  <roger@eyesopen.com>

* c-semantics.c (find_reachable_label): New function to find a
potentially reachable label in an expression.
(expand_unreachable_if_stmt): Similar to expand_if_stmt but
assumes the start of the IF_STMT is unreachable (dead) code.
(expand_unreachable_stmt): Similar to expand_stmt but assumes
the start of the statement list is unreachable (dead) code.
(genrtl_if_stmt):  If the controlling expression of the IF
is constant, use expand_unreachable_stmt for the THEN or ELSE
clause as appropriate.
(genrtl_switch_stmt):  Use expand_unreachable_stmt to expand
the body of a SWITCH statement.
(expand_stmt): The code immediately following a "return",
"break", "continue" or "goto" is unreachable.
* Makefile.in (c-semantics.o): Depend upon tree-inline.h.

* gcc.dg/Wunreachable-5.c: New test case for PR c/10175.
* gcc.c-torture/execute/medce-1.c: New test case.
* gcc.c-torture/execute/medce-2.c: New test case.

From-SVN: r65715

gcc/ChangeLog
gcc/Makefile.in
gcc/c-semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/medce-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/medce-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wunreachable-5.c [new file with mode: 0644]

index 644f928fd26ce7c46cc75a381acb109366e73953..cc4c64290b05600c956ebc8205ab9f8b6389cb95 100644 (file)
@@ -1,3 +1,20 @@
+2003-04-16  Roger Sayle  <roger@eyesopen.com>
+
+       * c-semantics.c (find_reachable_label): New function to find a
+       potentially reachable label in an expression.
+       (expand_unreachable_if_stmt): Similar to expand_if_stmt but
+       assumes the start of the IF_STMT is unreachable (dead) code.
+       (expand_unreachable_stmt): Similar to expand_stmt but assumes
+       the start of the statement list is unreachable (dead) code.
+       (genrtl_if_stmt):  If the controlling expression of the IF
+       is constant, use expand_unreachable_stmt for the THEN or ELSE
+       clause as appropriate.
+       (genrtl_switch_stmt):  Use expand_unreachable_stmt to expand
+       the body of a SWITCH statement.
+       (expand_stmt): The code immediately following a "return",
+       "break", "continue" or "goto" is unreachable.
+       * Makefile.in (c-semantics.o): Depend upon tree-inline.h.
+
 2003-04-16  Richard Henderson  <rth@redhat.com>
 
        * rtl.h (MEM_ALIAS_SET): Update documentation.
index 243828e66b553b63f74c0bc9b94916ebb0a9728a..2e6347e0b5370f31fb6b5fdd16149c10c493a4e3 100644 (file)
@@ -1332,7 +1332,7 @@ c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) la
 
 c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
        $(C_TREE_H) flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
-       $(EXPR_H) $(PREDICT_H)
+       $(EXPR_H) $(PREDICT_H) tree-inline.h
 
 c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
        $(C_TREE_H) tree-dump.h
index 6a81d6e47f2428e2d039019b23834a8cc3396030..2d88144f2d81a2cd06fe73381e9a3e2994fde9ca 100644 (file)
@@ -39,6 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "timevar.h"
 #include "predict.h"
+#include "tree-inline.h"
 
 /* If non-NULL, the address of a language-specific function for
    expanding statements.  */
@@ -51,6 +52,11 @@ void (*lang_expand_stmt) PARAMS ((tree));
    variables and labels do not require any RTL generation.  */
 void (*lang_expand_decl_stmt) PARAMS ((tree));
 
+static tree find_reachable_label_1     PARAMS ((tree *, int *, void *));
+static tree find_reachable_label       PARAMS ((tree));
+static bool expand_unreachable_if_stmt PARAMS ((tree));
+static bool expand_unreachable_stmt    PARAMS ((tree, int));
+
 /* Create an empty statement tree rooted at T.  */
 
 void
@@ -409,11 +415,20 @@ genrtl_if_stmt (t)
   emit_line_note (input_filename, lineno);
   expand_start_cond (cond, 0);
   if (THEN_CLAUSE (t))
-    expand_stmt (THEN_CLAUSE (t));
+    {
+      if (cond && integer_zerop (cond))
+       expand_unreachable_stmt (THEN_CLAUSE (t), warn_notreached);
+      else
+       expand_stmt (THEN_CLAUSE (t));
+    }
+
   if (ELSE_CLAUSE (t))
     {
       expand_start_else ();
-      expand_stmt (ELSE_CLAUSE (t));
+      if (cond && integer_nonzerop (cond))
+       expand_unreachable_stmt (ELSE_CLAUSE (t), warn_notreached);
+      else
+       expand_stmt (ELSE_CLAUSE (t));
     }
   expand_end_cond ();
 }
@@ -672,7 +687,7 @@ genrtl_switch_stmt (t)
 
   emit_line_note (input_filename, lineno);
   expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
-  expand_stmt (SWITCH_BODY (t));
+  expand_unreachable_stmt (SWITCH_BODY (t), warn_notreached);
   expand_end_case_type (cond, SWITCH_TYPE (t));
 }
 
@@ -808,7 +823,8 @@ expand_stmt (t)
 
        case RETURN_STMT:
          genrtl_return_stmt (t);
-         break;
+         expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+         return;
 
        case EXPR_STMT:
          genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
@@ -843,11 +859,13 @@ expand_stmt (t)
 
        case BREAK_STMT:
          genrtl_break_stmt ();
-         break;
+         expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+         return;
 
        case CONTINUE_STMT:
          genrtl_continue_stmt ();
-         break;
+         expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+         return;
 
        case SWITCH_STMT:
          genrtl_switch_stmt (t);
@@ -872,7 +890,8 @@ expand_stmt (t)
              NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
            }
          genrtl_goto_stmt (GOTO_DESTINATION (t));
-         break;
+         expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
+         return;
 
        case ASM_STMT:
          genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
@@ -904,3 +923,164 @@ expand_stmt (t)
       t = TREE_CHAIN (t);
     }
 }
+\f
+/* If *TP is a potentially reachable label, return nonzero.  */
+
+static tree
+find_reachable_label_1 (tp, walk_subtrees, data)
+     tree *tp;
+     int *walk_subtrees ATTRIBUTE_UNUSED;
+     void *data ATTRIBUTE_UNUSED;
+{
+  switch (TREE_CODE (*tp))
+    {
+    case LABEL_STMT:
+    case CASE_LABEL:
+      return *tp;
+
+    default:
+      break;
+    }
+  return NULL_TREE;
+}
+
+/* Determine whether expression EXP contains a potentially
+   reachable label.  */
+static tree
+find_reachable_label (exp)
+     tree exp;
+{
+  int line = lineno;
+  const char *file = input_filename;
+  tree ret = walk_tree (&exp, find_reachable_label_1, NULL, NULL);
+  input_filename = file;
+  lineno = line;
+  return ret;
+}
+
+/* Expand an unreachable if statement, T.  This function returns
+   true if the IF_STMT contains a potentially reachable code_label.  */
+static bool
+expand_unreachable_if_stmt (t)
+     tree t;
+{
+  if (find_reachable_label (IF_COND (t)) != NULL_TREE)
+    {
+      genrtl_if_stmt (t);
+      return true;
+    }
+
+  if (THEN_CLAUSE (t) && ELSE_CLAUSE (t))
+    {
+      if (expand_unreachable_stmt (THEN_CLAUSE (t), 0))
+       {
+         rtx label;
+         label = gen_label_rtx ();
+         emit_jump (label);
+         expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+         emit_label (label);
+         return true;
+       }
+      else
+       return expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+    }
+  else if (THEN_CLAUSE (t))
+    return expand_unreachable_stmt (THEN_CLAUSE (t), 0);
+  else if (ELSE_CLAUSE (t))
+    return expand_unreachable_stmt (ELSE_CLAUSE (t), 0);
+
+  return false;
+}
+
+/* Expand an unreachable statement list.  This function skips all
+   statements preceding the first potentially reachable label and
+   then expands the statements normally with expand_stmt.  This
+   function returns true if such a reachable label was found.  */
+static bool
+expand_unreachable_stmt (t, warn)
+     tree t;
+     int warn;
+{
+  int saved;
+
+  while (t && t != error_mark_node)
+    {
+      if (warn)
+       switch (TREE_CODE (t))
+         {
+         case BREAK_STMT:
+         case CONTINUE_STMT:
+         case EXPR_STMT:
+         case GOTO_STMT:
+         case IF_STMT:
+         case RETURN_STMT:
+           if (!STMT_LINENO_FOR_FN_P (t))
+             lineno = STMT_LINENO (t);
+           warning("will never be executed");
+           warn = false;
+           break;
+
+         default:
+           break;
+         }
+
+      switch (TREE_CODE (t))
+       {
+       case GOTO_STMT:
+       case CONTINUE_STMT:
+       case BREAK_STMT:
+         break;
+
+       case FILE_STMT:
+         input_filename = FILE_STMT_FILENAME (t);
+         break;
+
+       case RETURN_STMT:
+         if (find_reachable_label (RETURN_STMT_EXPR (t)) != NULL_TREE)
+           {
+             expand_stmt (t);
+             return true;
+           }
+         break;
+
+       case EXPR_STMT:
+         if (find_reachable_label (EXPR_STMT_EXPR (t)) != NULL_TREE)
+           {
+             expand_stmt (t);
+             return true;
+           }
+         break;
+
+       case IF_STMT:
+         if (expand_unreachable_if_stmt (t))
+           {
+             expand_stmt (TREE_CHAIN (t));
+             return true;
+           }
+         break;
+
+       case COMPOUND_STMT:
+         if (expand_unreachable_stmt (COMPOUND_BODY (t), warn))
+           {
+             expand_stmt (TREE_CHAIN (t));
+             return true;
+           }
+         warn = false;
+         break;
+
+       case SCOPE_STMT:
+         saved = stmts_are_full_exprs_p ();
+         prep_stmt (t);
+         genrtl_scope_stmt (t);
+         current_stmt_tree ()->stmts_are_full_exprs_p = saved;
+         break;
+
+       default:
+         expand_stmt (t);
+         return true;
+       }
+      t = TREE_CHAIN (t);
+    }
+  return false;
+}
+
index 1a1b86d21daf9a33ed8a009863432ffd320a5e4c..6225ba27fe28173bdb50de9f966ff295b1659a60 100644 (file)
@@ -1,3 +1,9 @@
+2003-04-16  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/Wunreachable-5.c: New test case for PR c/10175.
+       * gcc.c-torture/execute/medce-1.c: New test case.
+       * gcc.c-torture/execute/medce-2.c: New test case.
+
 2003-04-15  Mark Mitchell  <mark@codesourcery.com>
 
        * lib/prune.exp: Ignore more messages.
diff --git a/gcc/testsuite/gcc.c-torture/execute/medce-1.c b/gcc/testsuite/gcc.c-torture/execute/medce-1.c
new file mode 100644 (file)
index 0000000..0c0a772
--- /dev/null
@@ -0,0 +1,33 @@
+
+extern void abort (void);
+extern void link_error (void);
+
+static int ok = 0;
+
+void bar (void)
+{
+  ok = 1;
+}
+
+void foo(int x)
+{
+  switch (x)
+  {
+  case 0:
+    if (0)
+    {
+      link_error();
+  case 1:
+      bar();
+    }
+  }
+}
+
+int main()
+{
+  foo (1);
+  if (!ok)
+    abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/medce-2.c b/gcc/testsuite/gcc.c-torture/execute/medce-2.c
new file mode 100644 (file)
index 0000000..cd83ead
--- /dev/null
@@ -0,0 +1,42 @@
+
+extern void abort ();
+
+static int ok = 0;
+
+int bar(void)
+{
+  ok |= 1;
+  return 1;
+}
+
+void bat(void)
+{
+  ok |= 2;
+}
+
+void baz(void)
+{
+  ok |= 4;
+}
+
+void foo()
+{
+  goto lab;
+
+  if (0)
+  {
+    if (({lab: bar();}))
+      bat ();
+    else
+      baz ();
+  }
+}
+
+int main()
+{
+  foo();
+  if (ok != 3)
+    abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wunreachable-5.c b/gcc/testsuite/gcc.dg/Wunreachable-5.c
new file mode 100644 (file)
index 0000000..11dc320
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR c/10175 */
+
+/* { dg-do compile } */
+/* { dg-options "-Wunreachable-code" } */
+
+int value;
+
+int main(void)
+{
+    if (0)
+        value = 0;  /* { dg-warning "will never be executed" "" } */
+    else
+        value = 1;
+
+    return 0;
+}
+