From: Roger Sayle Date: Thu, 17 Apr 2003 01:22:51 +0000 (+0000) Subject: re PR c/10175 (-Wunreachable-code doesn't work for single lines) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=96c6931df4d8809e4adf59a64977ac3889f6560b;p=gcc.git re PR c/10175 (-Wunreachable-code doesn't work for single lines) 2003-04-16 Roger Sayle * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 644f928fd26..cc4c64290b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2003-04-16 Roger Sayle + + * 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 * rtl.h (MEM_ALIAS_SET): Update documentation. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 243828e66b5..2e6347e0b53 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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 diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index 6a81d6e47f2..2d88144f2d8 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -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); } } + +/* 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; +} + diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1a1b86d21da..6225ba27fe2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-04-16 Roger Sayle + + * 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 * 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 index 00000000000..0c0a77274f5 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/medce-1.c @@ -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 index 00000000000..cd83ead2867 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/medce-2.c @@ -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 index 00000000000..11dc3204da1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wunreachable-5.c @@ -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; +} +