This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR c/10175: Fix for -Wunreachable-code


The following patch fixes high priority PR c/10175 which is a
regression for both 3.3 and mainline.  The patch itself is a
variant of my recent "Middle-end dead code elimination" patch
http://gcc.gnu.org/ml/gcc-patches/2003-03/msg02448.html

Many thanks to Steven Bosscher for bringing this GNATS PR to my
attention.  This revision provides an additional argument to
expand_unreachable_stmt that controls whether a warning should
be issued for the first "unreachable" statement in the list.

With this change the testcase reported in the PR, included below
as gcc.c-torture/gcc.dg/Wunreachable-3.c, now correctly reports
warnings for both conditionals.  For brevity, I haven't reposted
the other new testcases, they remain unchanged from the post above.

The following patch has been tested on i686-pc-linux-gnu with a
complete bootstrap, all languages except Ada and treelang, and
regression tested with a top-level "make -k check" with no new
regressions (except for libjava due to timeouts).


Ok for mainline?  If approved, I'll wait a week or so before posting
a version of consideration for the 3.3 release branch, if this
is considered a suitable solution.


2003-03-30  Roger Sayle  <roger at eyesopen dot com>

	PR c/10175
	* 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-3.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.


Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-semantics.c,v
retrieving revision 1.53
diff -c -3 -p -r1.53 c-semantics.c
*** c-semantics.c	22 Feb 2003 00:32:02 -0000	1.53
--- c-semantics.c	30 Mar 2003 17:10:34 -0000
*************** Software Foundation, 59 Temple Place - S
*** 39,44 ****
--- 39,45 ----
  #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.  */
*************** void (*lang_expand_stmt) PARAMS ((tree))
*** 51,56 ****
--- 52,62 ----
     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
*************** genrtl_if_stmt (t)
*** 409,419 ****
    emit_line_note (input_filename, lineno);
    expand_start_cond (cond, 0);
    if (THEN_CLAUSE (t))
!     expand_stmt (THEN_CLAUSE (t));
    if (ELSE_CLAUSE (t))
      {
        expand_start_else ();
!       expand_stmt (ELSE_CLAUSE (t));
      }
    expand_end_cond ();
  }
--- 415,434 ----
    emit_line_note (input_filename, lineno);
    expand_start_cond (cond, 0);
    if (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 ();
!       if (cond && integer_nonzerop (cond))
! 	expand_unreachable_stmt (ELSE_CLAUSE (t), warn_notreached);
!       else
! 	expand_stmt (ELSE_CLAUSE (t));
      }
    expand_end_cond ();
  }
*************** genrtl_switch_stmt (t)
*** 672,678 ****

    emit_line_note (input_filename, lineno);
    expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
!   expand_stmt (SWITCH_BODY (t));
    expand_end_case_type (cond, SWITCH_TYPE (t));
  }

--- 687,693 ----

    emit_line_note (input_filename, lineno);
    expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
!   expand_unreachable_stmt (SWITCH_BODY (t), warn_notreached);
    expand_end_case_type (cond, SWITCH_TYPE (t));
  }

*************** expand_stmt (t)
*** 808,814 ****

  	case RETURN_STMT:
  	  genrtl_return_stmt (t);
! 	  break;

  	case EXPR_STMT:
  	  genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
--- 823,830 ----

  	case RETURN_STMT:
  	  genrtl_return_stmt (t);
! 	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
! 	  return;

  	case EXPR_STMT:
  	  genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
*************** expand_stmt (t)
*** 843,853 ****

  	case BREAK_STMT:
  	  genrtl_break_stmt ();
! 	  break;

  	case CONTINUE_STMT:
  	  genrtl_continue_stmt ();
! 	  break;

  	case SWITCH_STMT:
  	  genrtl_switch_stmt (t);
--- 859,871 ----

  	case BREAK_STMT:
  	  genrtl_break_stmt ();
! 	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
! 	  return;

  	case CONTINUE_STMT:
  	  genrtl_continue_stmt ();
! 	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
! 	  return;

  	case SWITCH_STMT:
  	  genrtl_switch_stmt (t);
*************** expand_stmt (t)
*** 872,878 ****
  	      NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
  	    }
  	  genrtl_goto_stmt (GOTO_DESTINATION (t));
! 	  break;

  	case ASM_STMT:
  	  genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
--- 890,897 ----
  	      NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
  	    }
  	  genrtl_goto_stmt (GOTO_DESTINATION (t));
! 	  expand_unreachable_stmt (TREE_CHAIN (t), warn_notreached);
! 	  return;

  	case ASM_STMT:
  	  genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
*************** expand_stmt (t)
*** 904,906 ****
--- 923,1086 ----
        t = TREE_CHAIN (t);
      }
  }
+
+ /* 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: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1026
diff -c -3 -p -r1.1026 Makefile.in
*** Makefile.in	23 Mar 2003 20:13:50 -0000	1.1026
--- Makefile.in	30 Mar 2003 17:10:35 -0000
*************** c-format.o : c-format.c $(CONFIG_H) $(SY
*** 1330,1336 ****

  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)

  c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
  	$(C_TREE_H) tree-dump.h
--- 1330,1336 ----

  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) 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


/* PR c/10175 */

/* { dg-do compile } */
/* { dg-options "-O2 -Wunreachable-code" } */

int main(void)
{
    int value = 0;

    if (0)
        value = 0;  /* { dg-warning "will never be executed" "" } */
    else
        value = 1;

    if (0) {
        value = 0;  /* { dg-warning "will never be executed" "" } */
        value = 0;
    } else {
        value = 1;
        value = 1;
    }

    return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger at eyesopen dot com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]