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]

Remove rtl-level exception handling


Yaye.  All of this is redundant with tree-eh.c.

Tested on i686-linux.


r~



	* except.c (expand_eh_region_start, expand_eh_region_end, 
	expand_eh_handler, expand_eh_region_end_cleanup,
	expand_start_all_catch, expand_start_catch, expand_end_catch,
	expand_end_all_catch, expand_eh_region_end_allowed,
	expand_eh_region_end_must_not_throw, expand_eh_region_end_throw,
	expand_eh_region_end_fixup): Remove.
	* stmt.c (struct nesting): Remove stack_level, innermost_stack_block,
	cleanups, outer_cleanups, label_chain, exception_region.
	(struct goto_fixup): Remove stack_level, cleanup_list_list.
	(struct label_chain): Remove.
	(struct stmt_status): Remove x_stack_block_stack.
	(stack_block_stack, expand_goto_internal, expand_fixup, expand_fixups,
	fixup_gotos, save_stack_pointer, expand_decl_cleanup,
	expand_decl_cleanup_eh, expand_cleanups, start_cleanup_deferral,
	end_cleanup_deferral, last_cleanup_this_contour, 
	containing_blocks_have_cleanups_or_stack_level,
	any_pending_cleanups): Remove.
	(expand_null_return_1): Take no arguments.
	(expand_label, expand_naked_return, expand_return,
	expand_start_bindings_and_block, expand_end_bindings, expand_decl,
	expand_anon_union_decl, expand_start_case, pushcase, pushcase_range,
	expand_end_case_type): Don't use any of them.
	* calls.c (expand_call): Likewise.
	* dojump.c (do_jump): Likewise.
	* function.c (expand_function_end): Likewise.
	* expr.c (store_expr, expand_expr_real_1): Likewise.
	(safe_from_p): Don't handle WITH_CLEANUP_EXPR, CLEANUP_POINT_EXPR.
	(expand_expr_real_1): Don't handle WITH_CLEANUP_EXPR, 
	CLEANUP_POINT_EXPR, TARGET_EXPR, TRY_CATCH_EXPR, CATCH_EXPR, 
	EH_FILTER_EXPR, TRY_FINALLY_EXPR, GOTO_SUBROUTINE_EXPR.
	* fold-const.c (fold_checksum_tree): Use first_rtl_op.
	* gengtype.c (adjust_field_tree_exp): Remove rtl op handling.
	* gimplify.c (gimplify_cleanup_point_expr): Renumber operands
	for WITH_CLEANUP_EXPR.
	(gimple_push_cleanup): Likewise.
	* integrate.c (copy_decl_for_inlining): Don't DECL_TOO_LATE.
	* print-tree.c (print_node): Likewise.
	* tree-pretty-print.c (dump_generic_node): Remove GOTO_SUBROUTINE_EXPR.
	* tree.c (first_rtl_op): Always just TREE_CODE_LENGTH.
	(has_cleanups): Remove GOTO_SUBROUTINE_EXPR.
	* tree.def (WITH_CLEANUP_EXPR): Remove op1 and op2.
	(GOTO_SUBROUTINE_EXPR): Remove.
	* tree.h (WITH_CLEANUP_EXPR_RTL): Remove.
	(DECL_TOO_LATE): Remove.
	* except.h, tree.h: Update decls.
ada/
	* trans.c (gnat_to_gnu <N_Handled_Sequence_Of_Statements>): Update
	commentary.
cp/
	* cp-tree.h (expand_eh_spec_block): Remove.
java/
	* expr.c (case_identity, get_primitive_array_vtable,
	java_expand_expr, emit_init_test_initialization): Remove.
	* java-tree.h (java_expand_expr): Remove.
	* lang.c (LANG_HOOKS_EXPAND_EXPR): Remove.

Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.344
diff -c -p -d -r1.344 calls.c
*** gcc/calls.c	8 Jul 2004 05:58:35 -0000	1.344
--- gcc/calls.c	8 Jul 2004 07:19:32 -0000
*************** expand_call (tree exp, rtx target, int i
*** 2263,2269 ****
        || !flag_optimize_sibling_calls
        || !rtx_equal_function_value_matters
        || current_nesting_level () == 0
-       || any_pending_cleanups ()
        || args_size.var
        || lookup_stmt_eh_region (exp) >= 0)
      try_tail_call = 0;
--- 2263,2268 ----
*************** expand_call (tree exp, rtx target, int i
*** 2343,2352 ****
        /* Do the same for the function address if it is an expression.  */
        if (!fndecl)
          addr = fix_unsafe_tree (addr);
-       /* Expanding one of those dangerous arguments could have added
- 	 cleanups, but otherwise give it a whirl.  */
-       if (any_pending_cleanups ())
- 	try_tail_call = 0;
      }
  
  
--- 2342,2347 ----
*************** expand_call (tree exp, rtx target, int i
*** 2959,2974 ****
  
        /* If value type not void, return an rtx for the value.  */
  
-       /* If there are cleanups to be called, don't use a hard reg as target.
- 	 We need to double check this and see if it matters anymore.  */
-       if (any_pending_cleanups ())
- 	{
- 	  if (target && REG_P (target)
- 	      && REGNO (target) < FIRST_PSEUDO_REGISTER)
- 	    target = 0;
- 	  sibcall_failure = 1;
- 	}
- 
        if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
  	  || ignore)
  	target = const0_rtx;
--- 2954,2959 ----
*************** expand_call (tree exp, rtx target, int i
*** 3222,3228 ****
        clear_pending_stack_adjust ();
        emit_insn (gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx));
        emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx);
-       save_stack_pointer ();
      }
  
    return target;
--- 3207,3212 ----
Index: gcc/dojump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dojump.c,v
retrieving revision 1.22
diff -c -p -d -r1.22 dojump.c
*** gcc/dojump.c	6 Jul 2004 20:01:08 -0000	1.22
--- gcc/dojump.c	8 Jul 2004 07:19:32 -0000
*************** do_jump (tree exp, rtx if_false_label, r
*** 290,307 ****
        if (if_false_label == 0)
          if_false_label = drop_through_label = gen_label_rtx ();
        do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
-       start_cleanup_deferral ();
        do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
-       end_cleanup_deferral ();
        break;
  
      case TRUTH_ORIF_EXPR:
        if (if_true_label == 0)
          if_true_label = drop_through_label = gen_label_rtx ();
        do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
-       start_cleanup_deferral ();
        do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
-       end_cleanup_deferral ();
        break;
  
      case COMPOUND_EXPR:
--- 290,303 ----
*************** do_jump (tree exp, rtx if_false_label, r
*** 362,368 ****
  
          do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
  
-         start_cleanup_deferral ();
          /* Now the THEN-expression.  */
          do_jump (TREE_OPERAND (exp, 1),
                   if_false_label ? if_false_label : drop_through_label,
--- 358,363 ----
*************** do_jump (tree exp, rtx if_false_label, r
*** 375,381 ****
          do_jump (TREE_OPERAND (exp, 2),
             if_false_label ? if_false_label : drop_through_label,
             if_true_label ? if_true_label : drop_through_label);
-         end_cleanup_deferral ();
        }
        break;
  
--- 370,375 ----
Index: gcc/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.276
diff -c -p -d -r1.276 except.c
*** gcc/except.c	18 Jun 2004 01:20:51 -0000	1.276
--- gcc/except.c	8 Jul 2004 07:19:32 -0000
*************** static hashval_t t2r_hash (const void *)
*** 260,267 ****
  static void add_type_for_runtime (tree);
  static tree lookup_type_for_runtime (tree);
  
- static struct eh_region *expand_eh_region_end (void);
- 
  static void resolve_fixup_regions (void);
  static void remove_fixup_regions (void);
  static void remove_unreachable_regions (rtx);
--- 260,265 ----
*************** set_eh_region_tree_label (struct eh_regi
*** 574,714 ****
    region->tree_label = lab;
  }
  
- /* Start an exception handling region.  All instructions emitted
-    after this point are considered to be part of the region until
-    expand_eh_region_end is invoked.  */
- 
- void
- expand_eh_region_start (void)
- {
-   struct eh_region *new;
-   rtx note;
- 
-   if (! doing_eh (0))
-     return;
- 
-   new = gen_eh_region (ERT_UNKNOWN, cfun->eh->cur_region);
-   cfun->eh->cur_region = new;
- 
-   /* Create a note marking the start of this region.  */
-   note = emit_note (NOTE_INSN_EH_REGION_BEG);
-   NOTE_EH_HANDLER (note) = new->region_number;
- }
- 
- /* Common code to end a region.  Returns the region just ended.  */
- 
- static struct eh_region *
- expand_eh_region_end (void)
- {
-   struct eh_region *cur_region = cfun->eh->cur_region;
-   rtx note;
- 
-   /* Create a note marking the end of this region.  */
-   note = emit_note (NOTE_INSN_EH_REGION_END);
-   NOTE_EH_HANDLER (note) = cur_region->region_number;
- 
-   /* Pop.  */
-   cfun->eh->cur_region = cur_region->outer;
- 
-   return cur_region;
- }
- 
- /* Expand HANDLER, which is the operand 1 of a TRY_CATCH_EXPR.  Catch
-    blocks and C++ exception-specifications are handled specially.  */
- 
- void
- expand_eh_handler (tree handler)
- {
-   tree inner = expr_first (handler);
- 
-   switch (TREE_CODE (inner))
-     {
-     case CATCH_EXPR:
-       expand_start_all_catch ();
-       expand_expr (handler, const0_rtx, VOIDmode, 0);
-       expand_end_all_catch ();
-       break;
- 
-     case EH_FILTER_EXPR:
-       if (EH_FILTER_MUST_NOT_THROW (handler))
- 	expand_eh_region_end_must_not_throw (EH_FILTER_FAILURE (handler));
-       else
- 	expand_eh_region_end_allowed (EH_FILTER_TYPES (handler),
- 				      EH_FILTER_FAILURE (handler));
-       break;
- 
-     default:
-       expand_eh_region_end_cleanup (handler);
-       break;
-     }
- }
- 
- /* End an exception handling region for a cleanup.  HANDLER is an
-    expression to expand for the cleanup.  */
- 
- void
- expand_eh_region_end_cleanup (tree handler)
- {
-   struct eh_region *region;
-   tree protect_cleanup_actions;
-   rtx around_label;
-   rtx data_save[2];
- 
-   if (! doing_eh (0))
-     return;
- 
-   region = expand_eh_region_end ();
-   region->type = ERT_CLEANUP;
-   region->label = gen_label_rtx ();
-   region->u.cleanup.exp = handler;
-   region->u.cleanup.prev_try = cfun->eh->try_region;
- 
-   around_label = gen_label_rtx ();
-   emit_jump (around_label);
- 
-   emit_label (region->label);
- 
-   if (flag_non_call_exceptions || region->may_contain_throw)
-     {
-       /* Give the language a chance to specify an action to be taken if an
- 	 exception is thrown that would propagate out of the HANDLER.  */
-       protect_cleanup_actions
- 	= (lang_protect_cleanup_actions
- 	   ? (*lang_protect_cleanup_actions) ()
- 	   : NULL_TREE);
- 
-       if (protect_cleanup_actions)
- 	expand_eh_region_start ();
- 
-       /* In case this cleanup involves an inline destructor with a try block in
- 	 it, we need to save the EH return data registers around it.  */
-       data_save[0] = gen_reg_rtx (ptr_mode);
-       emit_move_insn (data_save[0], get_exception_pointer (cfun));
-       data_save[1] = gen_reg_rtx (word_mode);
-       emit_move_insn (data_save[1], get_exception_filter (cfun));
- 
-       expand_expr (handler, const0_rtx, VOIDmode, 0);
- 
-       emit_move_insn (cfun->eh->exc_ptr, data_save[0]);
-       emit_move_insn (cfun->eh->filter, data_save[1]);
- 
-       if (protect_cleanup_actions)
- 	expand_eh_region_end_must_not_throw (protect_cleanup_actions);
- 
-       /* We need any stack adjustment complete before the around_label.  */
-       do_pending_stack_adjust ();
-     }
- 
-   /* We delay the generation of the _Unwind_Resume until we generate
-      landing pads.  We emit a marker here so as to get good control
-      flow data in the meantime.  */
-   region->resume
-     = emit_jump_insn (gen_rtx_RESX (VOIDmode, region->region_number));
-   emit_barrier ();
- 
-   emit_label (around_label);
- }
- 
  void
  expand_resx_expr (tree exp)
  {
--- 572,577 ----
*************** expand_resx_expr (tree exp)
*** 719,915 ****
    emit_barrier ();
  }
  
- /* End an exception handling region for a try block, and prepares
-    for subsequent calls to expand_start_catch.  */
- 
- void
- expand_start_all_catch (void)
- {
-   struct eh_region *region;
- 
-   if (! doing_eh (1))
-     return;
- 
-   region = expand_eh_region_end ();
-   region->type = ERT_TRY;
-   region->u.try.prev_try = cfun->eh->try_region;
-   region->u.try.continue_label = gen_label_rtx ();
- 
-   cfun->eh->try_region = region;
- 
-   emit_jump (region->u.try.continue_label);
- }
- 
- /* Begin a catch clause.  TYPE is the type caught, a list of such
-    types, (in the case of Java) an ADDR_EXPR which points to the
-    runtime type to match, or null if this is a catch-all
-    clause. Providing a type list enables to associate the catch region
-    with potentially several exception types, which is useful e.g. for
-    Ada.  */
- 
- void
- expand_start_catch (tree type_or_list)
- {
-   struct eh_region *c;
-   rtx note;
- 
-   if (! doing_eh (0))
-     return;
- 
-   c = gen_eh_region_catch (cfun->eh->try_region, type_or_list);
-   cfun->eh->cur_region = c;
- 
-   c->label = gen_label_rtx ();
-   emit_label (c->label);
- 
-   note = emit_note (NOTE_INSN_EH_REGION_BEG);
-   NOTE_EH_HANDLER (note) = c->region_number;
- }
- 
- /* End a catch clause.  Control will resume after the try/catch block.  */
- 
- void
- expand_end_catch (void)
- {
-   if (! doing_eh (0))
-     return;
- 
-   expand_eh_region_end ();
-   emit_jump (cfun->eh->try_region->u.try.continue_label);
- }
- 
- /* End a sequence of catch handlers for a try block.  */
- 
- void
- expand_end_all_catch (void)
- {
-   struct eh_region *try_region;
- 
-   if (! doing_eh (0))
-     return;
- 
-   try_region = cfun->eh->try_region;
-   cfun->eh->try_region = try_region->u.try.prev_try;
- 
-   emit_label (try_region->u.try.continue_label);
- }
- 
- /* End an exception region for an exception type filter.  ALLOWED is a
-    TREE_LIST of types to be matched by the runtime.  FAILURE is an
-    expression to invoke if a mismatch occurs.
- 
-    ??? We could use these semantics for calls to rethrow, too; if we can
-    see the surrounding catch clause, we know that the exception we're
-    rethrowing satisfies the "filter" of the catch type.  */
- 
- void
- expand_eh_region_end_allowed (tree allowed, tree failure)
- {
-   struct eh_region *region;
-   rtx around_label;
- 
-   if (! doing_eh (0))
-     return;
- 
-   region = expand_eh_region_end ();
-   region->type = ERT_ALLOWED_EXCEPTIONS;
-   region->u.allowed.type_list = allowed;
-   region->label = gen_label_rtx ();
- 
-   for (; allowed ; allowed = TREE_CHAIN (allowed))
-     add_type_for_runtime (TREE_VALUE (allowed));
- 
-   /* We must emit the call to FAILURE here, so that if this function
-      throws a different exception, that it will be processed by the
-      correct region.  */
- 
-   around_label = gen_label_rtx ();
-   emit_jump (around_label);
- 
-   emit_label (region->label);
-   expand_expr (failure, const0_rtx, VOIDmode, EXPAND_NORMAL);
-   /* We must adjust the stack before we reach the AROUND_LABEL because
-      the call to FAILURE does not occur on all paths to the
-      AROUND_LABEL.  */
-   do_pending_stack_adjust ();
- 
-   emit_label (around_label);
- }
- 
- /* End an exception region for a must-not-throw filter.  FAILURE is an
-    expression invoke if an uncaught exception propagates this far.
- 
-    This is conceptually identical to expand_eh_region_end_allowed with
-    an empty allowed list (if you passed "std::terminate" instead of
-    "__cxa_call_unexpected"), but they are represented differently in
-    the C++ LSDA.  */
- 
- void
- expand_eh_region_end_must_not_throw (tree failure)
- {
-   struct eh_region *region;
-   rtx around_label;
- 
-   if (! doing_eh (0))
-     return;
- 
-   region = expand_eh_region_end ();
-   region->type = ERT_MUST_NOT_THROW;
-   region->label = gen_label_rtx ();
- 
-   /* We must emit the call to FAILURE here, so that if this function
-      throws a different exception, that it will be processed by the
-      correct region.  */
- 
-   around_label = gen_label_rtx ();
-   emit_jump (around_label);
- 
-   emit_label (region->label);
-   expand_expr (failure, const0_rtx, VOIDmode, EXPAND_NORMAL);
- 
-   emit_label (around_label);
- }
- 
- /* End an exception region for a throw.  No handling goes on here,
-    but it's the easiest way for the front-end to indicate what type
-    is being thrown.  */
- 
- void
- expand_eh_region_end_throw (tree type)
- {
-   struct eh_region *region;
- 
-   if (! doing_eh (0))
-     return;
- 
-   region = expand_eh_region_end ();
-   region->type = ERT_THROW;
-   region->u.throw.type = type;
- }
- 
- /* End a fixup region.  Within this region the cleanups for the immediately
-    enclosing region are _not_ run.  This is used for goto cleanup to avoid
-    destroying an object twice.
- 
-    This would be an extraordinarily simple prospect, were it not for the
-    fact that we don't actually know what the immediately enclosing region
-    is.  This surprising fact is because expand_cleanups is currently
-    generating a sequence that it will insert somewhere else.  We collect
-    the proper notion of "enclosing" in convert_from_eh_region_ranges.  */
- 
- void
- expand_eh_region_end_fixup (tree handler)
- {
-   struct eh_region *fixup;
- 
-   if (! doing_eh (0))
-     return;
- 
-   fixup = expand_eh_region_end ();
-   fixup->type = ERT_FIXUP;
-   fixup->u.fixup.cleanup_exp = handler;
- }
- 
  /* Note that the current EH region (if any) may contain a throw, or a
     call to a function which itself may contain a throw.  */
  
--- 582,587 ----
*************** get_exception_filter (struct function *f
*** 962,970 ****
  
  /* This section is for the exception handling specific optimization pass.  */
  
! /* Random access the exception region tree.  It's just as simple to
!    collect the regions this way as in expand_eh_region_start, but
!    without having to realloc memory.  */
  
  void
  collect_eh_region_array (void)
--- 634,640 ----
  
  /* This section is for the exception handling specific optimization pass.  */
  
! /* Random access the exception region tree.  */
  
  void
  collect_eh_region_array (void)
Index: gcc/except.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.h,v
retrieving revision 1.76
diff -c -p -d -r1.76 except.h
*** gcc/except.h	4 Jun 2004 12:31:26 -0000	1.76
--- gcc/except.h	8 Jul 2004 07:19:32 -0000
*************** struct eh_region;
*** 35,86 ****
  /* Test: is exception handling turned on?  */
  extern int doing_eh (int);
  
- /* Start an exception handling region.  All instructions emitted after
-    this point are considered to be part of the region until an
-    expand_eh_region_end variant is invoked.  */
- extern void expand_eh_region_start (void);
- 
- /* End an exception handling region for a cleanup.  HANDLER is an
-    expression to expand for the cleanup.  */
- extern void expand_eh_region_end_cleanup (tree);
- 
- /* End an exception handling region for a try block, and prepares
-    for subsequent calls to expand_start_catch.  */
- extern void expand_start_all_catch (void);
- 
- /* Begin a catch clause.  TYPE is an object to be matched by the
-    runtime, or a list of such objects, or null if this is a catch-all
-    clause.  */
- extern void expand_start_catch (tree);
- 
- /* End a catch clause.  Control will resume after the try/catch block.  */
- extern void expand_end_catch (void);
- 
- /* End a sequence of catch handlers for a try block.  */
- extern void expand_end_all_catch (void);
- 
- /* End an exception region for an exception type filter.  ALLOWED is a
-    TREE_LIST of TREE_VALUE objects to be matched by the runtime.
-    FAILURE is a function to invoke if a mismatch occurs.  */
- extern void expand_eh_region_end_allowed (tree, tree);
- 
- /* End an exception region for a must-not-throw filter.  FAILURE is a
-    function to invoke if an uncaught exception propagates this far.  */
- extern void expand_eh_region_end_must_not_throw (tree);
- 
- /* End an exception region for a throw.  No handling goes on here,
-    but it's the easiest way for the front-end to indicate what type
-    is being thrown.  */
- extern void expand_eh_region_end_throw (tree);
- 
- /* End a fixup region.  Within this region the cleanups for the immediately
-    enclosing region are _not_ run.  This is used for goto cleanup to avoid
-    destroying an object twice.  */
- extern void expand_eh_region_end_fixup (tree);
- 
- /* End some sort of EH region, depending on the argument.  */
- extern void expand_eh_handler (tree);
- 
  /* Note that the current EH region (if any) may contain a throw, or a
     call to a function which itself may contain a throw.  */
  extern void note_eh_region_may_contain_throw (struct eh_region *);
--- 35,40 ----
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.672
diff -c -p -d -r1.672 expr.c
*** gcc/expr.c	7 Jul 2004 21:26:28 -0000	1.672
--- gcc/expr.c	8 Jul 2004 07:19:33 -0000
*************** store_expr (tree exp, rtx target, int wa
*** 4071,4086 ****
        do_pending_stack_adjust ();
        NO_DEFER_POP;
        jumpifnot (TREE_OPERAND (exp, 0), lab1);
-       start_cleanup_deferral ();
        store_expr (TREE_OPERAND (exp, 1), target, want_value & 2);
-       end_cleanup_deferral ();
        emit_queue ();
        emit_jump_insn (gen_jump (lab2));
        emit_barrier ();
        emit_label (lab1);
-       start_cleanup_deferral ();
        store_expr (TREE_OPERAND (exp, 2), target, want_value & 2);
-       end_cleanup_deferral ();
        emit_queue ();
        emit_label (lab2);
        OK_DEFER_POP;
--- 4071,4082 ----
*************** safe_from_p (rtx x, tree exp, int top_p)
*** 6042,6051 ****
  	  break;
  
  	case WITH_CLEANUP_EXPR:
- 	  exp_rtl = WITH_CLEANUP_EXPR_RTL (exp);
- 	  break;
- 
  	case CLEANUP_POINT_EXPR:
  	case SAVE_EXPR:
  	  return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
  
--- 6038,6047 ----
  	  break;
  
  	case WITH_CLEANUP_EXPR:
  	case CLEANUP_POINT_EXPR:
+ 	  /* Lowered by gimplify.c.  */
+ 	  abort ();
+ 
  	case SAVE_EXPR:
  	  return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
  
*************** expand_expr_real_1 (tree exp, rtx target
*** 7345,7380 ****
      case OBJ_TYPE_REF:
        return expand_expr (OBJ_TYPE_REF_EXPR (exp), target, tmode, modifier);
  
-     case WITH_CLEANUP_EXPR:
-       if (WITH_CLEANUP_EXPR_RTL (exp) == 0)
- 	{
- 	  WITH_CLEANUP_EXPR_RTL (exp)
- 	    = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
- 	  expand_decl_cleanup_eh (NULL_TREE, TREE_OPERAND (exp, 1),
- 				  CLEANUP_EH_ONLY (exp));
- 
- 	  /* That's it for this cleanup.  */
- 	  TREE_OPERAND (exp, 1) = 0;
- 	}
-       return WITH_CLEANUP_EXPR_RTL (exp);
- 
-     case CLEANUP_POINT_EXPR:
-       {
- 	/* Start a new binding layer that will keep track of all cleanup
- 	   actions to be performed.  */
- 	expand_start_bindings (2);
- 
- 	target_temp_slot_level = temp_slot_level;
- 
- 	op0 = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
- 	/* If we're going to use this value, load it up now.  */
- 	if (! ignore)
- 	  op0 = force_not_mem (op0);
- 	preserve_temp_slots (op0);
- 	expand_end_bindings (NULL_TREE, 0, 0);
-       }
-       return op0;
- 
      case CALL_EXPR:
        /* Check for a built-in function.  */
        if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
--- 7341,7346 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8180,8194 ****
  	  tree then_ = TREE_OPERAND (exp, 1);
  	  tree else_ = TREE_OPERAND (exp, 2);
  
! 	  /* If we do not have any pending cleanups or stack_levels
! 	     to restore, and at least one arm of the COND_EXPR is a
! 	     GOTO_EXPR to a local label, then we can emit more efficient
! 	     code by using jumpif/jumpifnot instead of the 'if' machinery.  */
! 	  if (! optimize
! 	      || containing_blocks_have_cleanups_or_stack_level ())
! 	    ;
! 	  else if (TREE_CODE (then_) == GOTO_EXPR
! 		   && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
  	    {
  	      jumpif (pred, label_rtx (GOTO_DESTINATION (then_)));
  	      return expand_expr (else_, const0_rtx, VOIDmode, 0);
--- 8146,8153 ----
  	  tree then_ = TREE_OPERAND (exp, 1);
  	  tree else_ = TREE_OPERAND (exp, 2);
  
! 	  if (TREE_CODE (then_) == GOTO_EXPR
! 	      && TREE_CODE (GOTO_DESTINATION (then_)) == LABEL_DECL)
  	    {
  	      jumpif (pred, label_rtx (GOTO_DESTINATION (then_)));
  	      return expand_expr (else_, const0_rtx, VOIDmode, 0);
*************** expand_expr_real_1 (tree exp, rtx target
*** 8202,8208 ****
  
  	  /* Just use the 'if' machinery.  */
  	  expand_start_cond (pred, 0);
- 	  start_cleanup_deferral ();
  	  expand_expr (then_, const0_rtx, VOIDmode, 0);
  
  	  exp = else_;
--- 8161,8166 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8225,8231 ****
  	      expand_start_else ();
  	      expand_expr (exp, const0_rtx, VOIDmode, 0);
  	    }
- 	  end_cleanup_deferral ();
  	  expand_end_cond ();
  	  return const0_rtx;
  	}
--- 8183,8188 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8422,8428 ****
  	    else
  	      jumpifnot (TREE_OPERAND (exp, 0), op0);
  
- 	    start_cleanup_deferral ();
  	    if (binary_op && temp == 0)
  	      /* Just touch the other operand.  */
  	      expand_expr (TREE_OPERAND (binary_op, 1),
--- 8379,8384 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8458,8464 ****
  			modifier == EXPAND_STACK_PARM ? 2 : 0);
  	    jumpif (TREE_OPERAND (exp, 0), op0);
  
- 	    start_cleanup_deferral ();
  	    if (TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
  	      store_expr (TREE_OPERAND (exp, 2), temp,
  			  modifier == EXPAND_STACK_PARM ? 2 : 0);
--- 8414,8419 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8483,8489 ****
  			modifier == EXPAND_STACK_PARM ? 2 : 0);
  	    jumpifnot (TREE_OPERAND (exp, 0), op0);
  
- 	    start_cleanup_deferral ();
  	    if (TREE_TYPE (TREE_OPERAND (exp, 1)) != void_type_node)
  	      store_expr (TREE_OPERAND (exp, 1), temp,
  			  modifier == EXPAND_STACK_PARM ? 2 : 0);
--- 8438,8443 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8497,8504 ****
  	    op1 = gen_label_rtx ();
  	    jumpifnot (TREE_OPERAND (exp, 0), op0);
  
- 	    start_cleanup_deferral ();
- 
  	    /* One branch of the cond can be void, if it never returns. For
  	       example A ? throw : E  */
  	    if (temp != 0
--- 8451,8456 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8508,8519 ****
  	    else
  	      expand_expr (TREE_OPERAND (exp, 1),
  			   ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
- 	    end_cleanup_deferral ();
  	    emit_queue ();
  	    emit_jump_insn (gen_jump (op1));
  	    emit_barrier ();
  	    emit_label (op0);
- 	    start_cleanup_deferral ();
  	    if (temp != 0
  		&& TREE_TYPE (TREE_OPERAND (exp, 2)) != void_type_node)
  	      store_expr (TREE_OPERAND (exp, 2), temp,
--- 8460,8469 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8523,8530 ****
  			   ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
  	  }
  
- 	end_cleanup_deferral ();
- 
  	emit_queue ();
  	emit_label (op1);
  	OK_DEFER_POP;
--- 8473,8478 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8532,8629 ****
  	return temp;
        }
  
-     case TARGET_EXPR:
-       {
- 	/* Something needs to be initialized, but we didn't know
- 	   where that thing was when building the tree.  For example,
- 	   it could be the return value of a function, or a parameter
- 	   to a function which lays down in the stack, or a temporary
- 	   variable which must be passed by reference.
- 
- 	   We guarantee that the expression will either be constructed
- 	   or copied into our original target.  */
- 
- 	tree slot = TREE_OPERAND (exp, 0);
- 	tree cleanups = NULL_TREE;
- 	tree exp1;
- 
- 	if (TREE_CODE (slot) != VAR_DECL)
- 	  abort ();
- 
- 	if (! ignore)
- 	  target = original_target;
- 
- 	/* Set this here so that if we get a target that refers to a
- 	   register variable that's already been used, put_reg_into_stack
- 	   knows that it should fix up those uses.  */
- 	TREE_USED (slot) = 1;
- 
- 	if (target == 0)
- 	  {
- 	    if (DECL_RTL_SET_P (slot))
- 	      {
- 		target = DECL_RTL (slot);
- 		/* If we have already expanded the slot, so don't do
- 		   it again.  (mrs)  */
- 		if (TREE_OPERAND (exp, 1) == NULL_TREE)
- 		  return target;
- 	      }
- 	    else
- 	      {
- 		target = assign_temp (type, 2, 0, 1);
- 		SET_DECL_RTL (slot, target);
- 
- 		/* Since SLOT is not known to the called function
- 		   to belong to its stack frame, we must build an explicit
- 		   cleanup.  This case occurs when we must build up a reference
- 		   to pass the reference as an argument.  In this case,
- 		   it is very likely that such a reference need not be
- 		   built here.  */
- 
- 		if (TREE_OPERAND (exp, 2) == 0)
- 		  TREE_OPERAND (exp, 2)
- 		    = lang_hooks.maybe_build_cleanup (slot);
- 		cleanups = TREE_OPERAND (exp, 2);
- 	      }
- 	  }
- 	else
- 	  {
- 	    /* This case does occur, when expanding a parameter which
- 	       needs to be constructed on the stack.  The target
- 	       is the actual stack address that we want to initialize.
- 	       The function we call will perform the cleanup in this case.  */
- 
- 	    /* If we have already assigned it space, use that space,
- 	       not target that we were passed in, as our target
- 	       parameter is only a hint.  */
- 	    if (DECL_RTL_SET_P (slot))
- 	      {
- 		target = DECL_RTL (slot);
- 		/* If we have already expanded the slot, so don't do
-                    it again.  (mrs)  */
- 		if (TREE_OPERAND (exp, 1) == NULL_TREE)
- 		  return target;
- 	      }
- 	    else
- 	      SET_DECL_RTL (slot, target);
- 	  }
- 
- 	exp1 = TREE_OPERAND (exp, 3) = TREE_OPERAND (exp, 1);
- 	/* Mark it as expanded.  */
- 	TREE_OPERAND (exp, 1) = NULL_TREE;
- 
- 	if (VOID_TYPE_P (TREE_TYPE (exp1)))
- 	  /* If the initializer is void, just expand it; it will initialize
- 	     the object directly.  */
- 	  expand_expr (exp1, const0_rtx, VOIDmode, 0);
- 	else
- 	  store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
- 
- 	expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
- 
- 	return target;
-       }
- 
      case INIT_EXPR:
        {
  	tree lhs = TREE_OPERAND (exp, 0);
--- 8480,8485 ----
*************** expand_expr_real_1 (tree exp, rtx target
*** 8927,9020 ****
        return const0_rtx;
  
      case TRY_CATCH_EXPR:
-       {
- 	tree handler = TREE_OPERAND (exp, 1);
- 
- 	expand_eh_region_start ();
- 	op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
- 	expand_eh_handler (handler);
- 
- 	return op0;
-       }
- 
      case CATCH_EXPR:
-       expand_start_catch (CATCH_TYPES (exp));
-       expand_expr (CATCH_BODY (exp), const0_rtx, VOIDmode, 0);
-       expand_end_catch ();
-       return const0_rtx;
- 
      case EH_FILTER_EXPR:
-       /* Should have been handled in expand_eh_handler.  */
-       abort ();
- 
      case TRY_FINALLY_EXPR:
!       {
! 	tree try_block = TREE_OPERAND (exp, 0);
! 	tree finally_block = TREE_OPERAND (exp, 1);
! 
!         if ((!optimize && lang_protect_cleanup_actions == NULL)
! 	    || unsafe_for_reeval (finally_block) > 1)
! 	  {
! 	    /* In this case, wrapping FINALLY_BLOCK in an UNSAVE_EXPR
! 	       is not sufficient, so we cannot expand the block twice.
! 	       So we play games with GOTO_SUBROUTINE_EXPR to let us
! 	       expand the thing only once.  */
! 	    /* When not optimizing, we go ahead with this form since
! 	       (1) user breakpoints operate more predictably without
! 		   code duplication, and
! 	       (2) we're not running any of the global optimizers
! 	           that would explode in time/space with the highly
! 		   connected CFG created by the indirect branching.  */
! 
! 	    rtx finally_label = gen_label_rtx ();
! 	    rtx done_label = gen_label_rtx ();
! 	    rtx return_link = gen_reg_rtx (Pmode);
! 	    tree cleanup = build (GOTO_SUBROUTINE_EXPR, void_type_node,
! 			          (tree) finally_label, (tree) return_link);
! 	    TREE_SIDE_EFFECTS (cleanup) = 1;
! 
! 	    /* Start a new binding layer that will keep track of all cleanup
! 	       actions to be performed.  */
! 	    expand_start_bindings (2);
! 	    target_temp_slot_level = temp_slot_level;
! 
! 	    expand_decl_cleanup (NULL_TREE, cleanup);
! 	    op0 = expand_expr (try_block, target, tmode, modifier);
! 
! 	    preserve_temp_slots (op0);
! 	    expand_end_bindings (NULL_TREE, 0, 0);
! 	    emit_jump (done_label);
! 	    emit_label (finally_label);
! 	    expand_expr (finally_block, const0_rtx, VOIDmode, 0);
! 	    emit_indirect_jump (return_link);
! 	    emit_label (done_label);
! 	  }
! 	else
! 	  {
! 	    expand_start_bindings (2);
! 	    target_temp_slot_level = temp_slot_level;
! 
! 	    expand_decl_cleanup (NULL_TREE, finally_block);
! 	    op0 = expand_expr (try_block, target, tmode, modifier);
! 
! 	    preserve_temp_slots (op0);
! 	    expand_end_bindings (NULL_TREE, 0, 0);
! 	  }
! 
! 	return op0;
!       }
  
!     case GOTO_SUBROUTINE_EXPR:
!       {
! 	rtx subr = (rtx) TREE_OPERAND (exp, 0);
! 	rtx return_link = *(rtx *) &TREE_OPERAND (exp, 1);
! 	rtx return_address = gen_label_rtx ();
! 	emit_move_insn (return_link,
! 			gen_rtx_LABEL_REF (Pmode, return_address));
! 	emit_jump (subr);
! 	emit_label (return_address);
! 	return const0_rtx;
!       }
  
      case VA_ARG_EXPR:
        return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
--- 8783,8799 ----
        return const0_rtx;
  
      case TRY_CATCH_EXPR:
      case CATCH_EXPR:
      case EH_FILTER_EXPR:
      case TRY_FINALLY_EXPR:
!       /* Lowered by tree-eh.c.  */
!       abort ();
  
!     case WITH_CLEANUP_EXPR:
!     case CLEANUP_POINT_EXPR:
!     case TARGET_EXPR:
!       /* Lowered by gimplify.c.  */
!       abort ();
  
      case VA_ARG_EXPR:
        return expand_builtin_va_arg (TREE_OPERAND (exp, 0), type);
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.419
diff -c -p -d -r1.419 fold-const.c
*** gcc/fold-const.c	7 Jul 2004 21:28:01 -0000	1.419
--- gcc/fold-const.c	8 Jul 2004 07:19:33 -0000
*************** fold_checksum_tree (tree expr, struct md
*** 9048,9054 ****
    fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
    if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
      fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
-   len = TREE_CODE_LENGTH (code);
    switch (TREE_CODE_CLASS (code))
      {
      case 'c':
--- 9048,9053 ----
*************** fold_checksum_tree (tree expr, struct md
*** 9085,9102 ****
  	}
        break;
      case 'e':
-       switch (code)
- 	{
- 	case GOTO_SUBROUTINE_EXPR: len = 0; break;
- 	case WITH_CLEANUP_EXPR: len = 2; break;
- 	default: break;
- 	}
-       /* Fall through.  */
      case 'r':
      case '<':
      case '1':
      case '2':
      case 's':
        for (i = 0; i < len; ++i)
  	fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
        break;
--- 9084,9095 ----
  	}
        break;
      case 'e':
      case 'r':
      case '<':
      case '1':
      case '2':
      case 's':
+       len = first_rtl_op (code);
        for (i = 0; i < len; ++i)
  	fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
        break;
Index: gcc/function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.548
diff -c -p -d -r1.548 function.c
*** gcc/function.c	7 Jul 2004 23:02:22 -0000	1.548
--- gcc/function.c	8 Jul 2004 07:19:33 -0000
*************** expand_function_end (void)
*** 4554,4568 ****
       sh mach_dep_reorg) that still try and compute their own lifetime info
       instead of using the general framework.  */
    use_return_register ();
- 
-   /* Fix up any gotos that jumped out to the outermost
-      binding level of the function.
-      Must follow emitting RETURN_LABEL.  */
- 
-   /* If you have any cleanups to do at this point,
-      and they need to create temporary variables,
-      then you will lose.  */
-   expand_fixups (get_insns ());
  }
  
  rtx
--- 4554,4559 ----
Index: gcc/gengtype.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gengtype.c,v
retrieving revision 1.55
diff -c -p -d -r1.55 gengtype.c
*** gcc/gengtype.c	3 Jul 2004 00:15:43 -0000	1.55
--- gcc/gengtype.c	8 Jul 2004 07:19:33 -0000
*************** adjust_field_tree_exp (type_p t, options
*** 644,658 ****
  {
    pair_p flds;
    options_p nodot;
-   size_t i;
-   static const struct {
-     const char *name;
-     int first_rtl;
-     int num_rtl;
-   } data[] = {
-     { "GOTO_SUBROUTINE_EXPR", 0, 2 },
-     { "WITH_CLEANUP_EXPR", 2, 1 },
-   };
  
    if (t->kind != TYPE_ARRAY)
      {
--- 644,649 ----
*************** adjust_field_tree_exp (type_p t, options
*** 684,727 ****
      flds->opt->info = "";
    }
  
-   for (i = 0; i < ARRAY_SIZE (data); i++)
-     {
-       pair_p old_flds = flds;
-       pair_p subfields = NULL;
-       int r_index;
-       const char *sname;
- 
-       for (r_index = 0;
- 	   r_index < data[i].first_rtl + data[i].num_rtl;
- 	   r_index++)
- 	{
- 	  pair_p old_subf = subfields;
- 	  subfields = xmalloc (sizeof (*subfields));
- 	  subfields->next = old_subf;
- 	  subfields->name = xasprintf ("[%d]", r_index);
- 	  if (r_index < data[i].first_rtl)
- 	    subfields->type = t->u.a.p;
- 	  else
- 	    subfields->type = create_pointer (find_structure ("rtx_def", 0));
- 	  subfields->line.file = __FILE__;
- 	  subfields->line.line = __LINE__;
- 	  subfields->opt = nodot;
- 	}
- 
-       flds = xmalloc (sizeof (*flds));
-       flds->next = old_flds;
-       flds->name = "";
-       sname = xasprintf ("tree_exp_%s", data[i].name);
-       new_structure (sname, 0, &lexer_line, subfields, NULL);
-       flds->type = find_structure (sname, 0);
-       flds->line.file = __FILE__;
-       flds->line.line = __LINE__;
-       flds->opt = xmalloc (sizeof (*flds->opt));
-       flds->opt->next = nodot;
-       flds->opt->name = "tag";
-       flds->opt->info = data[i].name;
-     }
- 
    new_structure ("tree_exp_subunion", 1, &lexer_line, flds, nodot);
    return find_structure ("tree_exp_subunion", 1);
  }
--- 675,680 ----
Index: gcc/gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.42
diff -c -p -d -r2.42 gimplify.c
*** gcc/gimplify.c	6 Jul 2004 02:20:08 -0000	2.42
--- gcc/gimplify.c	8 Jul 2004 07:19:34 -0000
*************** gimplify_cleanup_point_expr (tree *expr_
*** 3210,3216 ****
  	{
  	  if (tsi_one_before_end_p (iter))
  	    {
! 	      tsi_link_before (&iter, TREE_OPERAND (wce, 1), TSI_SAME_STMT);
  	      tsi_delink (&iter);
  	      break;
  	    }
--- 3210,3216 ----
  	{
  	  if (tsi_one_before_end_p (iter))
  	    {
! 	      tsi_link_before (&iter, TREE_OPERAND (wce, 0), TSI_SAME_STMT);
  	      tsi_delink (&iter);
  	      break;
  	    }
*************** gimplify_cleanup_point_expr (tree *expr_
*** 3220,3227 ****
  
  	      sl = tsi_split_statement_list_after (&iter);
  	      tfe = build (TRY_FINALLY_EXPR, void_type_node, sl, NULL_TREE);
! 	      append_to_statement_list (TREE_OPERAND (wce, 1),
! 				     &TREE_OPERAND (tfe, 1));
  	      *wce_p = tfe;
  	      iter = tsi_start (sl);
  	    }
--- 3220,3227 ----
  
  	      sl = tsi_split_statement_list_after (&iter);
  	      tfe = build (TRY_FINALLY_EXPR, void_type_node, sl, NULL_TREE);
! 	      append_to_statement_list (TREE_OPERAND (wce, 0),
! 				        &TREE_OPERAND (tfe, 1));
  	      *wce_p = tfe;
  	      iter = tsi_start (sl);
  	    }
*************** gimple_push_cleanup (tree var, tree clea
*** 3285,3292 ****
        tree ftrue = build (MODIFY_EXPR, void_type_node, flag,
  			  boolean_true_node);
        cleanup = build (COND_EXPR, void_type_node, flag, cleanup, NULL);
!       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
! 		   cleanup, NULL_TREE);
        append_to_statement_list (ffalse, &gimplify_ctxp->conditional_cleanups);
        append_to_statement_list (wce, &gimplify_ctxp->conditional_cleanups);
        append_to_statement_list (ftrue, pre_p);
--- 3285,3291 ----
        tree ftrue = build (MODIFY_EXPR, void_type_node, flag,
  			  boolean_true_node);
        cleanup = build (COND_EXPR, void_type_node, flag, cleanup, NULL);
!       wce = build (WITH_CLEANUP_EXPR, void_type_node, cleanup);
        append_to_statement_list (ffalse, &gimplify_ctxp->conditional_cleanups);
        append_to_statement_list (wce, &gimplify_ctxp->conditional_cleanups);
        append_to_statement_list (ftrue, pre_p);
*************** gimple_push_cleanup (tree var, tree clea
*** 3298,3309 ****
      }
    else
      {
!       wce = build (WITH_CLEANUP_EXPR, void_type_node, NULL_TREE,
! 		   cleanup, NULL_TREE);
        append_to_statement_list (wce, pre_p);
      }
  
!   gimplify_stmt (&TREE_OPERAND (wce, 1));
  }
  
  /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR.  */
--- 3297,3307 ----
      }
    else
      {
!       wce = build (WITH_CLEANUP_EXPR, void_type_node, cleanup);
        append_to_statement_list (wce, pre_p);
      }
  
!   gimplify_stmt (&TREE_OPERAND (wce, 0));
  }
  
  /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR.  */
Index: gcc/integrate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.264
diff -c -p -d -r1.264 integrate.c
*** gcc/integrate.c	7 Jul 2004 19:23:59 -0000	1.264
--- gcc/integrate.c	8 Jul 2004 07:19:34 -0000
*************** copy_decl_for_inlining (tree decl, tree 
*** 160,166 ****
        if (TREE_CODE (copy) == LABEL_DECL)
  	{
  	  TREE_ADDRESSABLE (copy) = 0;
- 	  DECL_TOO_LATE (copy) = 0;
  	}
      }
  
--- 160,165 ----
Index: gcc/print-tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/print-tree.c,v
retrieving revision 1.88
diff -c -p -d -r1.88 print-tree.c
*** gcc/print-tree.c	3 Jul 2004 00:15:43 -0000	1.88
--- gcc/print-tree.c	8 Jul 2004 07:19:34 -0000
*************** print_node (FILE *file, const char *pref
*** 337,344 ****
        if (TREE_CODE (node) == FIELD_DECL && DECL_NONADDRESSABLE_P (node))
  	fputs (" nonaddressable", file);
  
-       if (TREE_CODE (node) == LABEL_DECL && DECL_TOO_LATE (node))
- 	fputs (" too-late", file);
        if (TREE_CODE (node) == LABEL_DECL && DECL_ERROR_ISSUED (node))
  	fputs (" error-issued", file);
  
--- 337,342 ----
Index: gcc/stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.371
diff -c -p -d -r1.371 stmt.c
*** gcc/stmt.c	5 Jul 2004 21:57:44 -0000	1.371
--- gcc/stmt.c	8 Jul 2004 07:19:34 -0000
*************** struct nesting GTY(())
*** 164,196 ****
  	  /* Sequence number of this binding contour within the function,
  	     in order of entry.  */
  	  int block_start_count;
- 	  /* Nonzero => value to restore stack to on exit.  */
- 	  rtx stack_level;
  	  /* The NOTE that starts this contour.
  	     Used by expand_goto to check whether the destination
  	     is within each contour or not.  */
  	  rtx first_insn;
- 	  /* Innermost containing binding contour that has a stack level.  */
- 	  struct nesting *innermost_stack_block;
- 	  /* List of cleanups to be run on exit from this contour.
- 	     This is a list of expressions to be evaluated.
- 	     The TREE_PURPOSE of each link is the ..._DECL node
- 	     which the cleanup pertains to.  */
- 	  tree cleanups;
- 	  /* List of cleanup-lists of blocks containing this block,
- 	     as they were at the locus where this block appears.
- 	     There is an element for each containing block,
- 	     ordered innermost containing block first.
- 	     The tail of this list can be 0,
- 	     if all remaining elements would be empty lists.
- 	     The element's TREE_VALUE is the cleanup-list of that block,
- 	     which may be null.  */
- 	  tree outer_cleanups;
- 	  /* Chain of labels defined inside this binding contour.
- 	     For contours that have stack levels or cleanups.  */
- 	  struct label_chain *label_chain;
- 	  /* Nonzero if this is associated with an EH region.  */
- 	  int exception_region;
  	  /* The saved target_temp_slot_level from our outer block.
  	     We may reset target_temp_slot_level to be the level of
  	     this block, if that is done, target_temp_slot_level
--- 164,173 ----
*************** do { struct nesting *target = STACK;			\
*** 251,258 ****
  	    cond_stack = cond_stack->next;		\
  	  if (block_stack == this)			\
  	    block_stack = block_stack->next;		\
- 	  if (stack_block_stack == this)		\
- 	    stack_block_stack = stack_block_stack->next; \
  	  if (case_stack == this)			\
  	    case_stack = case_stack->next;		\
  	  nesting_depth = nesting_stack->depth - 1;	\
--- 228,233 ----
*************** struct goto_fixup GTY(())
*** 284,311 ****
    /* Number of binding contours started in current function
       before the label reference.  */
    int block_start_count;
-   /* The outermost stack level that should be restored for this jump.
-      Each time a binding contour that resets the stack is exited,
-      if the target label is *not* yet defined, this slot is updated.  */
-   rtx stack_level;
-   /* List of lists of cleanup expressions to be run by this goto.
-      There is one element for each block that this goto is within.
-      The tail of this list can be 0,
-      if all remaining elements would be empty.
-      The TREE_VALUE contains the cleanup list of that block as of the
-      time this goto was seen.
-      The TREE_ADDRESSABLE flag is 1 for a block that has been exited.  */
-   tree cleanup_list_list;
- };
- 
- /* Within any binding contour that must restore a stack level,
-    all labels are recorded with a chain of these structures.  */
- 
- struct label_chain GTY(())
- {
-   /* Points to following fixup.  */
-   struct label_chain *next;
-   tree label;
  };
  
  struct stmt_status GTY(())
--- 259,264 ----
*************** struct stmt_status GTY(())
*** 315,324 ****
  
    /* If any new stacks are added here, add them to POPSTACKS too.  */
  
-   /* Chain of all pending binding contours that restore stack levels
-      or have cleanups.  */
-   struct nesting * x_stack_block_stack;
- 
    /* Chain of all pending conditional statements.  */
    struct nesting * x_cond_stack;
  
--- 268,273 ----
*************** struct stmt_status GTY(())
*** 343,349 ****
  };
  
  #define block_stack (cfun->stmt->x_block_stack)
- #define stack_block_stack (cfun->stmt->x_stack_block_stack)
  #define cond_stack (cfun->stmt->x_cond_stack)
  #define case_stack (cfun->stmt->x_case_stack)
  #define nesting_stack (cfun->stmt->x_nesting_stack)
--- 292,297 ----
*************** int using_eh_for_cleanups_p = 0;
*** 357,374 ****
  
  static int n_occurrences (int, const char *);
  static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
- static void expand_goto_internal (tree, rtx, rtx);
- static int expand_fixup (tree, rtx, rtx);
  static void expand_nl_goto_receiver (void);
- static void fixup_gotos (struct nesting *, rtx, tree, rtx, int);
  static bool check_operand_nalternatives (tree, tree);
  static bool check_unique_operand_names (tree, tree);
  static char *resolve_operand_name_1 (char *, tree, tree);
! static void expand_null_return_1 (rtx);
  static enum br_predictor return_prediction (rtx);
  static rtx shift_return_value (rtx);
  static void expand_value_return (rtx);
- static void expand_cleanups (tree, int, int);
  static void do_jump_if_equal (rtx, rtx, rtx, int);
  static int estimate_case_costs (case_node_ptr);
  static bool same_case_target_p (rtx, rtx);
--- 305,318 ----
  
  static int n_occurrences (int, const char *);
  static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
  static void expand_nl_goto_receiver (void);
  static bool check_operand_nalternatives (tree, tree);
  static bool check_unique_operand_names (tree, tree);
  static char *resolve_operand_name_1 (char *, tree, tree);
! static void expand_null_return_1 (void);
  static enum br_predictor return_prediction (rtx);
  static rtx shift_return_value (rtx);
  static void expand_value_return (rtx);
  static void do_jump_if_equal (rtx, rtx, rtx, int);
  static int estimate_case_costs (case_node_ptr);
  static bool same_case_target_p (rtx, rtx);
*************** expand_computed_goto (tree exp)
*** 507,513 ****
  void
  expand_label (tree label)
  {
-   struct label_chain *p;
    rtx label_r = label_rtx (label);
  
    do_pending_stack_adjust ();
--- 451,456 ----
*************** expand_label (tree label)
*** 528,541 ****
        
    if (DECL_NONLOCAL (label) || FORCED_LABEL (label))
      maybe_set_first_label_num (label_r);
- 
-   if (stack_block_stack != 0)
-     {
-       p = ggc_alloc (sizeof (struct label_chain));
-       p->next = stack_block_stack->data.block.label_chain;
-       stack_block_stack->data.block.label_chain = p;
-       p->label = label;
-     }
  }
  
  /* Generate RTL code for a `goto' statement with target label LABEL.
--- 471,476 ----
*************** expand_goto (tree label)
*** 553,937 ****
      abort ();
  #endif
  
!   expand_goto_internal (label, label_rtx (label), NULL_RTX);
! }
! 
! /* Generate RTL code for a `goto' statement with target label BODY.
!    LABEL should be a LABEL_REF.
!    LAST_INSN, if non-0, is the rtx we should consider as the last
!    insn emitted (for the purposes of cleaning up a return).  */
! 
! static void
! expand_goto_internal (tree body, rtx label, rtx last_insn)
! {
!   struct nesting *block;
!   rtx stack_level = 0;
! 
!   if (GET_CODE (label) != CODE_LABEL)
!     abort ();
! 
!   /* If label has already been defined, we can tell now
!      whether and how we must alter the stack level.  */
! 
!   if (PREV_INSN (label) != 0)
!     {
!       /* Find the innermost pending block that contains the label.
! 	 (Check containment by comparing insn-uids.)
! 	 Then restore the outermost stack level within that block,
! 	 and do cleanups of all blocks contained in it.  */
!       for (block = block_stack; block; block = block->next)
! 	{
! 	  if (INSN_UID (block->data.block.first_insn) < INSN_UID (label))
! 	    break;
! 	  if (block->data.block.stack_level != 0)
! 	    stack_level = block->data.block.stack_level;
! 	  /* Execute the cleanups for blocks we are exiting.  */
! 	  if (block->data.block.cleanups != 0)
! 	    {
! 	      expand_cleanups (block->data.block.cleanups, 1, 1);
! 	      do_pending_stack_adjust ();
! 	    }
! 	}
! 
!       if (stack_level)
! 	{
! 	  /* Ensure stack adjust isn't done by emit_jump, as this
! 	     would clobber the stack pointer.  This one should be
! 	     deleted as dead by flow.  */
! 	  clear_pending_stack_adjust ();
! 	  do_pending_stack_adjust ();
! 
! 	  /* Don't do this adjust if it's to the end label and this function
! 	     is to return with a depressed stack pointer.  */
! 	  if (label == return_label
! 	      && (((TREE_CODE (TREE_TYPE (current_function_decl))
! 		   == FUNCTION_TYPE)
! 		   && (TYPE_RETURNS_STACK_DEPRESSED
! 		       (TREE_TYPE (current_function_decl))))))
! 	    ;
! 	  else
! 	    emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
! 	}
! 
!       if (body != 0 && DECL_TOO_LATE (body))
! 	error ("jump to `%s' invalidly jumps into binding contour",
! 	       IDENTIFIER_POINTER (DECL_NAME (body)));
!     }
!   /* Label not yet defined: may need to put this goto
!      on the fixup list.  */
!   else if (! expand_fixup (body, label, last_insn))
!     {
!       /* No fixup needed.  Record that the label is the target
! 	 of at least one goto that has no fixup.  */
!       if (body != 0)
! 	TREE_ADDRESSABLE (body) = 1;
!     }
! 
!   emit_jump (label);
! }
! 
! /* Generate if necessary a fixup for a goto
!    whose target label in tree structure (if any) is TREE_LABEL
!    and whose target in rtl is RTL_LABEL.
! 
!    If LAST_INSN is nonzero, we pretend that the jump appears
!    after insn LAST_INSN instead of at the current point in the insn stream.
! 
!    The fixup will be used later to insert insns just before the goto.
!    Those insns will restore the stack level as appropriate for the
!    target label, and will (in the case of C++) also invoke any object
!    destructors which have to be invoked when we exit the scopes which
!    are exited by the goto.
! 
!    Value is nonzero if a fixup is made.  */
! 
! static int
! expand_fixup (tree tree_label, rtx rtl_label, rtx last_insn)
! {
!   struct nesting *block, *end_block;
! 
!   /* See if we can recognize which block the label will be output in.
!      This is possible in some very common cases.
!      If we succeed, set END_BLOCK to that block.
!      Otherwise, set it to 0.  */
! 
!   if (cond_stack
!       && (rtl_label == cond_stack->data.cond.endif_label
! 	  || rtl_label == cond_stack->data.cond.next_label))
!     end_block = cond_stack;
!   else
!     end_block = 0;
! 
!   /* Now set END_BLOCK to the binding level to which we will return.  */
! 
!   if (end_block)
!     {
!       struct nesting *next_block = end_block->all;
!       block = block_stack;
! 
!       /* First see if the END_BLOCK is inside the innermost binding level.
! 	 If so, then no cleanups or stack levels are relevant.  */
!       while (next_block && next_block != block)
! 	next_block = next_block->all;
! 
!       if (next_block)
! 	return 0;
! 
!       /* Otherwise, set END_BLOCK to the innermost binding level
! 	 which is outside the relevant control-structure nesting.  */
!       next_block = block_stack->next;
!       for (block = block_stack; block != end_block; block = block->all)
! 	if (block == next_block)
! 	  next_block = next_block->next;
!       end_block = next_block;
!     }
! 
!   /* Does any containing block have a stack level or cleanups?
!      If not, no fixup is needed, and that is the normal case
!      (the only case, for standard C).  */
!   for (block = block_stack; block != end_block; block = block->next)
!     if (block->data.block.stack_level != 0
! 	|| block->data.block.cleanups != 0)
!       break;
! 
!   if (block != end_block)
!     {
!       /* Ok, a fixup is needed.  Add a fixup to the list of such.  */
!       struct goto_fixup *fixup = ggc_alloc (sizeof (struct goto_fixup));
!       /* In case an old stack level is restored, make sure that comes
! 	 after any pending stack adjust.  */
!       /* ?? If the fixup isn't to come at the present position,
! 	 doing the stack adjust here isn't useful.  Doing it with our
! 	 settings at that location isn't useful either.  Let's hope
! 	 someone does it!  */
!       if (last_insn == 0)
! 	do_pending_stack_adjust ();
!       fixup->target = tree_label;
!       fixup->target_rtl = rtl_label;
! 
!       /* Create a BLOCK node and a corresponding matched set of
! 	 NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes at
! 	 this point.  The notes will encapsulate any and all fixup
! 	 code which we might later insert at this point in the insn
! 	 stream.  Also, the BLOCK node will be the parent (i.e. the
! 	 `SUPERBLOCK') of any other BLOCK nodes which we might create
! 	 later on when we are expanding the fixup code.
! 
! 	 Note that optimization passes might move the *_BLOCK notes away,
! 	 so we use a NOTE_INSN_DELETED as a placeholder.  */
! 
!       {
! 	rtx original_before_jump
! 	  = last_insn ? last_insn : get_last_insn ();
! 	rtx start;
! 	rtx end;
! 	tree block;
! 
! 	block = make_node (BLOCK);
! 	TREE_USED (block) = 1;
! 
! 	BLOCK_CHAIN (block)
! 	  = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
! 	BLOCK_CHAIN (DECL_INITIAL (current_function_decl))
! 	  = block;
! 
! 	start_sequence ();
! 	start = emit_note (NOTE_INSN_BLOCK_BEG);
! 	NOTE_BLOCK (start) = block;
! 	fixup->before_jump = emit_note (NOTE_INSN_DELETED);
! 	end = emit_note (NOTE_INSN_BLOCK_END);
! 	NOTE_BLOCK (end) = block;
! 	fixup->context = block;
! 	end_sequence ();
! 	emit_insn_after (start, original_before_jump);
!       }
! 
!       fixup->block_start_count = current_block_start_count;
!       fixup->stack_level = 0;
!       fixup->cleanup_list_list
! 	= ((block->data.block.outer_cleanups
! 	    || block->data.block.cleanups)
! 	   ? tree_cons (NULL_TREE, block->data.block.cleanups,
! 			block->data.block.outer_cleanups)
! 	   : 0);
!       fixup->next = goto_fixup_chain;
!       goto_fixup_chain = fixup;
!     }
! 
!   return block != 0;
! }
! 
! /* Expand any needed fixups in the outputmost binding level of the
!    function.  FIRST_INSN is the first insn in the function.  */
! 
! void
! expand_fixups (rtx first_insn)
! {
!   fixup_gotos (NULL, NULL_RTX, NULL_TREE, first_insn, 0);
! }
! 
! /* When exiting a binding contour, process all pending gotos requiring fixups.
!    THISBLOCK is the structure that describes the block being exited.
!    STACK_LEVEL is the rtx for the stack level to restore exiting this contour.
!    CLEANUP_LIST is a list of expressions to evaluate on exiting this contour.
!    FIRST_INSN is the insn that began this contour.
! 
!    Gotos that jump out of this contour must restore the
!    stack level and do the cleanups before actually jumping.
! 
!    DONT_JUMP_IN positive means report error if there is a jump into this
!    contour from before the beginning of the contour.  This is also done if
!    STACK_LEVEL is nonzero unless DONT_JUMP_IN is negative.  */
! 
! static void
! fixup_gotos (struct nesting *thisblock, rtx stack_level,
! 	     tree cleanup_list, rtx first_insn, int dont_jump_in)
! {
!   struct goto_fixup *f, *prev;
! 
!   /* F is the fixup we are considering; PREV is the previous one.  */
!   /* We run this loop in two passes so that cleanups of exited blocks
!      are run first, and blocks that are exited are marked so
!      afterwards.  */
! 
!   for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
!     {
!       /* Test for a fixup that is inactive because it is already handled.  */
!       if (f->before_jump == 0)
! 	{
! 	  /* Delete inactive fixup from the chain, if that is easy to do.  */
! 	  if (prev != 0)
! 	    prev->next = f->next;
! 	}
!       /* Has this fixup's target label been defined?
! 	 If so, we can finalize it.  */
!       else if (PREV_INSN (f->target_rtl) != 0)
! 	{
! 	  rtx cleanup_insns;
! 
! 	  /* If this fixup jumped into this contour from before the beginning
! 	     of this contour, report an error.   This code used to use
! 	     the first non-label insn after f->target_rtl, but that's
! 	     wrong since such can be added, by things like put_var_into_stack
! 	     and have INSN_UIDs that are out of the range of the block.  */
! 	  /* ??? Bug: this does not detect jumping in through intermediate
! 	     blocks that have stack levels or cleanups.
! 	     It detects only a problem with the innermost block
! 	     around the label.  */
! 	  if (f->target != 0
! 	      && (dont_jump_in > 0 || (dont_jump_in == 0 && stack_level)
! 		  || cleanup_list)
! 	      && INSN_UID (first_insn) < INSN_UID (f->target_rtl)
! 	      && INSN_UID (first_insn) > INSN_UID (f->before_jump)
! 	      && ! DECL_ERROR_ISSUED (f->target))
! 	    {
! 	      error ("%Jlabel '%D' used before containing binding contour",
! 		     f->target, f->target);
! 	      /* Prevent multiple errors for one label.  */
! 	      DECL_ERROR_ISSUED (f->target) = 1;
! 	    }
! 
! 	  /* We will expand the cleanups into a sequence of their own and
! 	     then later on we will attach this new sequence to the insn
! 	     stream just ahead of the actual jump insn.  */
! 
! 	  start_sequence ();
! 
! 	  /* Temporarily restore the lexical context where we will
! 	     logically be inserting the fixup code.  We do this for the
! 	     sake of getting the debugging information right.  */
! 
! 	  lang_hooks.decls.pushlevel (0);
! 	  lang_hooks.decls.set_block (f->context);
! 
! 	  /* Expand the cleanups for blocks this jump exits.  */
! 	  if (f->cleanup_list_list)
! 	    {
! 	      tree lists;
! 	      for (lists = f->cleanup_list_list; lists; lists = TREE_CHAIN (lists))
! 		/* Marked elements correspond to blocks that have been closed.
! 		   Do their cleanups.  */
! 		if (TREE_ADDRESSABLE (lists)
! 		    && TREE_VALUE (lists) != 0)
! 		  {
! 		    expand_cleanups (TREE_VALUE (lists), 1, 1);
! 		    /* Pop any pushes done in the cleanups,
! 		       in case function is about to return.  */
! 		    do_pending_stack_adjust ();
! 		  }
! 	    }
! 
! 	  /* Restore stack level for the biggest contour that this
! 	     jump jumps out of.  */
! 	  if (f->stack_level
! 	      && ! (f->target_rtl == return_label
! 		    && ((TREE_CODE (TREE_TYPE (current_function_decl))
! 			 == FUNCTION_TYPE)
! 			&& (TYPE_RETURNS_STACK_DEPRESSED
! 			    (TREE_TYPE (current_function_decl))))))
! 	    emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
! 
! 	  /* Finish up the sequence containing the insns which implement the
! 	     necessary cleanups, and then attach that whole sequence to the
! 	     insn stream just ahead of the actual jump insn.  Attaching it
! 	     at that point insures that any cleanups which are in fact
! 	     implicit C++ object destructions (which must be executed upon
! 	     leaving the block) appear (to the debugger) to be taking place
! 	     in an area of the generated code where the object(s) being
! 	     destructed are still "in scope".  */
! 
! 	  cleanup_insns = get_insns ();
! 	  lang_hooks.decls.poplevel (1, 0, 0);
! 
! 	  end_sequence ();
! 	  emit_insn_after (cleanup_insns, f->before_jump);
! 
! 	  f->before_jump = 0;
! 	}
!     }
! 
!   /* For any still-undefined labels, do the cleanups for this block now.
!      We must do this now since items in the cleanup list may go out
!      of scope when the block ends.  */
!   for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
!     if (f->before_jump != 0
! 	&& PREV_INSN (f->target_rtl) == 0
! 	/* Label has still not appeared.  If we are exiting a block with
! 	   a stack level to restore, that started before the fixup,
! 	   mark this stack level as needing restoration
! 	   when the fixup is later finalized.  */
! 	&& thisblock != 0
! 	/* Note: if THISBLOCK == 0 and we have a label that hasn't appeared, it
! 	   means the label is undefined.  That's erroneous, but possible.  */
! 	&& (thisblock->data.block.block_start_count
! 	    <= f->block_start_count))
!       {
! 	tree lists = f->cleanup_list_list;
! 	rtx cleanup_insns;
! 
! 	for (; lists; lists = TREE_CHAIN (lists))
! 	  /* If the following elt. corresponds to our containing block
! 	     then the elt. must be for this block.  */
! 	  if (TREE_CHAIN (lists) == thisblock->data.block.outer_cleanups)
! 	    {
! 	      start_sequence ();
! 	      lang_hooks.decls.pushlevel (0);
! 	      lang_hooks.decls.set_block (f->context);
! 	      expand_cleanups (TREE_VALUE (lists), 1, 1);
! 	      do_pending_stack_adjust ();
! 	      cleanup_insns = get_insns ();
! 	      lang_hooks.decls.poplevel (1, 0, 0);
! 	      end_sequence ();
! 	      if (cleanup_insns != 0)
! 		f->before_jump
! 		  = emit_insn_after (cleanup_insns, f->before_jump);
! 
! 	      f->cleanup_list_list = TREE_CHAIN (lists);
! 	    }
! 
! 	if (stack_level)
! 	  f->stack_level = stack_level;
!       }
  }
  
  /* Return the number of times character C occurs in string S.  */
--- 488,494 ----
      abort ();
  #endif
  
!   emit_jump (label_rtx (label));
  }
  
  /* Return the number of times character C occurs in string S.  */
*************** preserve_subexpressions_p (void)
*** 2297,2312 ****
  void
  expand_null_return (void)
  {
-   rtx last_insn;
- 
-   last_insn = get_last_insn ();
- 
    /* If this function was declared to return a value, but we
       didn't, clobber the return registers so that they are not
       propagated live to the rest of the function.  */
    clobber_return_register ();
  
!   expand_null_return_1 (last_insn);
  }
  
  /* Generate RTL to return directly from the current function.
--- 1854,1865 ----
  void
  expand_null_return (void)
  {
    /* If this function was declared to return a value, but we
       didn't, clobber the return registers so that they are not
       propagated live to the rest of the function.  */
    clobber_return_register ();
  
!   expand_null_return_1 ();
  }
  
  /* Generate RTL to return directly from the current function.
*************** expand_null_return (void)
*** 2315,2331 ****
  void
  expand_naked_return (void)
  {
!   rtx last_insn, end_label;
! 
!   last_insn = get_last_insn ();
!   end_label = naked_return_label;
  
    clear_pending_stack_adjust ();
    do_pending_stack_adjust ();
  
    if (end_label == 0)
      end_label = naked_return_label = gen_label_rtx ();
!   expand_goto_internal (NULL_TREE, end_label, last_insn);
  }
  
  /* Try to guess whether the value of return means error code.  */
--- 1868,1883 ----
  void
  expand_naked_return (void)
  {
!   rtx end_label;
  
    clear_pending_stack_adjust ();
    do_pending_stack_adjust ();
  
+   end_label = naked_return_label;
    if (end_label == 0)
      end_label = naked_return_label = gen_label_rtx ();
! 
!   emit_jump (end_label);
  }
  
  /* Try to guess whether the value of return means error code.  */
*************** shift_return_value (rtx val)
*** 2389,2395 ****
  static void
  expand_value_return (rtx val)
  {
-   rtx last_insn;
    rtx return_reg;
    enum br_predictor pred;
  
--- 1941,1946 ----
*************** expand_value_return (rtx val)
*** 2405,2411 ****
  
      }
  
-   last_insn = get_last_insn ();
    return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
  
    /* Copy the value to the return location
--- 1956,1961 ----
*************** expand_value_return (rtx val)
*** 2431,2453 ****
  	emit_move_insn (return_reg, val);
      }
  
!   expand_null_return_1 (last_insn);
  }
  
! /* Output a return with no value.  If LAST_INSN is nonzero,
!    pretend that the return takes place after LAST_INSN.  */
  
  static void
! expand_null_return_1 (rtx last_insn)
  {
!   rtx end_label = return_label;
  
    clear_pending_stack_adjust ();
    do_pending_stack_adjust ();
  
    if (end_label == 0)
       end_label = return_label = gen_label_rtx ();
!   expand_goto_internal (NULL_TREE, end_label, last_insn);
  }
  
  /* Generate RTL to evaluate the expression RETVAL and return it
--- 1981,2003 ----
  	emit_move_insn (return_reg, val);
      }
  
!   expand_null_return_1 ();
  }
  
! /* Output a return with no value.  */
  
  static void
! expand_null_return_1 (void)
  {
!   rtx end_label;
  
    clear_pending_stack_adjust ();
    do_pending_stack_adjust ();
  
+   end_label = return_label;
    if (end_label == 0)
       end_label = return_label = gen_label_rtx ();
!   emit_jump (end_label);
  }
  
  /* Generate RTL to evaluate the expression RETVAL and return it
*************** expand_null_return_1 (rtx last_insn)
*** 2456,2470 ****
  void
  expand_return (tree retval)
  {
-   /* If there are any cleanups to be performed, then they will
-      be inserted following LAST_INSN.  It is desirable
-      that the last_insn, for such purposes, should be the
-      last insn before computing the return value.  Otherwise, cleanups
-      which call functions can clobber the return value.  */
-   /* ??? rms: I think that is erroneous, because in C++ it would
-      run destructors on variables that might be used in the subsequent
-      computation of the return value.  */
-   rtx last_insn = 0;
    rtx result_rtl;
    rtx val = 0;
    tree retval_rhs;
--- 2006,2011 ----
*************** expand_return (tree retval)
*** 2487,2500 ****
      }
    else if (TREE_CODE (retval) == RESULT_DECL)
      retval_rhs = retval;
!   else if ((TREE_CODE (retval) == MODIFY_EXPR || TREE_CODE (retval) == INIT_EXPR)
  	   && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
      retval_rhs = TREE_OPERAND (retval, 1);
    else
      retval_rhs = retval;
  
-   last_insn = get_last_insn ();
- 
    result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
  
    /* If the result is an aggregate that is being returned in one (or more)
--- 2028,2040 ----
      }
    else if (TREE_CODE (retval) == RESULT_DECL)
      retval_rhs = retval;
!   else if ((TREE_CODE (retval) == MODIFY_EXPR
! 	    || TREE_CODE (retval) == INIT_EXPR)
  	   && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
      retval_rhs = TREE_OPERAND (retval, 1);
    else
      retval_rhs = retval;
  
    result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
  
    /* If the result is an aggregate that is being returned in one (or more)
*************** expand_return (tree retval)
*** 2502,2509 ****
       copying a BLKmode value into registers.  We could put this code in a
       more general area (for use by everyone instead of just function
       call/return), but until this feature is generally usable it is kept here
!      (and in expand_call).  The value must go into a pseudo in case there
!      are cleanups that will clobber the real return register.  */
  
    if (retval_rhs != 0
        && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
--- 2042,2048 ----
       copying a BLKmode value into registers.  We could put this code in a
       more general area (for use by everyone instead of just function
       call/return), but until this feature is generally usable it is kept here
!      (and in expand_call).  */
  
    if (retval_rhs != 0
        && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
*************** expand_return (tree retval)
*** 2631,2643 ****
        val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
        val = force_not_mem (val);
        emit_queue ();
!       /* Return the calculated value, doing cleanups first.  */
        expand_value_return (shift_return_value (val));
      }
    else
      {
!       /* No cleanups or no hard reg used;
! 	 calculate value into hard return reg.  */
        expand_expr (retval, const0_rtx, VOIDmode, 0);
        emit_queue ();
        expand_value_return (result_rtl);
--- 2170,2181 ----
        val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
        val = force_not_mem (val);
        emit_queue ();
!       /* Return the calculated value.  */
        expand_value_return (shift_return_value (val));
      }
    else
      {
!       /* No hard reg used; calculate value into hard return reg.  */
        expand_expr (retval, const0_rtx, VOIDmode, 0);
        emit_queue ();
        expand_value_return (result_rtl);
*************** expand_start_bindings_and_block (int fla
*** 2686,2694 ****
    thisblock->next = block_stack;
    thisblock->all = nesting_stack;
    thisblock->depth = ++nesting_depth;
-   thisblock->data.block.stack_level = 0;
-   thisblock->data.block.cleanups = 0;
-   thisblock->data.block.exception_region = 0;
    thisblock->data.block.block_target_temp_slot_level = target_temp_slot_level;
  
    thisblock->data.block.conditional_code = 0;
--- 2224,2229 ----
*************** expand_start_bindings_and_block (int fla
*** 2701,2716 ****
       never the last instruction.  */
    emit_note (NOTE_INSN_DELETED);
  
-   if (block_stack
-       && !(block_stack->data.block.cleanups == NULL_TREE
- 	   && block_stack->data.block.outer_cleanups == NULL_TREE))
-     thisblock->data.block.outer_cleanups
-       = tree_cons (NULL_TREE, block_stack->data.block.cleanups,
- 		   block_stack->data.block.outer_cleanups);
-   else
-     thisblock->data.block.outer_cleanups = 0;
-   thisblock->data.block.label_chain = 0;
-   thisblock->data.block.innermost_stack_block = stack_block_stack;
    thisblock->data.block.first_insn = note;
    thisblock->data.block.block_start_count = ++current_block_start_count;
    thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;
--- 2236,2241 ----
*************** warn_about_unused_variables (tree vars)
*** 2906,2912 ****
  
  void
  expand_end_bindings (tree vars, int mark_ends ATTRIBUTE_UNUSED,
! 		     int dont_jump_in)
  {
    struct nesting *thisblock = block_stack;
  
--- 2431,2437 ----
  
  void
  expand_end_bindings (tree vars, int mark_ends ATTRIBUTE_UNUSED,
! 		     int dont_jump_in ATTRIBUTE_UNUSED)
  {
    struct nesting *thisblock = block_stack;
  
*************** expand_end_bindings (tree vars, int mark
*** 2920,2990 ****
        emit_label (thisblock->exit_label);
      }
  
!   /* Don't allow jumping into a block that has a stack level.
!      Cleanups are allowed, though.  */
!   if (dont_jump_in > 0
!       || (dont_jump_in == 0 && thisblock->data.block.stack_level != 0))
!     {
!       struct label_chain *chain;
! 
!       /* Any labels in this block are no longer valid to go to.
! 	 Mark them to cause an error message.  */
!       for (chain = thisblock->data.block.label_chain; chain; chain = chain->next)
! 	{
! 	  DECL_TOO_LATE (chain->label) = 1;
! 	  /* If any goto without a fixup came to this label,
! 	     that must be an error, because gotos without fixups
! 	     come from outside all saved stack-levels.  */
! 	  if (TREE_ADDRESSABLE (chain->label))
! 	    error ("%Jlabel '%D' used before containing binding contour",
! 		   chain->label, chain->label);
! 	}
!     }
! 
!   /* Restore stack level in effect before the block
!      (only if variable-size objects allocated).  */
!   /* Perform any cleanups associated with the block.  */
! 
!   if (thisblock->data.block.stack_level != 0
!       || thisblock->data.block.cleanups != 0)
!     {
!       int reachable;
!       rtx insn;
! 
!       /* Only clean up here if this point can actually be reached.  */
!       insn = get_last_insn ();
!       if (GET_CODE (insn) == NOTE)
! 	insn = prev_nonnote_insn (insn);
!       reachable = (! insn || GET_CODE (insn) != BARRIER);
! 
!       /* Do the cleanups.  */
!       expand_cleanups (thisblock->data.block.cleanups, 0, reachable);
!       if (reachable)
! 	do_pending_stack_adjust ();
! 
!       /* Restore the stack level.  */
! 
!       if (reachable && thisblock->data.block.stack_level != 0)
! 	{
! 	  emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
! 			      thisblock->data.block.stack_level, NULL_RTX);
! 	  if (cfun->nonlocal_goto_save_area)
! 	    update_nonlocal_goto_save_area ();
! 	}
! 
!       /* Any gotos out of this block must also do these things.
! 	 Also report any gotos with fixups that came to labels in this
! 	 level.  */
!       fixup_gotos (thisblock,
! 		   thisblock->data.block.stack_level,
! 		   thisblock->data.block.cleanups,
! 		   thisblock->data.block.first_insn,
! 		   dont_jump_in);
!     }
! 
!   /* Mark the beginning and end of the scope if requested.
!      We do this now, after running cleanups on the variables
!      just going out of scope, so they are in scope for their cleanups.  */
  
    /* Get rid of the beginning-mark if we don't make an end-mark.  */
    NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
--- 2445,2451 ----
        emit_label (thisblock->exit_label);
      }
  
!   /* Mark the beginning and end of the scope if requested.  */
  
    /* Get rid of the beginning-mark if we don't make an end-mark.  */
    NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
*************** expand_end_bindings (tree vars, int mark
*** 2994,3023 ****
  
    /* Restore block_stack level for containing block.  */
  
-   stack_block_stack = thisblock->data.block.innermost_stack_block;
    POPSTACK (block_stack);
  
    /* Pop the stack slot nesting and free any slots at this level.  */
    pop_temp_slots ();
  }
  
- /* Generate code to save the stack pointer at the start of the current block
-    and set up to restore it on exit.  */
- 
- void
- save_stack_pointer (void)
- {
-   struct nesting *thisblock = block_stack;
- 
-   if (thisblock->data.block.stack_level == 0)
-     {
-       emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
- 		       &thisblock->data.block.stack_level,
- 		       thisblock->data.block.first_insn);
-       stack_block_stack = thisblock;
-     }
- }
- 
  /* Generate RTL for the automatic variable declaration DECL.
     (Other kinds of declarations are simply ignored if seen here.)  */
  
--- 2455,2466 ----
*************** expand_decl (tree decl)
*** 3143,3149 ****
        /* Record the stack pointer on entry to block, if have
  	 not already done so.  */
        do_pending_stack_adjust ();
-       save_stack_pointer ();
  
        /* Compute the variable's size, in bytes.  This will expand any
  	 needed SAVE_EXPRs for the first time.  */
--- 2586,2591 ----
*************** expand_decl_init (tree decl)
*** 3270,3402 ****
    pop_temp_slots ();
  }
  
- /* CLEANUP is an expression to be executed at exit from this binding contour;
-    for example, in C++, it might call the destructor for this variable.
- 
-    We wrap CLEANUP in an UNSAVE_EXPR node, so that we can expand the
-    CLEANUP multiple times, and have the correct semantics.  This
-    happens in exception handling, for gotos, returns, breaks that
-    leave the current scope.
- 
-    If CLEANUP is nonzero and DECL is zero, we record a cleanup
-    that is not associated with any particular variable.  */
- 
- int
- expand_decl_cleanup (tree decl, tree cleanup)
- {
-   struct nesting *thisblock;
- 
-   /* Error if we are not in any block.  */
-   if (cfun == 0 || block_stack == 0)
-     return 0;
- 
-   thisblock = block_stack;
- 
-   /* Record the cleanup if there is one.  */
- 
-   if (cleanup != 0)
-     {
-       tree t;
-       rtx seq;
-       tree *cleanups = &thisblock->data.block.cleanups;
-       int cond_context = conditional_context ();
- 
-       if (cond_context)
- 	{
- 	  rtx flag = gen_reg_rtx (word_mode);
- 	  rtx set_flag_0;
- 	  tree cond;
- 
- 	  start_sequence ();
- 	  emit_move_insn (flag, const0_rtx);
- 	  set_flag_0 = get_insns ();
- 	  end_sequence ();
- 
- 	  thisblock->data.block.last_unconditional_cleanup
- 	    = emit_insn_after (set_flag_0,
- 				thisblock->data.block.last_unconditional_cleanup);
- 
- 	  emit_move_insn (flag, const1_rtx);
- 
- 	  cond = build_decl (VAR_DECL, NULL_TREE,
- 			     lang_hooks.types.type_for_mode (word_mode, 1));
- 	  SET_DECL_RTL (cond, flag);
- 
- 	  /* Conditionalize the cleanup.  */
- 	  cleanup = build (COND_EXPR, void_type_node,
- 			   lang_hooks.truthvalue_conversion (cond),
- 			   cleanup, integer_zero_node);
- 	  cleanup = fold (cleanup);
- 
- 	  cleanups = &thisblock->data.block.cleanups;
- 	}
- 
-       cleanup = unsave_expr (cleanup);
- 
-       t = *cleanups = tree_cons (decl, cleanup, *cleanups);
- 
-       if (! cond_context)
- 	/* If this block has a cleanup, it belongs in stack_block_stack.  */
- 	stack_block_stack = thisblock;
- 
-       if (cond_context)
- 	{
- 	  start_sequence ();
- 	}
- 
-       if (! using_eh_for_cleanups_p)
- 	TREE_ADDRESSABLE (t) = 1;
-       else
- 	expand_eh_region_start ();
- 
-       if (cond_context)
- 	{
- 	  seq = get_insns ();
- 	  end_sequence ();
- 	  if (seq)
- 	    thisblock->data.block.last_unconditional_cleanup
- 	      = emit_insn_after (seq,
- 				 thisblock->data.block.last_unconditional_cleanup);
- 	}
-       else
- 	{
- 	  thisblock->data.block.last_unconditional_cleanup
- 	    = get_last_insn ();
- 	  /* When we insert instructions after the last unconditional cleanup,
- 	     we don't adjust last_insn.  That means that a later add_insn will
- 	     clobber the instructions we've just added.  The easiest way to
- 	     fix this is to just insert another instruction here, so that the
- 	     instructions inserted after the last unconditional cleanup are
- 	     never the last instruction.  */
- 	  emit_note (NOTE_INSN_DELETED);
- 	}
-     }
-   return 1;
- }
- 
- /* Like expand_decl_cleanup, but maybe only run the cleanup if an exception
-    is thrown.  */
- 
- int
- expand_decl_cleanup_eh (tree decl, tree cleanup, int eh_only)
- {
-   int ret = expand_decl_cleanup (decl, cleanup);
-   if (cleanup && ret)
-     {
-       tree node = block_stack->data.block.cleanups;
-       CLEANUP_EH_ONLY (node) = eh_only;
-     }
-   return ret;
- }
  
  /* DECL is an anonymous union.  CLEANUP is a cleanup for DECL.
     DECL_ELTS is the list of elements that belong to DECL's type.
     In each, the TREE_VALUE is a VAR_DECL, and the TREE_PURPOSE a cleanup.  */
  
  void
! expand_anon_union_decl (tree decl, tree cleanup, tree decl_elts)
  {
-   struct nesting *thisblock = cfun == 0 ? 0 : block_stack;
    rtx x;
    tree t;
  
--- 2712,2726 ----
    pop_temp_slots ();
  }
  
  
  /* DECL is an anonymous union.  CLEANUP is a cleanup for DECL.
     DECL_ELTS is the list of elements that belong to DECL's type.
     In each, the TREE_VALUE is a VAR_DECL, and the TREE_PURPOSE a cleanup.  */
  
  void
! expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED,
! 			tree decl_elts)
  {
    rtx x;
    tree t;
  
*************** expand_anon_union_decl (tree decl, tree 
*** 3409,3422 ****
        }
  
    expand_decl (decl);
-   expand_decl_cleanup (decl, cleanup);
    x = DECL_RTL (decl);
  
    /* Go through the elements, assigning RTL to each.  */
    for (t = decl_elts; t; t = TREE_CHAIN (t))
      {
        tree decl_elt = TREE_VALUE (t);
-       tree cleanup_elt = TREE_PURPOSE (t);
        enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
  
        /* If any of the elements are addressable, so is the entire
--- 2733,2744 ----
*************** expand_anon_union_decl (tree decl, tree 
*** 3453,3597 ****
  	}
        else
  	abort ();
- 
-       /* Record the cleanup if there is one.  */
- 
-       if (cleanup != 0)
- 	thisblock->data.block.cleanups
- 	  = tree_cons (decl_elt, cleanup_elt,
- 		       thisblock->data.block.cleanups);
      }
  }
  
- /* Expand a list of cleanups LIST.
-    Elements may be expressions or may be nested lists.
- 
-    If IN_FIXUP is nonzero, we are generating this cleanup for a fixup
-    goto and handle protection regions specially in that case.
- 
-    If REACHABLE, we emit code, otherwise just inform the exception handling
-    code about this finalization.  */
- 
- static void
- expand_cleanups (tree list, int in_fixup, int reachable)
- {
-   tree tail;
-   for (tail = list; tail; tail = TREE_CHAIN (tail))
-     if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
-       expand_cleanups (TREE_VALUE (tail), in_fixup, reachable);
-     else
-       {
- 	if (! in_fixup && using_eh_for_cleanups_p)
- 	  expand_eh_region_end_cleanup (TREE_VALUE (tail));
- 
- 	if (reachable && !CLEANUP_EH_ONLY (tail))
- 	  {
- 	    /* Cleanups may be run multiple times.  For example,
- 	       when exiting a binding contour, we expand the
- 	       cleanups associated with that contour.  When a goto
- 	       within that binding contour has a target outside that
- 	       contour, it will expand all cleanups from its scope to
- 	       the target.  Though the cleanups are expanded multiple
- 	       times, the control paths are non-overlapping so the
- 	       cleanups will not be executed twice.  */
- 
- 	    /* We may need to protect from outer cleanups.  */
- 	    if (in_fixup && using_eh_for_cleanups_p)
- 	      {
- 		expand_eh_region_start ();
- 
- 		expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
- 
- 		expand_eh_region_end_fixup (TREE_VALUE (tail));
- 	      }
- 	    else
- 	      expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
- 
- 	    free_temp_slots ();
- 	  }
-       }
- }
- 
- /* Mark when the context we are emitting RTL for as a conditional
-    context, so that any cleanup actions we register with
-    expand_decl_init will be properly conditionalized when those
-    cleanup actions are later performed.  Must be called before any
-    expression (tree) is expanded that is within a conditional context.  */
- 
- void
- start_cleanup_deferral (void)
- {
-   /* block_stack can be NULL if we are inside the parameter list.  It is
-      OK to do nothing, because cleanups aren't possible here.  */
-   if (block_stack)
-     ++block_stack->data.block.conditional_code;
- }
- 
- /* Mark the end of a conditional region of code.  Because cleanup
-    deferrals may be nested, we may still be in a conditional region
-    after we end the currently deferred cleanups, only after we end all
-    deferred cleanups, are we back in unconditional code.  */
- 
- void
- end_cleanup_deferral (void)
- {
-   /* block_stack can be NULL if we are inside the parameter list.  It is
-      OK to do nothing, because cleanups aren't possible here.  */
-   if (block_stack)
-     --block_stack->data.block.conditional_code;
- }
- 
- tree
- last_cleanup_this_contour (void)
- {
-   if (block_stack == 0)
-     return 0;
- 
-   return block_stack->data.block.cleanups;
- }
- 
- 
- /* Return nonzero if any containing block has a stack level or
-    cleanups.  */
- 
- int
- containing_blocks_have_cleanups_or_stack_level (void)
- {
-   struct nesting *block;
- 
-   for (block = block_stack; block; block = block->next)
-     if (block->data.block.stack_level != 0
-         || block->data.block.cleanups != 0)
-       return 1;
- 
-   return 0;
- }
- 
- /* Return 1 if there are any pending cleanups at this point.
-    Check the current contour as well as contours that enclose
-    the current contour.  */
- 
- int
- any_pending_cleanups (void)
- {
-   struct nesting *block;
- 
-   if (cfun == NULL || cfun->stmt == NULL || block_stack == 0)
-     return 0;
- 
-   if (block_stack->data.block.cleanups != NULL)
-     return 1;
- 
-   if (block_stack->data.block.outer_cleanups == 0)
-     return 0;
- 
-   for (block = block_stack->next; block; block = block->next)
-     if (block->data.block.cleanups != 0)
-       return 1;
- 
-   return 0;
- }
- 
  /* Enter a case (Pascal) or switch (C) statement.
     Push a block onto case_stack and nesting_stack
     to accumulate the case-labels that are seen
--- 2775,2783 ----
*************** expand_start_case (int exit_flag, tree e
*** 3635,3642 ****
      emit_note (NOTE_INSN_DELETED);
  
    thiscase->data.case_stmt.start = get_last_insn ();
- 
-   start_cleanup_deferral ();
  }
  
  /* Accumulate one case or default label inside a case or switch statement.
--- 2821,2826 ----
*************** expand_start_case (int exit_flag, tree e
*** 3649,3655 ****
     If VALUE is a duplicate or overlaps, return 2 and do nothing
     except store the (first) duplicate node in *DUPLICATE.
     If VALUE is out of range, return 3 and do nothing.
-    If we are jumping into the scope of a cleanup or var-sized array, return 5.
     Return 0 on success.
  
     Extended to handle range statements.  */
--- 2833,2838 ----
*************** pushcase (tree value, tree (*converter) 
*** 3665,3674 ****
    if (! (case_stack && case_stack->data.case_stmt.start))
      return 1;
  
-   if (stack_block_stack
-       && stack_block_stack->depth > case_stack->depth)
-     return 5;
- 
    index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
    nominal_type = case_stack->data.case_stmt.nominal_type;
  
--- 2848,2853 ----
*************** pushcase_range (tree value1, tree value2
*** 3710,3719 ****
    if (! (case_stack && case_stack->data.case_stmt.start))
      return 1;
  
-   if (stack_block_stack
-       && stack_block_stack->depth > case_stack->depth)
-     return 5;
- 
    index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
    nominal_type = case_stack->data.case_stmt.nominal_type;
  
--- 2889,2894 ----
*************** expand_end_case_type (tree orig_index, t
*** 4268,4275 ****
        if (count != 0)
  	range = fold (build (MINUS_EXPR, index_type, maxval, minval));
  
-       end_cleanup_deferral ();
- 
        if (count == 0)
  	{
  	  expand_expr (index_expr, const0_rtx, VOIDmode, 0);
--- 3443,3448 ----
*************** expand_end_case_type (tree orig_index, t
*** 4482,4489 ****
        reorder_insns (before_case, end,
  		     thiscase->data.case_stmt.start);
      }
-   else
-     end_cleanup_deferral ();
  
    if (thiscase->exit_label && !exit_done)
      emit_label (thiscase->exit_label);
--- 3655,3660 ----
Index: gcc/tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.21
diff -c -p -d -r2.21 tree-pretty-print.c
*** gcc/tree-pretty-print.c	7 Jul 2004 21:26:30 -0000	2.21
--- gcc/tree-pretty-print.c	8 Jul 2004 07:19:34 -0000
*************** dump_generic_node (pretty_printer *buffe
*** 1185,1194 ****
        is_expr = false;
        break;
  
-     case GOTO_SUBROUTINE_EXPR:
-       NIY;
-       break;
- 
      case LABEL_EXPR:
        op0 = TREE_OPERAND (node, 0);
        /* If this is for break or continue, don't bother printing it.  */
--- 1185,1190 ----
Index: gcc/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.390
diff -c -p -d -r1.390 tree.c
*** gcc/tree.c	8 Jul 2004 03:40:29 -0000	1.390
--- gcc/tree.c	8 Jul 2004 07:19:34 -0000
*************** first_rtl_op (enum tree_code code)
*** 1493,1502 ****
  {
    switch (code)
      {
-     case GOTO_SUBROUTINE_EXPR:
-       return 0;
-     case WITH_CLEANUP_EXPR:
-       return 2;
      default:
        return TREE_CODE_LENGTH (code);
      }
--- 1493,1498 ----
*************** has_cleanups (tree exp)
*** 1850,1856 ****
    switch (TREE_CODE (exp))
      {
      case TARGET_EXPR:
-     case GOTO_SUBROUTINE_EXPR:
      case WITH_CLEANUP_EXPR:
        return 1;
  
--- 1846,1851 ----
Index: gcc/tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.def,v
retrieving revision 1.91
diff -c -p -d -r1.91 tree.def
*** gcc/tree.def	7 Jul 2004 21:26:30 -0000	1.91
--- gcc/tree.def	8 Jul 2004 07:19:34 -0000
*************** DEFTREECODE (LABELED_BLOCK_EXPR, "labele
*** 494,509 ****
  DEFTREECODE (CALL_EXPR, "call_expr", 'e', 3)
  
  /* Specify a value to compute along with its corresponding cleanup.
!    Operand 0 argument is an expression whose value needs a cleanup.
!    Operand 1 is the cleanup expression for the object.
!    Operand 2 is unused.
!    The cleanup is executed by the first enclosing CLEANUP_POINT_EXPR, if
!    it exists, otherwise it is the responsibility of the caller to manually
!    call expand_start_target_temps/expand_end_target_temps, as needed.
! 
!    This differs from TRY_CATCH_EXPR in that operand 2 is always
!    evaluated when an exception isn't thrown when cleanups are run.  */
! DEFTREECODE (WITH_CLEANUP_EXPR, "with_cleanup_expr", 'e', 3)
  
  /* Specify a cleanup point.
     Operand 0 is an expression that may have cleanups.  If it does, those
--- 494,504 ----
  DEFTREECODE (CALL_EXPR, "call_expr", 'e', 3)
  
  /* Specify a value to compute along with its corresponding cleanup.
!    Operand 0 is the cleanup expression.
!    The cleanup is executed by the first enclosing CLEANUP_POINT_EXPR,
!    which must exist.  This differs from TRY_CATCH_EXPR in that operand 1
!    is always evaluated when cleanups are run.  */
! DEFTREECODE (WITH_CLEANUP_EXPR, "with_cleanup_expr", 'e', 1)
  
  /* Specify a cleanup point.
     Operand 0 is an expression that may have cleanups.  If it does, those
*************** DEFTREECODE (LABEL_EXPR, "label_expr", '
*** 790,802 ****
     The type should be void and the value should be ignored.  */
  DEFTREECODE (GOTO_EXPR, "goto_expr", 's', 1)
  
- /* Used internally for cleanups in the implementation of TRY_FINALLY_EXPR.
-    (Specifically, it is created by expand_expr, not front-ends.)
-    Operand 0 is the rtx for the start of the subroutine we need to call.
-    Operand 1 is the rtx for a variable in which to store the address
-    of where the subroutine should return to.  */
- DEFTREECODE (GOTO_SUBROUTINE_EXPR, "goto_subroutine", 's', 2)
- 
  /* RETURN.  Evaluates operand 0, then returns from the current function.
     Presumably that operand is an assignment that stores into the
     RESULT_DECL that hold the value to be returned.
--- 785,790 ----
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.545
diff -c -p -d -r1.545 tree.h
*** gcc/tree.h	7 Jul 2004 22:03:43 -0000	1.545
--- gcc/tree.h	8 Jul 2004 07:19:34 -0000
*************** struct tree_vec GTY(())
*** 1025,1034 ****
  				 && VOID_TYPE_P (TREE_TYPE (NODE)) \
  				 && integer_zerop (TREE_OPERAND (NODE, 0)))
  
- /* In a WITH_CLEANUP_EXPR node.  */
- #define WITH_CLEANUP_EXPR_RTL(NODE) \
-   TREE_RTL_OPERAND_CHECK (NODE, WITH_CLEANUP_EXPR, 2)
- 
  /* In a CONSTRUCTOR node.  */
  #define CONSTRUCTOR_ELTS(NODE) TREE_OPERAND_CHECK_CODE (NODE, CONSTRUCTOR, 0)
  
--- 1025,1030 ----
*************** extern GTY (()) unsigned binfo_lang_slot
*** 2013,2022 ****
     specially.  */
  #define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl.bit_field_flag)
  
- /* In a LABEL_DECL, nonzero means label was defined inside a binding
-    contour that restored a stack level and which is now exited.  */
- #define DECL_TOO_LATE(NODE) (LABEL_DECL_CHECK (NODE)->decl.bit_field_flag)
- 
  /* Unused in FUNCTION_DECL.  */
  
  /* In a VAR_DECL that's static,
--- 2009,2014 ----
*************** extern bool commutative_tree_code (enum 
*** 3333,3339 ****
  
  /* In stmt.c */
  
- extern void expand_fixups (rtx);
  extern void expand_expr_stmt (tree);
  extern void expand_expr_stmt_value (tree, int, int);
  extern int warn_if_unused_value (tree, location_t);
--- 3325,3330 ----
*************** extern void expand_start_bindings_and_bl
*** 3355,3367 ****
    expand_start_bindings_and_block(flags, NULL_TREE)
  extern void expand_end_bindings (tree, int, int);
  extern void warn_about_unused_variables (tree);
- extern void start_cleanup_deferral (void);
- extern void end_cleanup_deferral (void);
  extern int is_body_block (tree);
  
  extern int conditional_context (void);
  extern struct nesting * current_nesting_level (void);
- extern tree last_cleanup_this_contour (void);
  extern void expand_start_case (int, tree, tree, const char *);
  extern void expand_end_case_type (tree, tree);
  #define expand_end_case(cond) expand_end_case_type (cond, NULL)
--- 3346,3355 ----
*************** extern void expand_asm_operands (tree, t
*** 3613,3629 ****
  extern void expand_asm_expr (tree);
  extern bool asm_op_is_mem_input (tree, tree);
  extern tree resolve_asm_operand_names (tree, tree, tree);
- extern int any_pending_cleanups (void);
  extern void init_stmt_for_function (void);
  extern void expand_start_target_temps (void);
  extern void expand_end_target_temps (void);
  extern void expand_elseif (tree);
- extern void save_stack_pointer (void);
  extern void expand_decl (tree);
- extern int expand_decl_cleanup (tree, tree);
- extern int expand_decl_cleanup_eh (tree, tree, int);
  extern void expand_anon_union_decl (tree, tree, tree);
- extern int containing_blocks_have_cleanups_or_stack_level (void);
  
  /* In gimplify.c.  */
  extern tree create_artificial_label (void);
--- 3601,3612 ----
Index: gcc/ada/trans.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ada/trans.c,v
retrieving revision 1.66
diff -c -p -d -r1.66 trans.c
*** gcc/ada/trans.c	2 Jul 2004 01:15:35 -0000	1.66
--- gcc/ada/trans.c	8 Jul 2004 07:19:35 -0000
*************** gnat_to_gnu (Node_Id gnat_node)
*** 3236,3255 ****
      case N_Handled_Sequence_Of_Statements:
  
        /* The GCC exception handling mechanism can handle both ZCX and SJLJ
! 	 schemes and we have our own SJLJ mechanism. To call the GCC
! 	 mechanism, we first call expand_eh_region_start if there is at least
! 	 one handler associated with the region.  We then generate code for
! 	 the region and call expand_start_all_catch to announce that the
! 	 associated handlers are going to be generated.
! 
! 	 For each handler we call expand_start_catch, generate code for the
! 	 handler, and then call expand_end_catch.
! 
! 	 After all the handlers, we call expand_end_all_catch.
! 
! 	 Here we deal with the region level calls and the
! 	 N_Exception_Handler branch deals with the handler level calls
! 	 (start_catch/end_catch).
  
  	 ??? The region level calls down there have been specifically put in
  	 place for a ZCX context and currently the order in which things are
--- 3236,3244 ----
      case N_Handled_Sequence_Of_Statements:
  
        /* The GCC exception handling mechanism can handle both ZCX and SJLJ
! 	 schemes and we have our own SJLJ mechanism.  To call the GCC
! 	 mechanism, we call add_cleanup, and when we leave the binding,
! 	 end_stmt_group will create the TRY_FINALLY_EXPR.
  
  	 ??? The region level calls down there have been specifically put in
  	 place for a ZCX context and currently the order in which things are
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.998
diff -c -p -d -r1.998 cp-tree.h
*** gcc/cp/cp-tree.h	8 Jul 2004 04:32:27 -0000	1.998
--- gcc/cp/cp-tree.h	8 Jul 2004 07:19:35 -0000
*************** extern void init_exception_processing		(
*** 3833,3839 ****
  extern tree expand_start_catch_block		(tree);
  extern void expand_end_catch_block		(void);
  extern void expand_builtin_throw		(void);
- extern void expand_eh_spec_block	        (tree);
  extern void expand_exception_blocks		(void);
  extern tree build_exc_ptr			(void);
  extern tree build_throw				(tree);
--- 3833,3838 ----
Index: gcc/java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.196
diff -c -p -d -r1.196 expr.c
*** gcc/java/expr.c	7 Jul 2004 10:20:59 -0000	1.196
--- gcc/java/expr.c	8 Jul 2004 07:19:35 -0000
*************** static void java_push_constant_from_pool
*** 85,93 ****
  static void java_stack_pop (int); 
  static tree build_java_throw_out_of_bounds_exception (tree); 
  static tree build_java_check_indexed_type (tree, tree); 
- static tree case_identity (tree, tree); 
  static unsigned char peek_opcode_at_pc (struct JCF *, int, int);
- static int emit_init_test_initialization (void **entry, void * ptr);
  
  static GTY(()) tree operand_type[59];
  
--- 85,91 ----
*************** load_type_state (tree label)
*** 2455,2695 ****
      type_map [i] = TREE_VEC_ELT (vec, i);
  }
  
- /* Do the expansion of a Java switch. With Gcc, switches are front-end
-    dependent things, but they rely on gcc routines. This function is
-    placed here because it uses things defined locally in parse.y. */
- 
- static tree
- case_identity (tree t __attribute__ ((__unused__)), tree v)
- {
-   return v;
- }
- 
- /* Return the name of the vtable for an array of a given primitive
-    type.  */
- static tree
- get_primitive_array_vtable (tree elt)
- {
-   tree r;
-   if (elt == boolean_type_node)
-     r = boolean_array_vtable;
-   else if (elt == byte_type_node)
-     r = byte_array_vtable;
-   else if (elt == char_type_node)
-     r = char_array_vtable;
-   else if (elt == short_type_node)
-     r = short_array_vtable;
-   else if (elt == int_type_node)
-     r = int_array_vtable;
-   else if (elt == long_type_node)
-     r = long_array_vtable;
-   else if (elt == float_type_node)
-     r = float_array_vtable;
-   else if (elt == double_type_node)
-     r = double_array_vtable;
-   else
-     abort ();
-   return build_address_of (r);
- }
- 
- struct rtx_def *
- java_expand_expr (tree exp, rtx target, enum machine_mode tmode,
- 		  int modifier /* Actually an enum expand_modifier. */,
- 		  rtx *alt_rtl ATTRIBUTE_UNUSED)
- {
-   tree current;
- 
-   abort ();
- 
-   switch (TREE_CODE (exp))
-     {
- 
-     case EXPR_WITH_FILE_LOCATION:
-       {
- 	rtx to_return;
- 	const char *saved_input_filename = input_filename;
- 	int saved_lineno = input_line;
- 	input_filename = EXPR_WFL_FILENAME (exp);
- 	input_line = EXPR_WFL_LINENO (exp);
-         if (EXPR_WFL_EMIT_LINE_NOTE (exp))
-           emit_line_note (input_location);
- 	/* Possibly avoid switching back and forth here.  */
- 	to_return = expand_expr (EXPR_WFL_NODE (exp), target, tmode, modifier);
- 	input_filename = saved_input_filename;
- 	input_line = saved_lineno;
- 	return to_return;
-       }
- 
-     case NEW_ARRAY_INIT:
-       {
- 	rtx tmp;
- 	tree array_type = TREE_TYPE (TREE_TYPE (exp));
- 	tree element_type = TYPE_ARRAY_ELEMENT (array_type);
- 	tree data_fld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
- 	HOST_WIDE_INT ilength = java_array_type_length (array_type);
- 	tree length = build_int_2 (ilength, 0);
- 	tree init = TREE_OPERAND (exp, 0);
- 	tree array_decl;
- 
- 	/* See if we can generate the array statically.  */
- 	if (TREE_CONSTANT (init) && TREE_STATIC (exp)
- 	    && JPRIMITIVE_TYPE_P (element_type))
- 	  {
- 	    tree temp, value, init_decl;
- 	    struct rtx_def *r;
- 	    START_RECORD_CONSTRUCTOR (temp, object_type_node);
- 	    PUSH_FIELD_VALUE (temp, "vtable",
- 			      get_primitive_array_vtable (element_type));
- 	    if (! flag_hash_synchronization)
- 	      PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
- 	    FINISH_RECORD_CONSTRUCTOR (temp);
- 	    START_RECORD_CONSTRUCTOR (value, array_type);
- 	    PUSH_SUPER_VALUE (value, temp);
- 	    PUSH_FIELD_VALUE (value, "length", length);
- 	    PUSH_FIELD_VALUE (value, "data", init);
- 	    FINISH_RECORD_CONSTRUCTOR (value);
- 
- 	    init_decl = build_decl (VAR_DECL, generate_name (), array_type);
- 	    pushdecl_top_level (init_decl);
- 	    TREE_STATIC (init_decl) = 1;
- 	    DECL_INITIAL (init_decl) = value;
- 	    DECL_IGNORED_P (init_decl) = 1;
- 	    TREE_READONLY (init_decl) = 1;
- 	    /* Hash synchronization requires at least 64-bit alignment. */
- 	    if (flag_hash_synchronization && POINTER_SIZE < 64)
- 	      DECL_ALIGN (init_decl) = 64;
- 	    rest_of_decl_compilation (init_decl, NULL, 1, 0);
- 	    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (init_decl)) = 1;
- 	    init = build1 (ADDR_EXPR, TREE_TYPE (exp), init_decl);
- 	    r = expand_expr (init, target, tmode, modifier);
- 	    return r;
- 	  }
- 
- 	array_decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
- 	expand_decl (array_decl);
- 	tmp = expand_assignment (array_decl,
- 				 build_new_array (element_type, length),
- 				 1);
- 	if (TREE_CONSTANT (init)
- 	    && ilength >= 10 && JPRIMITIVE_TYPE_P (element_type))
- 	  {
- 	    tree init_decl;
- 	    init_decl = build_decl (VAR_DECL, generate_name (),
- 				    TREE_TYPE (init));
- 	    pushdecl_top_level (init_decl);
- 	    TREE_STATIC (init_decl) = 1;
- 	    DECL_INITIAL (init_decl) = init;
- 	    DECL_IGNORED_P (init_decl) = 1;
- 	    TREE_READONLY (init_decl) = 1;
- 	    rest_of_decl_compilation (init_decl, NULL, 1, 0);
- 	    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (init_decl)) = 1;
- 	    init = init_decl;
- 	  }
- 	expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
- 				  build_java_indirect_ref (array_type, 
- 					  array_decl, flag_check_references), 
- 				  data_fld, NULL_TREE),
- 			   init, 0);
- 	return tmp;
-       }
-     case BLOCK:
-       if (BLOCK_EXPR_BODY (exp))
- 	{
- 	  tree local;
- 	  rtx last;
- 	  tree body = BLOCK_EXPR_BODY (exp);
- 	  /* Set to 1 or more when we found a static class
-              initialization flag. */
- 	  int found_class_initialization_flag = 0;
- 
- 	  pushlevel (2);	/* 2 and above */
- 	  expand_start_bindings (0);
- 	  local = BLOCK_EXPR_DECLS (exp);
- 	  while (local)
- 	    {
- 	      tree next = TREE_CHAIN (local);
- 	      found_class_initialization_flag +=
- 		LOCAL_CLASS_INITIALIZATION_FLAG_P (local);
- 	      layout_decl (local, 0);
- 	      expand_decl (pushdecl (local));
- 	      local = next;
- 	    }
- 
- 	  /* Emit initialization code for test flags if we saw one. */
- 	  if (! always_initialize_class_p 
- 	      && current_function_decl
- 	      && found_class_initialization_flag)
- 	    htab_traverse 
- 	      (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
- 	       emit_init_test_initialization, NULL);
- 
- 	  /* Avoid deep recursion for long block.  */
- 	  while (TREE_CODE (body) == COMPOUND_EXPR)
- 	    {
- 	      expand_expr (TREE_OPERAND (body, 0), const0_rtx, VOIDmode, 0);
- 	      emit_queue ();
- 	      body = TREE_OPERAND (body, 1);
- 	    }
-   	  last = expand_expr (body, NULL_RTX, VOIDmode, 0);
- 	  emit_queue ();
- 	  expand_end_bindings (getdecls (), 1, 0);
- 	  poplevel (1, 1, 0);
- 	  return last;
- 	}
-       return const0_rtx;
- 
-     case CASE_EXPR:
-       {
- 	tree duplicate;
- 	if (pushcase (TREE_OPERAND (exp, 0), case_identity,
- 		      build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), 
- 		      &duplicate) == 2)
- 	  {
- 	    EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (exp);
- 	    parse_error_context
- 	      (wfl_operator, "Duplicate case label: `%s'",
- 	       print_int_node (TREE_OPERAND (exp, 0)));
- 	  }
- 	return const0_rtx;
-       }
- 
-     case DEFAULT_EXPR:
-       pushcase (NULL_TREE, 0, 
- 		build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), NULL);
-       return const0_rtx;
- 
-     case TRY_EXPR:
-       /* We expand a try[-catch] block */
- 
-       /* Expand the try block */
-       expand_eh_region_start ();
-       expand_expr_stmt (TREE_OPERAND (exp, 0));
-       expand_start_all_catch ();
- 
-       /* Expand all catch clauses (EH handlers) */
-       for (current = TREE_OPERAND (exp, 1); current; 
- 	   current = TREE_CHAIN (current))
- 	{
- 	  tree catch = TREE_OPERAND (current, 0);
- 	  tree decl = BLOCK_EXPR_DECLS (catch);
- 	  tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
- 
- 	  expand_start_catch (prepare_eh_table_type (type));
- 	  expand_expr_stmt (TREE_OPERAND (current, 0));
- 	  expand_end_catch ();
- 	}
-       expand_end_all_catch ();
-       return const0_rtx;
- 
-     case JAVA_EXC_OBJ_EXPR:
-       return expand_expr (build_exception_object_ref (TREE_TYPE (exp)),
- 			  target, tmode, modifier);
- 
-     default:
-       internal_error ("can't expand %s", tree_code_name [TREE_CODE (exp)]);
-     }
- }
- 
  /* Go over METHOD's bytecode and note instruction starts in
     instruction_bits[].  */
  
--- 2453,2458 ----
*************** force_evaluation_order (tree node)
*** 3448,3486 ****
    return node;
  }
  
- /* Called for every element in DECL_FUNCTION_INIT_TEST_TABLE of a
-    method in order to emit initialization code for each test flag.  */
- 
- static int
- emit_init_test_initialization (void **entry, void *x ATTRIBUTE_UNUSED)
- {
-   struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
-   tree klass = build_class_ref (ite->key);
-   tree rhs;
- 
-   /* If the DECL_INITIAL of the test flag is set to true, it
-      means that the class is already initialized the time it
-      is in use. */
-   if (DECL_INITIAL (ite->value) == boolean_true_node)
-     rhs = boolean_true_node;
-   /* Otherwise, we initialize the class init check variable by looking
-      at the `state' field of the class to see if it is already
-      initialized.  This makes things a bit faster if the class is
-      already initialized, which should be the common case.  */
-   else
-     rhs = build (GE_EXPR, boolean_type_node,
- 		 build (COMPONENT_REF, byte_type_node,
- 			build1 (INDIRECT_REF, class_type_node, klass),
- 			lookup_field (&class_type_node,
- 				      get_identifier ("state")),
- 			NULL_TREE),
- 		 build_int_2 (JV_STATE_DONE, 0));
- 
-   expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node, 
- 			   ite->value, rhs));
-   return true;
- }
- 
  /* EXPR_WITH_FILE_LOCATION are used to keep track of the exact
     location where an expression or an identifier were encountered. It
     is necessary for languages where the frontend parser will handle
--- 3211,3216 ----
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.207
diff -c -p -d -r1.207 java-tree.h
*** gcc/java/java-tree.h	7 Jul 2004 10:21:00 -0000	1.207
--- gcc/java/java-tree.h	8 Jul 2004 07:19:35 -0000
*************** extern tree decl_constant_value (tree);
*** 1333,1341 ****
  
  extern void java_mark_class_local (tree);
  
- #if defined(RTX_CODE) && defined (HAVE_MACHINE_MODES)
- struct rtx_def * java_expand_expr (tree, rtx, enum machine_mode, int, rtx *); 
- #endif
  extern void java_inlining_merge_static_initializers (tree, void *);
  extern void java_inlining_map_static_initializers (tree, void *);
  
--- 1333,1338 ----
Index: gcc/java/lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.153
diff -c -p -d -r1.153 lang.c
*** gcc/java/lang.c	27 Jun 2004 18:16:48 -0000	1.153
--- gcc/java/lang.c	8 Jul 2004 07:19:35 -0000
*************** struct language_function GTY(())
*** 224,231 ****
  #define LANG_HOOKS_UNSAFE_FOR_REEVAL java_unsafe_for_reeval
  #undef LANG_HOOKS_MARK_ADDRESSABLE
  #define LANG_HOOKS_MARK_ADDRESSABLE java_mark_addressable
- #undef LANG_HOOKS_EXPAND_EXPR
- #define LANG_HOOKS_EXPAND_EXPR java_expand_expr
  #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
  #define LANG_HOOKS_TRUTHVALUE_CONVERSION java_truthvalue_conversion
  #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
--- 224,229 ----


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