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]

fix c++/16034


I had assumed there was something in the testsuite that would test
this, and not seeing such a failure assumed that my rewrite worked.

Oh well.  Fixed both problems.


r~



        * c-gimplify.c (gimplify_condition): Remove.
        (gimplify_c_loop, gimplify_if_stmt, gimplify_switch_stmt): Don't
        call it.
cp/
        * semantics.c (begin_cond): New.
        (finish_cond): Rewrite to handle template DECL_STMTs specially.
        Assume that non-template decls go land before the conditional.
        (simplify_loop_decl_cond): Likewise.
        (begin_if_stmt, finish_if_stmt_cond, begin_while_stmt,
        finish_while_stmt_cond, finish_for_init_stmt, finish_for_cond,
        begin_switch_stmt, finish_switch_cond): Update to match.

Index: gcc/c-gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-gimplify.c,v
retrieving revision 2.9
diff -c -p -d -r2.9 c-gimplify.c
*** gcc/c-gimplify.c	17 Jun 2004 01:23:58 -0000	2.9
--- gcc/c-gimplify.c	18 Jun 2004 22:30:48 -0000
*************** static tree gimplify_c_loop (tree, tree,
*** 86,92 ****
  static void push_context (void);
  static void pop_context (void);
  static void add_block_to_enclosing (tree);
- static void gimplify_condition (tree *);
  
  enum bc_t { bc_break = 0, bc_continue = 1 };
  static tree begin_bc_block (enum bc_t);
--- 86,91 ----
*************** gimplify_expr_stmt (tree *stmt_p)
*** 417,439 ****
    return GS_OK;
  }
  
- /* If the condition for a loop (or the like) is a decl, it will be a
-    TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
-    a use of the decl.  Turn such a thing into a COMPOUND_EXPR.  */
- 
- static void
- gimplify_condition (tree *cond_p)
- {
-   tree cond = *cond_p;
-   if (cond && TREE_CODE (cond) == TREE_LIST)
-     {
-       tree decl = TREE_PURPOSE (cond);
-       tree value = TREE_VALUE (cond);
-       gimplify_stmt (&decl);
-       *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
-     }
- }
- 
  /* Begin a scope which can be exited by a break or continue statement.  BC
     indicates which.
  
--- 416,421 ----
*************** gimplify_c_loop (tree cond, tree body, t
*** 548,554 ****
        exit = build_and_jump (&LABEL_EXPR_LABEL (top));
        if (cond)
  	{
- 	  gimplify_condition (&cond);
  	  t = build_bc_goto (bc_break);
  	  exit = build (COND_EXPR, void_type_node, cond, exit, t);
  	  exit = fold (exit);
--- 530,535 ----
*************** gimplify_if_stmt (tree *stmt_p)
*** 647,653 ****
      else_ = build_empty_stmt ();
  
    stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
-   gimplify_condition (& TREE_OPERAND (stmt, 0));
    *stmt_p = stmt;
  
    return GS_OK;
--- 628,633 ----
*************** gimplify_switch_stmt (tree *stmt_p)
*** 664,671 ****
  
    break_block = begin_bc_block (bc_break);
  
-   gimplify_condition (&SWITCH_COND (stmt));
- 
    body = SWITCH_BODY (stmt);
    if (!body)
      body = build_empty_stmt ();
--- 644,649 ----
Index: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.402
diff -c -p -d -r1.402 semantics.c
*** gcc/cp/semantics.c	17 Jun 2004 22:35:53 -0000	1.402
--- gcc/cp/semantics.c	18 Jun 2004 22:30:48 -0000
*************** do_pushlevel (scope_kind sk)
*** 346,413 ****
    return ret;
  }
  
! /* Finish processing a conditional.  COND contains the raw expression;
!    STMT_P is a stacked statement list that will contain any other stmts
!    emitting during the processing of this conditional.  Place the 
!    resulting conditional back in STMT_P.  */
  
  static void
! finish_cond (tree cond, tree *stmt_p)
  {
!   tree stmt = *stmt_p;
!   stmt = pop_stmt_list (stmt);
!   if (TREE_SIDE_EFFECTS (stmt))
      {
!       /* If stmt is set, it will be a DECL_STMT.  When processing a template, 
! 	 using this is enough, because tsubst_expr considers the result of a
! 	 DECL_STMT to be the DECL.  When generating real code, we build a
! 	 funny little TREE_LIST thingy that's handled by the gimplifier.  */
!       /* ??? The object of this thingy is to get the DECL declared in the
! 	 proper scope.  Seems like this oughtn't be terribly hard with the
! 	 new explicit uses of BIND_EXPR and such.  */
!       if (processing_template_decl)
! 	{
! 	  stmt = expr_only (stmt);
! 	  if (!stmt)
! 	    abort ();
! 	}
!       else
!         stmt = build_tree_list (stmt, cond);
      }
!   else
!     stmt = cond;
!   *stmt_p = stmt;
  }
  
  /* If *COND_P specifies a conditional with a declaration, transform the
     loop such that
! 	    while (A x = 42) { }
! 	    for (; A x = 42;) { }
     becomes
! 	    while (true) { A x = 42; if (!x) break; }
! 	    for (;;) { A x = 42; if (!x) break; }
!    The statement list for the loop body should have been pushed.  */
! 
  static void
! simplify_loop_decl_cond (tree *cond_p)
  {
!   tree cond = *cond_p;
!   if (TREE_CODE (cond) == TREE_LIST)
!     {
!       tree if_stmt;
  
!       *cond_p = boolean_true_node;
!   
!       if_stmt = begin_if_stmt ();
!       add_stmt (TREE_PURPOSE (cond));
!       cond = build_unary_op (TRUTH_NOT_EXPR, TREE_VALUE (cond), 0);
!       finish_if_stmt_cond (cond, if_stmt);
!       finish_break_stmt ();
!       finish_then_clause (if_stmt);
!       finish_if_stmt (if_stmt);
!     }
! }
  
  
  /* Finish a goto-statement.  */
  
--- 346,405 ----
    return ret;
  }
  
! /* Begin a conditional that might contain a declaration.  When generating
!    normal code, we want the declaration to appear before the statement
!    containing the conditional.  When generating template code, we want the
!    conditional to be rendered as the raw DECL_STMT.  */
  
  static void
! begin_cond (tree *cond_p)
  {
!   if (processing_template_decl)
!     *cond_p = push_stmt_list ();
! }
! 
! /* Finish such a conditional.  */
! 
! static void
! finish_cond (tree *cond_p, tree expr)
! {
!   if (processing_template_decl)
      {
!       tree cond = pop_stmt_list (*cond_p);
!       if (TREE_CODE (cond) == DECL_STMT)
! 	expr = cond;
      }
!   *cond_p = expr;
  }
  
  /* If *COND_P specifies a conditional with a declaration, transform the
     loop such that
!             while (A x = 42) { }
!             for (; A x = 42;) { }
     becomes
!             while (true) { A x = 42; if (!x) break; }
!             for (;;) { A x = 42; if (!x) break; }
!    The statement list for BODY will be empty if the conditional did
!    not declare anything.  */
!                                                                                 
  static void
! simplify_loop_decl_cond (tree *cond_p, tree body)
  {
!   tree cond, if_stmt;
  
!   if (!TREE_SIDE_EFFECTS (body))
!     return;
  
+   cond = *cond_p;
+   *cond_p = boolean_true_node;
+    
+   if_stmt = begin_if_stmt ();
+   cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
+   finish_if_stmt_cond (cond, if_stmt);
+   finish_break_stmt ();
+   finish_then_clause (if_stmt);
+   finish_if_stmt (if_stmt);
+ }
  
  /* Finish a goto-statement.  */
  
*************** begin_if_stmt (void)
*** 494,501 ****
    scope = do_pushlevel (sk_block);
    r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
    TREE_CHAIN (r) = scope;
!   add_stmt (r);
!   IF_COND (r) = push_stmt_list ();
    return r;
  }
  
--- 486,492 ----
    scope = do_pushlevel (sk_block);
    r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
    TREE_CHAIN (r) = scope;
!   begin_cond (&IF_COND (r));
    return r;
  }
  
*************** begin_if_stmt (void)
*** 505,512 ****
  void 
  finish_if_stmt_cond (tree cond, tree if_stmt)
  {
!   cond = maybe_convert_cond (cond);
!   finish_cond (cond, &IF_COND (if_stmt));
    THEN_CLAUSE (if_stmt) = push_stmt_list ();
  }
  
--- 496,503 ----
  void 
  finish_if_stmt_cond (tree cond, tree if_stmt)
  {
!   finish_cond (&IF_COND (if_stmt), maybe_convert_cond (cond));
!   add_stmt (if_stmt);
    THEN_CLAUSE (if_stmt) = push_stmt_list ();
  }
  
*************** begin_while_stmt (void)
*** 558,564 ****
    r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
    add_stmt (r);
    WHILE_BODY (r) = do_pushlevel (sk_block);
!   WHILE_COND (r) = push_stmt_list ();
    return r;
  }
  
--- 549,555 ----
    r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
    add_stmt (r);
    WHILE_BODY (r) = do_pushlevel (sk_block);
!   begin_cond (&WHILE_COND (r));
    return r;
  }
  
*************** begin_while_stmt (void)
*** 568,576 ****
  void 
  finish_while_stmt_cond (tree cond, tree while_stmt)
  {
!   cond = maybe_convert_cond (cond);
!   finish_cond (cond, &WHILE_COND (while_stmt));
!   simplify_loop_decl_cond (&WHILE_COND (while_stmt));
  }
  
  /* Finish a while-statement, which may be given by WHILE_STMT.  */
--- 559,566 ----
  void 
  finish_while_stmt_cond (tree cond, tree while_stmt)
  {
!   finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond));
!   simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt));
  }
  
  /* Finish a while-statement, which may be given by WHILE_STMT.  */
*************** finish_for_init_stmt (tree for_stmt)
*** 668,674 ****
      FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt));
    add_stmt (for_stmt);
    FOR_BODY (for_stmt) = do_pushlevel (sk_block);
!   FOR_COND (for_stmt) = push_stmt_list ();
  }
  
  /* Finish the COND of a for-statement, which may be given by
--- 658,664 ----
      FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt));
    add_stmt (for_stmt);
    FOR_BODY (for_stmt) = do_pushlevel (sk_block);
!   begin_cond (&FOR_COND (for_stmt));
  }
  
  /* Finish the COND of a for-statement, which may be given by
*************** finish_for_init_stmt (tree for_stmt)
*** 677,686 ****
  void
  finish_for_cond (tree cond, tree for_stmt)
  {
!   cond = maybe_convert_cond (cond);
!   finish_cond (cond, &FOR_COND (for_stmt));
!   if (FOR_COND (for_stmt))
!     simplify_loop_decl_cond (&FOR_COND (for_stmt));
  }
  
  /* Finish the increment-EXPRESSION in a for-statement, which may be
--- 667,674 ----
  void
  finish_for_cond (tree cond, tree for_stmt)
  {
!   finish_cond (&FOR_COND (for_stmt), maybe_convert_cond (cond));
!   simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt));
  }
  
  /* Finish the increment-EXPRESSION in a for-statement, which may be
*************** begin_switch_stmt (void)
*** 747,755 ****
  
    scope = do_pushlevel (sk_block);
    TREE_CHAIN (r) = scope;
! 
!   add_stmt (r);
!   SWITCH_COND (r) = push_stmt_list ();
  
    return r;
  }
--- 735,741 ----
  
    scope = do_pushlevel (sk_block);
    TREE_CHAIN (r) = scope;
!   begin_cond (&SWITCH_COND (r));
  
    return r;
  }
*************** finish_switch_cond (tree cond, tree swit
*** 793,800 ****
  	    cond = index;
  	}
      }
!   finish_cond (cond, &SWITCH_COND (switch_stmt));
    SWITCH_TYPE (switch_stmt) = orig_type;
    push_switch (switch_stmt);
    SWITCH_BODY (switch_stmt) = push_stmt_list ();
  }
--- 779,787 ----
  	    cond = index;
  	}
      }
!   finish_cond (&SWITCH_COND (switch_stmt), cond);
    SWITCH_TYPE (switch_stmt) = orig_type;
+   add_stmt (switch_stmt);
    push_switch (switch_stmt);
    SWITCH_BODY (switch_stmt) = push_stmt_list ();
  }
Index: gcc/testsuite/g++.dg/eh/scope1.C
===================================================================
RCS file: gcc/testsuite/g++.dg/eh/scope1.C
diff -N gcc/testsuite/g++.dg/eh/scope1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/eh/scope1.C	18 Jun 2004 22:30:48 -0000
***************
*** 0 ****
--- 1,71 ----
+ // Test that we've scoped the destructor properly for variables declared
+ // in a conditional.
+ // { dg-do run }
+ 
+ extern "C" void abort ();
+ 
+ class C
+ {
+   bool live;
+  public:
+   C();
+   C(const C &);
+   ~C ();
+   operator bool() const;
+ };
+ 
+ void f1 ()
+ {
+   while (C br = C()) abort ();
+ }
+ 
+ void f2 ()
+ {
+   for (; C br = C(); ) abort ();
+ }
+ 
+ void f3 ()
+ {
+   if (C br = C()) abort ();
+ }
+ 
+ void f4 ()
+ {
+   switch (C br = C())
+     {
+     default:
+       abort ();
+     case false:
+       break;
+     }
+ }
+ 
+ int main()
+ {
+   f1(); f2(); f3(); f4();
+   return 0;
+ }
+ 
+ C::C()
+ {
+   live = true;
+ }
+ 
+ C::C(const C &o)
+ {
+   if (!o.live)
+     abort ();
+   live = true;
+ }
+ 
+ C::~C()
+ {
+   live = false;
+ }
+ 
+ C::operator bool() const
+ {
+   if (!live)
+     abort ();
+   return false;
+ }


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