This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR c/10175: Fix for -Wunreachable-code
- From: Roger Sayle <roger at www dot eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Steven Bosscher <S dot Bosscher at student dot tudelft dot nl>
- Date: Sun, 30 Mar 2003 13:40:37 -0700 (MST)
- Subject: [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