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]

[tree-ssa] missing diagnostics for break/continue


I initially began this because I wanted to clean up gimplify_if_stmt,
and have this warning message be generic to the optimizers.

But I also noticed that failure to gimplify sub-trees means that we 
miss diagnosing errors on those subtrees.  So as a correctness issue
we must not eliminate dead conditionals as early as we do.

This bug is also present on mainline, filed as c/13014.  I committed
the test cases there as well.  Eric Christopher has volunteered to
look at fixing the bug there.


r~


Index: gcc/c-simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/c-simplify.c,v
retrieving revision 1.1.4.79
diff -c -p -d -r1.1.4.79 c-simplify.c
*** gcc/c-simplify.c	11 Nov 2003 00:07:18 -0000	1.1.4.79
--- gcc/c-simplify.c	11 Nov 2003 21:45:07 -0000
*************** gimplify_if_stmt (tree *stmt_p)
*** 722,770 ****
    tree else_ = ELSE_CLAUSE (stmt);
    tree cond = IF_COND (stmt);
  
-   /* Avoid generating silly code.  */
-   if (integer_nonzerop (cond))
-     {
-       /* If there are no reachable statements in the ELSE arm, then
-          we can just emit the THEN arm (skipping the conditional).  */
-       if (! find_reachable_label (else_))
-         {
- 	  if (warn_notreached)
- 	    {
- 	      location_t loc;
- 	      loc.file = input_filename;
- 	      loc.line = STMT_LINENO (TREE_CODE (else_) == COMPOUND_STMT
- 				      ? COMPOUND_BODY (else_)
- 				      : else_);
- 	      warning ("%Hwill never be executed", &loc);
- 	    }
- 
- 	  c_gimplify_stmt (&then_);
- 	  *stmt_p = then_;
- 	  return;
-         }
-     }
-   else if (integer_zerop (cond))
-     {
-       /* If there are no reachable statements in the THEN arm, then
-          we can just emit the ELSE arm (skipping the conditional).  */
-       if (! find_reachable_label (then_))
-         {
- 	  if (warn_notreached)
- 	    {
- 	      location_t loc;
- 	      loc.file = input_filename;
- 	      loc.line = STMT_LINENO (TREE_CODE (then_) == COMPOUND_STMT
- 				      ? COMPOUND_BODY (then_)
- 				      : then_);
- 	      warning ("%Hwill never be executed", &loc);
- 	    }
- 	  c_gimplify_stmt (&else_);
- 	  *stmt_p = else_;
- 	  return;
-         }
-     }
- 
    gimplify_condition (&cond);
    c_gimplify_stmt (&then_);
    c_gimplify_stmt (&else_);
--- 722,727 ----
Index: gcc/tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.206
diff -c -p -d -r1.1.4.206 tree-cfg.c
*** gcc/tree-cfg.c	11 Nov 2003 21:08:02 -0000	1.1.4.206
--- gcc/tree-cfg.c	11 Nov 2003 21:45:07 -0000
*************** struct rus_data
*** 862,895 ****
    bool repeat;
    bool may_throw;
    bool may_branch;
  };
  
  static void remove_useless_stmts_1 (tree *, struct rus_data *);
  
  static void
  remove_useless_stmts_cond (tree *stmt_p, struct rus_data *data)
  {
    tree then_clause, else_clause, cond;
  
    remove_useless_stmts_1 (&COND_EXPR_THEN (*stmt_p), data);
    remove_useless_stmts_1 (&COND_EXPR_ELSE (*stmt_p), data);
  
    then_clause = COND_EXPR_THEN (*stmt_p);
    else_clause = COND_EXPR_ELSE (*stmt_p);
    cond = COND_EXPR_COND (*stmt_p);
  
!   /* We may not have been able to completely optimize away the condition
!      previously due to the existence of a label in one arm.  If the label
!      has since become unreachable then we may be able to zap the entire
!      conditional here.  If so, replace the COND_EXPR and set up to repeat
!      this optimization pass.  */
!   if (integer_nonzerop (cond) && IS_EMPTY_STMT (else_clause))
      {
        *stmt_p = then_clause;
!        data->repeat = true;
      }
!   else if (integer_zerop (cond) && IS_EMPTY_STMT (then_clause))
      {
        *stmt_p = else_clause;
        data->repeat = true;
      }
--- 862,960 ----
    bool repeat;
    bool may_throw;
    bool may_branch;
+   bool has_label;
  };
  
  static void remove_useless_stmts_1 (tree *, struct rus_data *);
  
+ static bool
+ remove_useless_stmts_warn_notreached (tree stmt)
+ {
+   if (EXPR_LOCUS (stmt))
+     {
+       warning ("%Hwill never be executed", EXPR_LOCUS (stmt));
+       return true;
+     }
+ 
+   switch (TREE_CODE (stmt))
+     {
+     case COMPOUND_EXPR:
+       {
+ 	tree_stmt_iterator i;
+ 	for (i = tsi_start (&stmt); !tsi_end_p (i); tsi_next (&i))
+ 	  if (remove_useless_stmts_warn_notreached (tsi_stmt (i)))
+ 	    return true;
+       }
+       break;
+ 
+     case COND_EXPR:
+       if (remove_useless_stmts_warn_notreached (COND_EXPR_COND (stmt)))
+ 	return true;
+       if (remove_useless_stmts_warn_notreached (COND_EXPR_THEN (stmt)))
+ 	return true;
+       if (remove_useless_stmts_warn_notreached (COND_EXPR_ELSE (stmt)))
+ 	return true;
+       break;
+ 
+     case TRY_FINALLY_EXPR:
+     case TRY_CATCH_EXPR:
+       if (remove_useless_stmts_warn_notreached (TREE_OPERAND (stmt, 0)))
+ 	return true;
+       if (remove_useless_stmts_warn_notreached (TREE_OPERAND (stmt, 1)))
+ 	return true;
+       break;
+ 
+     case CATCH_EXPR:
+       return remove_useless_stmts_warn_notreached (CATCH_BODY (stmt));
+     case EH_FILTER_EXPR:
+       return remove_useless_stmts_warn_notreached (EH_FILTER_FAILURE (stmt));
+     case BIND_EXPR:
+       return remove_useless_stmts_warn_notreached (BIND_EXPR_BLOCK (stmt));
+ 
+     default:
+       /* Not a live container.  */
+       break;
+     }
+ 
+   return false;
+ }
+ 
  static void
  remove_useless_stmts_cond (tree *stmt_p, struct rus_data *data)
  {
    tree then_clause, else_clause, cond;
+   bool save_has_label, then_has_label, else_has_label;
+ 
+   save_has_label = data->has_label;
+   data->has_label = false;
  
    remove_useless_stmts_1 (&COND_EXPR_THEN (*stmt_p), data);
+ 
+   then_has_label = data->has_label;
+   data->has_label = false;
+ 
    remove_useless_stmts_1 (&COND_EXPR_ELSE (*stmt_p), data);
  
+   else_has_label = data->has_label;
+   data->has_label = save_has_label | then_has_label | else_has_label;
+ 
    then_clause = COND_EXPR_THEN (*stmt_p);
    else_clause = COND_EXPR_ELSE (*stmt_p);
    cond = COND_EXPR_COND (*stmt_p);
  
!   /* If there are no reachable statements in an arm, then we can
!      zap the entire conditional.  */
!   if (integer_nonzerop (cond) && !else_has_label)
      {
+       if (warn_notreached)
+ 	remove_useless_stmts_warn_notreached (else_clause);
        *stmt_p = then_clause;
!       data->repeat = true;
      }
!   else if (integer_zerop (cond) && !then_has_label)
      {
+       if (warn_notreached)
+ 	remove_useless_stmts_warn_notreached (then_clause);
        *stmt_p = else_clause;
        data->repeat = true;
      }
*************** remove_useless_stmts_tc (tree *stmt_p, s
*** 995,1000 ****
--- 1060,1067 ----
    /* If the body cannot throw, then we can drop the entire TRY_CATCH_EXPR.  */
    if (!this_may_throw)
      {
+       if (warn_notreached)
+ 	remove_useless_stmts_warn_notreached (TREE_OPERAND (*stmt_p, 1));
        *stmt_p = TREE_OPERAND (*stmt_p, 0);
        data->repeat = true;
        return;
*************** remove_useless_stmts_1 (tree *first_p, s
*** 1169,1174 ****
--- 1236,1244 ----
  	  break;
  	case GOTO_EXPR:
  	  remove_useless_stmts_goto (i, stmt_p, data);
+ 	  break;
+ 	case LABEL_EXPR:
+ 	  data->has_label = true;
  	  break;
  	case RETURN_EXPR:
  	  data->may_branch = true;
Index: gcc/testsuite/g++.dg/parse/dce1.C
===================================================================
RCS file: gcc/testsuite/g++.dg/parse/dce1.C
diff -N gcc/testsuite/g++.dg/parse/dce1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/parse/dce1.C	11 Nov 2003 21:45:07 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* Make sure that dead code isn't eliminated too early, avoiding 
+    detection of errors.  */
+ /* { dg-do compile } */
+ 
+ void foo(void)
+ {
+   if (0)
+     break;		/* { dg-error "" } */
+   if (1)
+     ;
+   else
+     continue;		/* { dg-error "" } */
+ }
Index: gcc/testsuite/gcc.dg/20031111-1.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/20031111-1.c
diff -N gcc/testsuite/gcc.dg/20031111-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/gcc.dg/20031111-1.c	11 Nov 2003 21:45:07 -0000
***************
*** 0 ****
--- 1,13 ----
+ /* Make sure that dead code isn't eliminated too early, avoiding 
+    detection of errors.  */
+ /* { dg-do compile } */
+ 
+ void foo(void)
+ {
+   if (0)
+     break;		/* { dg-error "" } */
+   if (1)
+     ;
+   else
+     continue;		/* { dg-error "" } */
+ }


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