This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa] C++ simplification patch


At long last, here's the patch which implements simplification of C++.  The
remaining failures are mostly for line number differences and -Wswitch, as
with the C frontend.

At first I had thought I only needed to add EH support, but of course that
was naive; most of the work had to do with various quirks of how the C++
frontend handles initialization.

Some things I'm still uncomfortable with:

  The hoops I'm jumping through to deal with C++ initialization semantics,
  particularly in returns, by adding new parms for simplify_modify_expr and
  simplify_cond_expr.  Suggestions of a better way are welcome.

  Handling of temporary variables created by the frontends.  Currently the
  genericizer assumes that an artificial decl with no name has not been
  pushed into a block, so it should be added to the main list of temps.
  This seems rather fragile, but it also seems to match existing practice.

  EH_FILTER_MUST_NOT_THROW is kind of a kludge, but doing better would
  require the backend to understand the difference between terminate and
  unexpected.

  EH handling of cleanups -- C++ says that if a cleanup run as a result of
  throwing an exception also throws, we call terminate.  However, if a
  cleanup run as a result of flowing off the end of a block throws, we
  propagate that exception.  This distinction is currently handled by the
  expander, controlled by lang_protect_cleanup_actions.  This works, but
  it's flow information which is hidden from the tree optimizers.  Lowering
  TRY_FINALLY_EXPR should solve this problem.

Other notes:

  Note that with this patch all the testcases which use old-style named
  return values will crash.  I don't care, as Mark has removed that support
  from the new parser.

  All tree optimizers are currently disabled for C++.  Remove the "&& 0" in
  cp/optimize.c:optimize_function to enable them.

Tested i686-pc-linux-gnu.

ChangeLog:
2003-01-02  Jason Merrill  <jason@redhat.com>

	* c-common.c (finish_fname_decls): Put the DECL_STMTs inside the
	outermost scope.
	* c-decl.c (c_make_fname_decl): Push the decls there, too.

	* fold-const.c (fold) [COND_EXPR]: Avoid NOP_EXPRs better.

	* integrate.c (copy_decl_for_inlining): Don't clear the rtl for
	static/external decls.
	
ChangeLog.tree-ssa:
2003-01-02  Jason Merrill  <jason@redhat.com>

	* c-simplify.c (c_genericize): Dump more info about the function.
	Use dump_function.
	* tree-dump.c (dump_function): Move from cp/optimize.c.
	* tree-dump.h: Declare it.

	* gimplify.c (mostly_copy_tree_r): Remove unnecessary cases.
	(unshare_expr): New fn.
	* tree-inline.c (mark_local_for_remap_r, unsave_r): New fns, adapted
	from C++ versions.
	(lhd_unsave_expr_now): Likewise.
	* tree.c (unsave_expr_now): Remove.
	(unsafe_for_reeval): Labels and BIND_EXPRs are only somewhat unsafe.

	* gimplify.c (simplify_function_tree): Add an outer BIND_EXPR if
	needed.
	(voidify_wrapper_expr): Not static.  Abort if we try to voidify an 
	expression with TREE_ADDRESSABLE type.  Be clever with INDIRECT_REFs.
	(foreach_stmt): Avoid redundant work.
	(create_tmp_var): Abort if we try to create a temp of ADDRESSABLE type.
	(simplify_expr): Simplify VTABLE_REF.
	* c-simplify.c (simplify_decl_stmt): Ignore DECL_EXTERNAL decls.
	(simplify_stmt_expr): Fix thinko.
	(simplify_block): Don't ignore partial scopes.
	(simplify_condition): New fn.
	(simplify_c_loop, simplify_if_stmt, simplify_switch_stmt): Call it.
	* expr.c (expand_expr) [BIND_EXPR]: Handle statics better.
	* tree-inline.c (remap_decl): Remap all decls.
	(declare_return_variable): Be clever with INDIRECT_REFs.
	(expand_call_inline): If we have an explicit return slot, the inlined
	body is void.
	(walk_tree): Fix type handling.
	(copy_tree_r): Don't walk into decls.
	* tree-simple.c (is_simple_unary_expr): Handle VTABLE_REF.
	(is_simple_id): Allow RESULT_DECL.
	* tree-simple.h (gsi_stmt): Strip WFLs and NOPs.

	* gimplify.c (simplify_cond_expr): Handle void arms.  Add target parm.
	(simplify_modify_expr): Pass it.  Add special handling for COND_EXPR
	and CONSTRUCTOR (from Daniel Berlin).  Add want_value parm.
	(simplify_expr): Pass new args. Loop sooner if language-specific
	simplification happened.
	(simplify_return_expr): Pass the whole MODIFY_EXPR to simplify_expr.
	(simplify_target_expr): Simplify.

	* tree.def (CATCH_EXPR, EH_FILTER_EXPR): New tree codes.
	* except.c (expand_eh_handler): New fn.
	(expand_eh_region_end_allowed): If no types are allowed, hand off to
	expand_eh_region_end_must_not_throw.
	* except.h: Declare expand_eh_handler.
	* expr.c (expand_expr) [TRY_CATCH_EXPR]: Use it.
	[CATCH_EXPR, EH_FILTER_EXPR]: New cases.
	* gimplify.c (simplify_expr) [EXC_PTR_EXPR, CATCH_EXPR, 
	EH_FILTER_EXPR]: New cases.
	(gimple_build_eh_filter): New fn.
	(maybe_protect_cleanup): New fn.
	(gimple_push_cleanup): Call it.
	(simplify_cleanup_point_expr): Fix thinko.
	* c-simplify.c (simplify_cleanup): Call it.
	* tree-simple.h: Declare it.
	* Makefile.in (gimplify.o): Depend on except.h.
	* tree.h (CATCH_TYPES, CATCH_BODY): New macros.
	(EH_FILTER_TYPES, EH_FILTER_FAILURE): New macros.
	* tree-simple.c (is_simple_id): Allow EXC_PTR_EXPR.
	* c-pretty-print.c (dump_c_node) [CLEANUP_POINT_EXPR]: Support.
	* tree-pretty-print.c (dump_generic_node): Likewise.
	[CATCH_EXPR, EH_FILTER_EXPR, EXC_PTR_EXPR]: Support.

	* c-pretty-print.c (NIY): Print operands.
	(dump_c_tree): Don't look at TREE_CHAIN if it doesn't matter.
	(dump_c_node) [ARRAY_TYPE]: Handle non-constant array bounds.
	[CALL_EXPR]: Pass spc down.
	[VTABLE_REF]: Support.
	(op_prio) [TARGET_EXPR]: Support.
	(print_call_name): Handle function pointers.
	* tree-pretty-print.c: Likewise.

cp/ChangeLog:
2003-01-02  Jason Merrill  <jason@redhat.com>

	* call.c (build_conditional_expr): Stabilize lvalues properly.
	* cvt.c (ocp_convert): Don't build NOP_EXPRs of class type.

	* call.c (convert_like_real): Call decl_constant_value for an
	IDENTITY_CONV even if there are no more conversions.

	* cvt.c (build_up_reference): Don't push unnamed temps.

	* decl.c (cp_make_fname_decl): Push the decls inside the
	outermost scope.

	* decl2.c (do_namespace_alias): Namespace aliases are DECL_EXTERNAL.

	* dump.c (cp_dump_tree): Don't try to dump class-specific fields
	for a backend struct.

	* except.c (wrap_cleanups_r, build_throw): Make
	MUST_NOT_THROW_EXPRs void.
	* init.c (expand_default_init): Update to handle MUST_NOT_THROW_EXPR.

	* init.c (build_vec_delete_1): Pre-evaluate the base address.

	* init.c (get_temp_regvar): Tweak.

	* tree.c (lvalue_p_1): Don't allow sloppy NOP_EXPRs as lvalues.
	Don't allow CALL_EXPR or VA_ARG_EXPR, either.

	* tree.c (cp_copy_res_decl_for_inlining): Only do debug tweaks if
	our replacement is a decl.

cp/ChangeLog.tree-ssa:	
2003-01-02  Jason Merrill  <jason@redhat.com>

	* Make-lang.in (CXX_C_OBJS): Replace old-tree-inline.o with
	tree-inline.o.

	* optimize.c (dump_function): Move to ../tree-dump.c.

	* cp-simplify.c (cp_simplify_expr): Handle PTRMEM_CST, INIT_EXPR, 
	MODIFY_EXPR and EMPTY_CLASS_EXPR.
	(cp_simplify_stmt): Handle USING_STMT.
	(cp_simplify_init_expr): New fn.
	* cvt.c (build_up_reference): Don't push the decl.
	* class.c (build_vtable_entry_ref, build_vtbl_ref_1): Unshare the 
	vtable address.
	* init.c (build_vtbl_address): Likewise.
	* cp-lang.c (LANG_HOOKS_UNSAVE_EXPR_NOW): Remove.
	* decl.c (lookup_name_real): Unshare the expansion of an ALIAS_DECL.
	(finish_function): Don't genericize templates.
	* parse.y (parse_asm_stmt): Fix prototype.
	* semantics.c (expand_body): Don't expand if we saw errors.
	Drop support for expanding non-GENERIC code.

	* cp-simplify.c (cp_simplify_stmt): Handle HANDLER and EH_SPEC_BLOCK.
	(genericize_try_block): Always build a TRY_CATCH_EXPR.
	(genericize_catch_block): New fn.
	(genericize_eh_spec_block): New fn.
	(cp_simplify_expr): Handle THROW_EXPR and MUST_NOT_THROW_EXPR.
	(simplify_must_not_throw_expr): New fn.
	* except.c (wrap_cleanups_r): Make the MUST_NOT_THROW_EXPR void.
	(build_throw): Likewise.

*** ./cp/Make-lang.in.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./cp/Make-lang.in	2002-12-14 23:07:36.000000000 -0500
*************** g++-cross$(exeext): g++$(exeext)
*** 80,86 ****
  # Shared with C front end:
  CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
   c-dump.o $(CXX_TARGET_OBJS) c-opts.o c-simplify.o c-pretty-print.o           \
!  old-tree-inline.o
  
  # Language-specific object files.
  CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
--- 80,86 ----
  # Shared with C front end:
  CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
   c-dump.o $(CXX_TARGET_OBJS) c-opts.o c-simplify.o c-pretty-print.o           \
!  tree-inline.o
  
  # Language-specific object files.
  CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
*** ./cp/call.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./cp/call.c	2003-01-02 11:43:03.000000000 -0500
*************** build_conditional_expr (tree arg1, tree 
*** 2997,3003 ****
      {
        if (pedantic)
  	pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
!       arg1 = arg2 = save_expr (arg1);
      }
  
    /* [expr.cond]
--- 2997,3006 ----
      {
        if (pedantic)
  	pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
!       if (real_lvalue_p (arg1))
! 	arg2 = arg1 = stabilize_reference (arg1);
!       else
! 	arg2 = arg1 = save_expr (arg1);
      }
  
    /* [expr.cond]
*************** convert_like_real (tree convs, tree expr
*** 3974,3979 ****
--- 3977,3988 ----
      case IDENTITY_CONV:
        if (type_unknown_p (expr))
  	expr = instantiate_type (totype, expr, tf_error | tf_warning);
+       /* Convert a non-array constant variable to its underlying value, unless we
+ 	 are about to bind it to a reference, in which case we need to
+ 	 leave it as an lvalue.  */
+       if (inner >= 0
+ 	  && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
+ 	expr = decl_constant_value (expr);
        return expr;
      case AMBIG_CONV:
        /* Call build_user_type_conversion again for the error.  */
*************** convert_like_real (tree convs, tree expr
*** 3989,4001 ****
    if (expr == error_mark_node)
      return error_mark_node;
  
-   /* Convert a non-array constant variable to its underlying value, unless we
-      are about to bind it to a reference, in which case we need to
-      leave it as an lvalue.  */
-   if (TREE_CODE (convs) != REF_BIND
-       && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
-     expr = decl_constant_value (expr);
- 
    switch (TREE_CODE (convs))
      {
      case RVALUE_CONV:
--- 3998,4003 ----
*** ./cp/class.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./cp/class.c	2003-01-02 11:43:05.000000000 -0500
*************** build_vtable_entry_ref (array_ref, insta
*** 396,402 ****
      basetype = TREE_TYPE (basetype);
  
    vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
!   first_fn = TYPE_BINFO_VTABLE (basetype);
  
    i = fold (build_array_ref (first_fn, idx));
    i = fold (build_c_cast (ptrdiff_type_node,
--- 396,402 ----
      basetype = TREE_TYPE (basetype);
  
    vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
!   first_fn = unshare_expr (TYPE_BINFO_VTABLE (basetype));
  
    i = fold (build_array_ref (first_fn, idx));
    i = fold (build_c_cast (ptrdiff_type_node,
*************** build_vtbl_ref_1 (instance, idx)
*** 439,445 ****
        tree binfo = lookup_base (fixed_type, basetype,
  				ba_ignore|ba_quiet, NULL);
        if (binfo)
! 	vtbl = BINFO_VTABLE (binfo);
      }
  
    if (!vtbl)
--- 439,445 ----
        tree binfo = lookup_base (fixed_type, basetype,
  				ba_ignore|ba_quiet, NULL);
        if (binfo)
! 	vtbl = unshare_expr (BINFO_VTABLE (binfo));
      }
  
    if (!vtbl)
*** ./cp/cp-lang.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./cp/cp-lang.c	2002-12-31 18:25:20.000000000 -0500
*************** static bool cp_var_mod_type_p PARAMS ((t
*** 65,72 ****
  #define LANG_HOOKS_PARSE_FILE c_common_parse_file
  #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
  #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL cxx_dup_lang_specific_decl
- #undef LANG_HOOKS_UNSAVE_EXPR_NOW
- #define LANG_HOOKS_UNSAVE_EXPR_NOW cxx_unsave_expr_now
  #undef LANG_HOOKS_MAYBE_BUILD_CLEANUP
  #define LANG_HOOKS_MAYBE_BUILD_CLEANUP cxx_maybe_build_cleanup
  #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
--- 65,70 ----
*** ./cp/cp-simplify.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./cp/cp-simplify.c	2003-01-02 16:26:45.000000000 -0500
*************** Software Foundation, 59 Temple Place - S
*** 31,36 ****
--- 31,40 ----
  #include "tree-simple.h"
  
  static void genericize_try_block	PARAMS ((tree *));
+ static void genericize_catch_block	PARAMS ((tree *));
+ static void genericize_eh_spec_block	PARAMS ((tree *));
+ static void simplify_must_not_throw_expr PARAMS ((tree *, tree *));
+ static void cp_simplify_init_expr	PARAMS ((tree *, tree *, tree *));
  
  /* Genericize a C++ _STMT.  Called from c_simplify_stmt.  */
  
*************** cp_simplify_stmt (stmt_p, next_p)
*** 46,51 ****
--- 50,69 ----
        genericize_try_block (stmt_p);
        return 1;
  
+     case HANDLER:
+       genericize_catch_block (stmt_p);
+       return 1;
+ 
+     case EH_SPEC_BLOCK:
+       genericize_eh_spec_block (stmt_p);
+       return 1;
+ 
+     case USING_STMT:
+       /* Just ignore for now.  Eventually we will want to pass this on to
+ 	 the debugger.  */
+       *stmt_p = empty_stmt_node;
+       return 1;
+ 
      default:
        break;
      }
*************** static void
*** 58,78 ****
  genericize_try_block (stmt_p)
       tree *stmt_p;
  {
!   tree stmt = *stmt_p;
  
!   if (CLEANUP_P (stmt))
!     {
!       /* Just convert to a TRY_CATCH_EXPR.  */
!       tree body = TRY_STMTS (stmt);
!       tree cleanup = TRY_HANDLERS (stmt);
  
!       c_simplify_stmt (&body);
  
!       *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
!     }
!   else
!     /* FIXME a real try block.  */
!     abort ();
  }
  
  /* Do C++-specific simplification.  Args are as for simplify_expr.  */
--- 76,120 ----
  genericize_try_block (stmt_p)
       tree *stmt_p;
  {
!   tree body = TRY_STMTS (*stmt_p);
!   tree cleanup = TRY_HANDLERS (*stmt_p);
  
!   c_simplify_stmt (&body);
!   /* cleanup is an expression, so it doesn't need to be genericized.  */
  
!   *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
! }
  
! /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
! 
! static void
! genericize_catch_block (stmt_p)
!      tree *stmt_p;
! {
!   tree type = HANDLER_TYPE (*stmt_p);
!   tree body = HANDLER_BODY (*stmt_p);
! 
!   c_simplify_stmt (&body);
! 
!   /* FIXME should the caught type go in TREE_TYPE?  */
!   *stmt_p = build (CATCH_EXPR, void_type_node, type, body);
! }
! 
! /* Genericize an EH_SPEC_BLOCK by converting it to a
!    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
! 
! static void
! genericize_eh_spec_block (stmt_p)
!      tree *stmt_p;
! {
!   tree body = EH_SPEC_STMTS (*stmt_p);
!   tree allowed = EH_SPEC_RAISES (*stmt_p);
!   tree failure = build_call (call_unexpected_node,
! 			     tree_cons (NULL_TREE, build_exc_ptr (),
! 					NULL_TREE));
!   c_simplify_stmt (&body);
! 
!   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
  }
  
  /* Do C++-specific simplification.  Args are as for simplify_expr.  */
*************** cp_simplify_expr (expr_p, pre_p, post_p)
*** 85,94 ****
--- 127,159 ----
  {
    switch (TREE_CODE (*expr_p))
      {
+     case PTRMEM_CST:
+       *expr_p = cplus_expand_constant (*expr_p);
+       return 1;
+ 
      case AGGR_INIT_EXPR:
        simplify_aggr_init_expr (expr_p);
+       return 1;
+ 
+     case THROW_EXPR:
+       /* FIXME communicate throw type to backend, probably by moving
+ 	 THROW_EXPR into ../tree.def.  */
+       *expr_p = TREE_OPERAND (*expr_p, 0);
+       return 1;
+ 
+     case MUST_NOT_THROW_EXPR:
+       simplify_must_not_throw_expr (expr_p, pre_p);
+       return 1;
+ 
+     case INIT_EXPR:
+     case MODIFY_EXPR:
+       cp_simplify_init_expr (expr_p, pre_p, post_p);
        break;
  
+     case EMPTY_CLASS_EXPR:
+       *expr_p = integer_zero_node;
+       return 1;
+ 
      default:
        break;
      }
*************** cp_simplify_expr (expr_p, pre_p, post_p)
*** 96,101 ****
--- 161,200 ----
    return c_simplify_expr (expr_p, pre_p, post_p);
  }
  
+ /* Simplify initialization from an AGGR_INIT_EXPR.  */
+ 
+ static void
+ cp_simplify_init_expr (expr_p, pre_p, post_p)
+      tree *expr_p;
+      tree *pre_p;
+      tree *post_p;
+ {
+   tree from = TREE_OPERAND (*expr_p, 1);
+   tree to = TREE_OPERAND (*expr_p, 0);
+ 
+   /* If we are initializing something from a TARGET_EXPR, strip the
+      TARGET_EXPR and initialize it directly.  */
+   /* What about code that pulls out the temp and uses it elsewhere?  I
+      think that such code never uses the TARGET_EXPR as an initializer.  If
+      I'm wrong, we'll abort because the temp won't have any RTL.  In that
+      case, I guess we'll need to replace references somehow.  */
+   if (TREE_CODE (from) == TARGET_EXPR)
+     from = TARGET_EXPR_INITIAL (from);
+ 
+   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
+      replace the slot operand with our target.
+ 
+      Should we add a target parm to simplify_expr instead?  No, as in this
+      case we want to replace the INIT_EXPR.  */
+   if (TREE_CODE (from) == AGGR_INIT_EXPR)
+     {
+       simplify_expr (&to, pre_p, post_p, is_simple_modify_expr_lhs, fb_lvalue);
+       TREE_OPERAND (from, 2) = to;
+       *expr_p = from;
+       simplify_aggr_init_expr (expr_p);
+     }
+ }
+ 
  /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR.  */
  
  void
*************** simplify_aggr_init_expr (tp)
*** 177,179 ****
--- 276,303 ----
    TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
    *tp = call_expr;
  }
+ 
+ /* Simplify a MUST_NOT_THROW_EXPR.  */
+ 
+ static void
+ simplify_must_not_throw_expr (expr_p, pre_p)
+      tree *expr_p;
+      tree *pre_p;
+ {
+   tree stmt = *expr_p;
+   tree temp = voidify_wrapper_expr (stmt);
+   tree body = TREE_OPERAND (stmt, 0);
+ 
+   simplify_stmt (&body);
+ 
+   stmt = gimple_build_eh_filter (body, NULL_TREE,
+ 				 build_call (terminate_node, NULL_TREE));
+ 
+   if (temp)
+     {
+       add_tree (stmt, pre_p);
+       *expr_p = temp;
+     }
+   else
+     *expr_p = stmt;
+ }
*** ./cp/cvt.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./cp/cvt.c	2002-12-31 12:53:37.000000000 -0500
*************** build_up_reference (type, arg, flags, de
*** 386,392 ****
  	{
  	  /* Automatic; make sure we handle the cleanup properly.  */
  	  maybe_push_cleanup_level (argtype);
! 	  arg = pushdecl (arg);
  	}
  
        /* Process the initializer for the declaration.  */
--- 386,393 ----
  	{
  	  /* Automatic; make sure we handle the cleanup properly.  */
  	  maybe_push_cleanup_level (argtype);
! 	  /* Don't push unnamed temps.  Do set DECL_CONTEXT, though.  */
! 	  DECL_CONTEXT (arg) = current_function_decl;
  	}
  
        /* Process the initializer for the declaration.  */
*************** ocp_convert (type, expr, convtype, flags
*** 671,676 ****
--- 672,686 ----
           conversion.  */
        else if (TREE_CODE (type) == COMPLEX_TYPE)
          return fold (convert_to_complex (type, e));
+       else if (TREE_CODE (e) == TARGET_EXPR)
+ 	{
+ 	  /* Don't build a NOP_EXPR of class type.  Instead, change the
+ 	     type of the temporary.  */
+ 	  TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
+ 	  return e;
+ 	}
+       else if (CLASS_TYPE_P (type))
+ 	abort ();
        else
  	return fold (build1 (NOP_EXPR, type, e));
      }
*** ./cp/decl.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/decl.c	2003-01-02 16:29:59.000000000 -0500
*************** does not match lookup in the current sco
*** 6235,6241 ****
      val = from_obj;
  
    if (val && TREE_CODE (val) == ALIAS_DECL)
!     val = DECL_INITIAL (val);
  
    return val;
  }
--- 6235,6241 ----
      val = from_obj;
  
    if (val && TREE_CODE (val) == ALIAS_DECL)
!     val = unshare_expr (DECL_INITIAL (val));
  
    return val;
  }
*************** cxx_init_decl_processing ()
*** 6706,6714 ****
       say -fwritable-strings?  */
    if (flag_writable_strings)
      flag_const_strings = 0;
- 
-   /* Disable for now.  */
-   flag_disable_simple = 1;
  }
  
  /* Generate an initializer for a function naming variable from
--- 6706,6711 ----
*************** cp_make_fname_decl (id, type_dep)
*** 6760,6766 ****
    tree init = cp_fname_init (name);
    tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
  
!   /* As we don't push the decl here, we must set the context.  */
    DECL_CONTEXT (decl) = current_function_decl;
    DECL_PRETTY_FUNCTION_P (decl) = type_dep;
        
--- 6757,6763 ----
    tree init = cp_fname_init (name);
    tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
  
!   /* As we're using pushdecl_with_scope, we must set the context.  */
    DECL_CONTEXT (decl) = current_function_decl;
    DECL_PRETTY_FUNCTION_P (decl) = type_dep;
        
*************** cp_make_fname_decl (id, type_dep)
*** 6771,6776 ****
--- 6768,6781 ----
    
    TREE_USED (decl) = 1;
  
+   if (current_function_decl)
+     {
+       struct cp_binding_level *b = current_binding_level;
+       while (b->level_chain->parm_flag == 0)
+ 	b = b->level_chain;
+       pushdecl_with_scope (decl, b);
+     }	
+ 
    cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
        
    return decl;
*************** finish_function (flags)
*** 14563,14569 ****
      warning ("no return statement in function returning non-void");
      
    /* Genericize before inlining.  */
!   if (!flag_disable_simple)
      c_genericize (fndecl);
  
    /* Clear out memory we no longer need.  */
--- 14568,14574 ----
      warning ("no return statement in function returning non-void");
      
    /* Genericize before inlining.  */
!   if (!flag_disable_simple && !processing_template_decl)
      c_genericize (fndecl);
  
    /* Clear out memory we no longer need.  */
*** ./cp/decl2.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/decl2.c	2003-01-02 11:43:08.000000000 -0500
*************** do_namespace_alias (alias, namespace)
*** 4326,4331 ****
--- 4326,4332 ----
    /* Build the alias.  */
    alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);     
    DECL_NAMESPACE_ALIAS (alias) = namespace;
+   DECL_EXTERNAL (alias) = 1;
    pushdecl (alias);
  }
  
*** ./cp/dump.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/dump.c	2002-12-19 13:54:13.000000000 -0500
*************** cp_dump_tree (dump_info, t)
*** 265,270 ****
--- 265,273 ----
  	  return 1;
  	}
  
+       if (! IS_AGGR_TYPE (t))
+ 	break;
+ 
        dump_child ("vfld", TYPE_VFIELD (t));
        if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t))
          dump_string(di, "spec");
*** ./cp/except.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/except.c	2002-12-22 16:04:20.000000000 -0500
*************** wrap_cleanups_r (tp, walk_subtrees, data
*** 561,567 ****
    cleanup = TARGET_EXPR_CLEANUP (exp);
    if (cleanup)
      {
!       cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup);
        TARGET_EXPR_CLEANUP (exp) = cleanup;
      }
  
--- 561,567 ----
    cleanup = TARGET_EXPR_CLEANUP (exp);
    if (cleanup)
      {
!       cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
        TARGET_EXPR_CLEANUP (exp) = cleanup;
      }
  
*************** build_throw (exp)
*** 733,739 ****
  	  return error_mark_node;
  	}
  
!       exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
        /* Prepend the allocation.  */
        exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
        if (temp_expr != void_zero_node)
--- 733,739 ----
  	  return error_mark_node;
  	}
  
!       exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
        /* Prepend the allocation.  */
        exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
        if (temp_expr != void_zero_node)
*** ./cp/init.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/init.c	2003-01-02 15:41:46.000000000 -0500
*************** Boston, MA 02111-1307, USA.  */
*** 35,40 ****
--- 35,41 ----
  #include "except.h"
  #include "toplev.h"
  #include "ggc.h"
+ #include "tree-inline.h"
  
  static void construct_virtual_base (tree, tree);
  static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
*************** build_vtbl_address (binfo)
*** 737,743 ****
    TREE_USED (vtbl) = 1;
  
    /* Now compute the address to use when initializing the vptr.  */
!   vtbl = BINFO_VTABLE (binfo_for);
    if (TREE_CODE (vtbl) == VAR_DECL)
      {
        vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
--- 738,744 ----
    TREE_USED (vtbl) = 1;
  
    /* Now compute the address to use when initializing the vptr.  */
!   vtbl = unshare_expr (BINFO_VTABLE (binfo_for));
    if (TREE_CODE (vtbl) == VAR_DECL)
      {
        vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
*************** expand_default_init (binfo, true_exp, ex
*** 1193,1205 ****
        else
  	init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
  
!       if (TREE_CODE (init) == TRY_CATCH_EXPR)
! 	/* We need to protect the initialization of a catch parm
! 	   with a call to terminate(), which shows up as a TRY_CATCH_EXPR
  	   around the TARGET_EXPR for the copy constructor.  See
! 	   expand_start_catch_block.  */
! 	TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
! 					TREE_OPERAND (init, 0));
        else
  	init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
        TREE_SIDE_EFFECTS (init) = 1;
--- 1194,1209 ----
        else
  	init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
  
!       if (TREE_CODE (init) == MUST_NOT_THROW_EXPR)
! 	/* We need to protect the initialization of a catch parm with a
! 	   call to terminate(), which shows up as a MUST_NOT_THROW_EXPR
  	   around the TARGET_EXPR for the copy constructor.  See
! 	   initialize_handler_parm.  */
! 	{
! 	  TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
! 					  TREE_OPERAND (init, 0));
! 	  TREE_TYPE (init) = void_type_node;
! 	}
        else
  	init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
        TREE_SIDE_EFFECTS (init) = 1;
*************** build_vec_delete_1 (base, maxindex, type
*** 2639,2648 ****
    if (controller)
      {
        TREE_OPERAND (controller, 1) = body;
!       return controller;
      }
!   else
!     return cp_convert (void_type_node, body);
  }
  
  /* Create an unnamed variable of the indicated TYPE.  */ 
--- 2643,2656 ----
    if (controller)
      {
        TREE_OPERAND (controller, 1) = body;
!       body = controller;
      }
! 
!   if (TREE_CODE (base) == SAVE_EXPR)
!     /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR.  */
!     body = build (COMPOUND_EXPR, void_type_node, base, body);
! 
!   return cp_convert (void_type_node, body);
  }
  
  /* Create an unnamed variable of the indicated TYPE.  */ 
*************** get_temp_regvar (type, init)
*** 2680,2686 ****
    decl = create_temporary_var (type);
    if (building_stmt_tree ())
      add_decl_stmt (decl);
!   if (!building_stmt_tree ())
      SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1));
    finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
  
--- 2688,2694 ----
    decl = create_temporary_var (type);
    if (building_stmt_tree ())
      add_decl_stmt (decl);
!   else
      SET_DECL_RTL (decl, assign_temp (type, 2, 0, 1));
    finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
  
*** ./cp/optimize.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/optimize.c	2003-01-02 15:50:29.000000000 -0500
*************** Software Foundation, 59 Temple Place - S
*** 39,50 ****
  #include "flags.h"
  #include "langhooks.h"
  #include "diagnostic.h"
  
  /* Prototypes.  */
  
  static tree calls_setjmp_r (tree *, int *, void *);
  static void update_cloned_parm (tree, tree);
- static void dump_function (enum tree_dump_index, tree);
  
  /* Optimize the body of FN.  */
  
--- 39,50 ----
  #include "flags.h"
  #include "langhooks.h"
  #include "diagnostic.h"
+ #include "tree-dump.h"
  
  /* Prototypes.  */
  
  static tree calls_setjmp_r (tree *, int *, void *);
  static void update_cloned_parm (tree, tree);
  
  /* Optimize the body of FN.  */
  
*************** optimize_function (tree fn)
*** 86,92 ****
        dump_function (TDI_simple, fn);
  
        /* Invoke the SSA tree optimizer.  */
!       if (optimize >= 1)
  	optimize_function_tree (fn);
      }
  
--- 86,92 ----
        dump_function (TDI_simple, fn);
  
        /* Invoke the SSA tree optimizer.  */
!       if (optimize >= 1 && 0)
  	optimize_function_tree (fn);
      }
  
*************** maybe_clone_body (tree fn)
*** 283,311 ****
    /* We don't need to process the original function any further.  */
    return 1;
  }
- 
- /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
- 
- static void
- dump_function (enum tree_dump_index phase, tree fn)
- {
-   FILE *stream;
-   int flags;
- 
-   stream = dump_begin (phase, &flags);
-   if (stream)
-     {
-       fprintf (stream, "\n;; Function %s",
- 	       decl_as_string (fn, TFF_DECL_SPECIFIERS));
-       fprintf (stream, " (%s)\n",
- 	       decl_as_string (DECL_ASSEMBLER_NAME (fn), 0));
-       fprintf (stream, ";; enabled by -%s\n", dump_flag_name (phase));
-       fprintf (stream, "\n");
-       
-       if (flags & TDF_RAW)
- 	dump_node (fn, TDF_SLIM | flags, stream);
-       else
- 	print_generic_stmt (stream, DECL_SAVED_TREE (fn), 0);
-       dump_end (phase, stream);
-     }
- }
--- 283,285 ----
*** ./cp/parse.y.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/parse.y	2003-01-02 11:39:29.000000000 -0500
*************** static tree parse_handle_class_head (tre
*** 132,138 ****
  static void parse_decl_instantiation (tree, tree, tree);
  static int parse_begin_function_definition (tree, tree);
  static tree parse_finish_call_expr (tree, tree, int);
! extern tree parse_asm_stmt PARAMS ((tree, tree, tree, tree, tree));
  
  /* Cons up an empty parameter list.  */
  static inline tree
--- 132,138 ----
  static void parse_decl_instantiation (tree, tree, tree);
  static int parse_begin_function_definition (tree, tree);
  static tree parse_finish_call_expr (tree, tree, int);
! static tree parse_asm_stmt PARAMS ((tree, tree, tree, tree, tree));
  
  /* Cons up an empty parameter list.  */
  static inline tree
*** ./cp/semantics.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/semantics.c	2003-01-02 11:43:11.000000000 -0500
***************
*** 41,46 ****
--- 41,47 ----
  #include "output.h"
  #include "timevar.h"
  #include "debug.h"
+ #include "diagnostic.h"
  
  /* There routines provide a modular interface to perform many parsing
     operations.  They may therefore be used during actual parsing, or
*************** expand_body (fn)
*** 2316,2321 ****
--- 2317,2328 ----
    if (DECL_EXTERNAL (fn))
      return;
  
+   if (errorcount || sorrycount)
+     {
+       TREE_ASM_WRITTEN (fn) = 1;
+       return;
+     }
+ 
    /* Save the current file name and line number.  When we expand the
       body of the function, we'll set LINENO and INPUT_FILENAME so that
       error-mesages come out in the right places.  */
*************** expand_body (fn)
*** 2339,2356 ****
  
    /* Expand the body.  */
    if (statement_code_p (TREE_CODE (DECL_SAVED_TREE (fn))))
!     expand_stmt (DECL_SAVED_TREE (fn));
!   else
!     expand_expr_stmt_value (DECL_SAVED_TREE (fn), 0, 0);
  
    /* Statements should always be full-expressions at the outermost set
       of curly braces for a function.  */
    my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
  
-   /* The outermost statement for a function contains the line number
-      recorded when we finished processing the function.  */
-   lineno = STMT_LINENO (DECL_SAVED_TREE (fn));
- 
    /* Generate code for the function.  */
    genrtl_finish_function (fn);
  
--- 2346,2359 ----
  
    /* Expand the body.  */
    if (statement_code_p (TREE_CODE (DECL_SAVED_TREE (fn))))
!     abort ();
! 
!   expand_expr_stmt_value (DECL_SAVED_TREE (fn), 0, 0);
  
    /* Statements should always be full-expressions at the outermost set
       of curly braces for a function.  */
    my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
  
    /* Generate code for the function.  */
    genrtl_finish_function (fn);
  
*** ./cp/tree.c.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./cp/tree.c	2002-12-31 19:34:24.000000000 -0500
*************** lvalue_p_1 (ref, treat_class_rvalues_as_
*** 93,105 ****
  			 allow_cast_as_lvalue);
  
      case NOP_EXPR:
!       /* If expression doesn't change the type, we consider it as an
! 	 lvalue even when cast_as_lvalue extension isn't selected.
! 	 That's because parts of the compiler are alleged to be sloppy
! 	 about sticking in NOP_EXPR node for no good reason.  */
!       if (allow_cast_as_lvalue ||
! 	  same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)),
! 		       TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0)))))
  	return lvalue_p_1 (TREE_OPERAND (ref, 0),
  			   treat_class_rvalues_as_lvalues,
  			   allow_cast_as_lvalue);
--- 93,99 ----
  			 allow_cast_as_lvalue);
  
      case NOP_EXPR:
!       if (allow_cast_as_lvalue)
  	return lvalue_p_1 (TREE_OPERAND (ref, 0),
  			   treat_class_rvalues_as_lvalues,
  			   allow_cast_as_lvalue);
*************** lvalue_p_1 (ref, treat_class_rvalues_as_
*** 179,187 ****
  
      case CALL_EXPR:
      case VA_ARG_EXPR:
!       return ((treat_class_rvalues_as_lvalues
! 	       && IS_AGGR_TYPE (TREE_TYPE (ref)))
! 	      ? clk_class : clk_none);
  
      case FUNCTION_DECL:
        /* All functions (except non-static-member functions) are
--- 173,180 ----
  
      case CALL_EXPR:
      case VA_ARG_EXPR:
!       /* Any class-valued call would be wrapped in a TARGET_EXPR.  */
!       return clk_none;
  
      case FUNCTION_DECL:
        /* All functions (except non-static-member functions) are
*************** cp_copy_res_decl_for_inlining (result, f
*** 2368,2380 ****
  	  /* We have a named return value; copy the name and source
  	     position so we can get reasonable debugging information, and
  	     register the return variable as its equivalent.  */
! 	  DECL_NAME (var) = DECL_NAME (nrv);
! 	  DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
! 	  DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
! 	  /* Don't lose initialization info.  */
! 	  DECL_INITIAL (var) = DECL_INITIAL (nrv);
! 	  /* Don't forget that it needs to go in the stack.  */
! 	  TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
  
  	  splay_tree_insert (decl_map,
  			     (splay_tree_key) nrv,
--- 2361,2376 ----
  	  /* We have a named return value; copy the name and source
  	     position so we can get reasonable debugging information, and
  	     register the return variable as its equivalent.  */
! 	  if (TREE_CODE (var) == VAR_DECL)
! 	    {
! 	      DECL_NAME (var) = DECL_NAME (nrv);
! 	      DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
! 	      DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
! 	      /* Don't lose initialization info.  */
! 	      DECL_INITIAL (var) = DECL_INITIAL (nrv);
! 	      /* Don't forget that it needs to go in the stack.  */
! 	      TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
! 	    }
  
  	  splay_tree_insert (decl_map,
  			     (splay_tree_key) nrv,
*** ./Makefile.in.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./Makefile.in	2003-01-02 11:41:14.000000000 -0500
*************** c-simplify.o : c-simplify.c $(CONFIG_H) 
*** 1446,1452 ****
     $(TM_H) coretypes.h
  gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
     diagnostic.h tree-simple.h tree-inline.h varray.h langhooks.h \
!    langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h
  tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
     $(TM_H) coretypes.h
--- 1446,1452 ----
     $(TM_H) coretypes.h
  gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
     diagnostic.h tree-simple.h tree-inline.h varray.h langhooks.h \
!    langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h
  tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
     $(TM_H) coretypes.h
*** ./c-common.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./c-common.c	2002-12-31 02:23:41.000000000 -0500
*************** finish_fname_decls ()
*** 1055,1067 ****
    
    if (body)
      {
!       /* They were called into existence, so add to statement tree.  */
!       body = chainon (body,
! 		      TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)));
!       body = build_stmt (COMPOUND_STMT, body);
!       
!       COMPOUND_STMT_NO_SCOPE (body) = 1;
!       TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)) = body;
      }
    
    for (ix = 0; fname_vars[ix].decl; ix++)
--- 1055,1072 ----
    
    if (body)
      {
!       /* They were called into existence, so add to statement tree.  Add
! 	 the DECL_STMTs inside the outermost scope.  */
!       tree *p = &DECL_SAVED_TREE (current_function_decl);
!       /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK.  */
!       while (TREE_CODE (*p) != COMPOUND_STMT)
! 	p = &TREE_CHAIN (*p);
!       p = &COMPOUND_BODY (*p);
!       if (TREE_CODE (*p) == SCOPE_STMT)
! 	p = &TREE_CHAIN (*p);
! 
!       body = chainon (body, *p);
!       *p = body;
      }
    
    for (ix = 0; fname_vars[ix].decl; ix++)
*************** finish_fname_decls ()
*** 1084,1090 ****
    saved_function_name_decls = stack;
  }
  
! /* Return the text name of the current function, suitable prettified
     by PRETTY_P.  */
  
  const char *
--- 1089,1095 ----
    saved_function_name_decls = stack;
  }
  
! /* Return the text name of the current function, suitably prettified
     by PRETTY_P.  */
  
  const char *
*************** fname_decl (rid, id)
*** 1168,1174 ****
      }
    if (!ix && !current_function_decl)
      pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
!   
    return decl;
  }
  
--- 1173,1179 ----
      }
    if (!ix && !current_function_decl)
      pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
! 
    return decl;
  }
  
*** ./c-decl.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./c-decl.c	2003-01-02 11:41:16.000000000 -0500
*************** c_make_fname_decl (id, type_dep)
*** 2552,2557 ****
--- 2552,2569 ----
    DECL_INITIAL (decl) = init;
  
    TREE_USED (decl) = 1;
+ 
+   if (current_function_decl)
+     {
+       /* Add the decls to the outermost block.  */
+       struct binding_level *b = current_binding_level;
+       struct binding_level *old = b;
+       while (b->level_chain->parm_flag == 0)
+ 	b = b->level_chain;
+       current_binding_level = b;
+       pushdecl (decl);
+       current_binding_level = old;
+     }	
    
    finish_decl (decl, init, NULL_TREE);
  
*** ./c-pretty-print.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./c-pretty-print.c	2003-01-02 15:51:21.000000000 -0500
*************** Software Foundation, 59 Temple Place - S
*** 30,35 ****
--- 30,36 ----
  #include "diagnostic.h"
  #include "real.h"
  #include "hashtab.h"
+ #include "langhooks.h"
  
  static int op_prio				PARAMS ((tree));
  static const char *op_symbol			PARAMS ((tree));
*************** static void dump_c_tree				PARAMS ((outp
*** 49,72 ****
        							 int));
  static int dump_c_node				PARAMS ((output_buffer *, tree,
        							 int, int));
! 
  
  #define INDENT(SPACE) do { \
    int i; for (i = 0; i<SPACE; i++) output_add_space (buffer); } while (0)
! #define NIY do { \
!     output_add_string (buffer, "<<< Unknown tree: "); \
!     output_add_string (buffer, tree_code_name[(int) TREE_CODE (node)]); \
!     output_add_string (buffer, " >>>\n"); } while (0)
  
  #define PRINT_FUNCTION_NAME(NODE)  output_printf             \
    (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ?              \
!    IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (NODE, 0))) : \
!    IDENTIFIER_POINTER (DECL_NAME (NODE)))
! 
  
  static output_buffer buffer;
  static int initialized = 0;
  
  /* Print the tree T in full, on file FILE.  */
   
  void 
--- 50,93 ----
        							 int));
  static int dump_c_node				PARAMS ((output_buffer *, tree,
        							 int, int));
! static void do_niy				PARAMS ((output_buffer *,
! 							 tree));
  
  #define INDENT(SPACE) do { \
    int i; for (i = 0; i<SPACE; i++) output_add_space (buffer); } while (0)
! 
! #define NIY do_niy(buffer,node)
  
  #define PRINT_FUNCTION_NAME(NODE)  output_printf             \
    (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ?              \
!    (*lang_hooks.decl_printable_name) (TREE_OPERAND (NODE, 0), 1) : \
!    (*lang_hooks.decl_printable_name) (NODE, 1))
  
  static output_buffer buffer;
  static int initialized = 0;
  
+ /* Try to print something for an unknown tree code.  */
+ 
+ static void
+ do_niy (buffer, node)
+      output_buffer *buffer;
+      tree node;
+ {
+   int i, len;
+ 
+   output_add_string (buffer, "<<< Unknown tree: ");
+   output_add_string (buffer, tree_code_name[(int) TREE_CODE (node)]);
+ 
+   len = first_rtl_op (TREE_CODE (node));
+   for (i = 0; i < len; ++i)
+     {
+       newline_and_indent (buffer, 2);
+       dump_c_node (buffer, TREE_OPERAND (node, i), 2, 0);
+     }
+ 
+   output_add_string (buffer, " >>>\n");
+ }
+      
  /* Print the tree T in full, on file FILE.  */
   
  void 
*************** dump_c_tree (buffer, t, spc)
*** 185,190 ****
--- 206,215 ----
  	default:
  	  break;
  	}
+ 
+       if (!(*lang_hooks.tree_inlining.tree_chain_matters_p) (node))
+ 	break;
+ 
        node = TREE_CHAIN (node);
        if (htab_find (htab, node))
  	{
*************** dump_c_node (buffer, node, spc, brief_du
*** 379,387 ****
  	  {
  	    output_add_character (buffer, '[');
  	    if (TYPE_SIZE (tmp))
! 	      output_decimal (buffer,
! 			      TREE_INT_CST_LOW (TYPE_SIZE (tmp)) / 
! 			      TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tmp))));
  	    output_add_character (buffer, ']');
  	    tmp = TREE_TYPE (tmp);
  	  }
--- 404,419 ----
  	  {
  	    output_add_character (buffer, '[');
  	    if (TYPE_SIZE (tmp))
! 	      {
! 		tree size = TYPE_SIZE (tmp);
! 		if (TREE_CODE (size) == INTEGER_CST)
! 		  output_decimal (buffer,
! 				  TREE_INT_CST_LOW (TYPE_SIZE (tmp)) / 
! 				  TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tmp))));
! 		else if (TREE_CODE (size) == MULT_EXPR)
! 		  dump_c_node (buffer, TREE_OPERAND (size, 0), spc, brief_dump);
! 		/* else punt.  */
! 	      }
  	    output_add_character (buffer, ']');
  	    tmp = TREE_TYPE (tmp);
  	  }
*************** dump_c_node (buffer, node, spc, brief_du
*** 790,796 ****
        output_add_character (buffer, '(');
        op1 = TREE_OPERAND (node, 1);
        if (op1)
! 	dump_c_node (buffer, op1, 0, brief_dump);
        output_add_character (buffer, ')');
        break;
  
--- 822,828 ----
        output_add_character (buffer, '(');
        op1 = TREE_OPERAND (node, 1);
        if (op1)
! 	dump_c_node (buffer, op1, spc, brief_dump);
        output_add_character (buffer, ')');
        break;
  
*************** dump_c_node (buffer, node, spc, brief_du
*** 803,809 ****
        break;
  
      case CLEANUP_POINT_EXPR:
!       NIY;
        break;
  
      case PLACEHOLDER_EXPR:
--- 835,843 ----
        break;
  
      case CLEANUP_POINT_EXPR:
!       output_add_string (buffer, "<<cleanup_point ");
!       dump_c_node (buffer, TREE_OPERAND (node, 0), spc, brief_dump);
!       output_add_string (buffer, ">>");
        break;
  
      case PLACEHOLDER_EXPR:
*************** dump_c_node (buffer, node, spc, brief_du
*** 1451,1456 ****
--- 1485,1500 ----
        dump_c_node (buffer, op0, spc, brief_dump);
        break;
  
+     case VTABLE_REF:
+       output_add_string (buffer, "VTABLE_REF <(");
+       dump_c_node (buffer, TREE_OPERAND (node, 0), spc, brief_dump);
+       output_add_string (buffer, "),");
+       dump_c_node (buffer, TREE_OPERAND (node, 1), spc, brief_dump);
+       output_add_character (buffer, ',');
+       dump_c_node (buffer, TREE_OPERAND (node, 2), spc, brief_dump);
+       output_add_character (buffer, '>');
+       break;
+ 
      default:
        NIY;
      }
*************** op_prio (op)
*** 1749,1754 ****
--- 1793,1799 ----
      case FIX_CEIL_EXPR:
      case FIX_FLOOR_EXPR:
      case FIX_ROUND_EXPR:
+     case TARGET_EXPR:
        return 14;
  
      case CALL_EXPR:
*************** print_call_name (buffer, node)
*** 1935,1943 ****
      case ADDR_EXPR:
      case INDIRECT_REF:
      case NOP_EXPR:
!       PRINT_FUNCTION_NAME (TREE_OPERAND (op0, 0));
        break;
!     
      case EXPR_WITH_FILE_LOCATION:
        if (TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
          PRINT_FUNCTION_NAME (TREE_OPERAND (op0, 0));
--- 1980,1988 ----
      case ADDR_EXPR:
      case INDIRECT_REF:
      case NOP_EXPR:
!       dump_c_node (buffer, TREE_OPERAND (op0, 0), 0, 0);
        break;
! 
      case EXPR_WITH_FILE_LOCATION:
        if (TREE_CODE (TREE_OPERAND (op0, 0)) == VAR_DECL)
          PRINT_FUNCTION_NAME (TREE_OPERAND (op0, 0));
*** ./java/parse.y.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./java/parse.y	2003-01-02 11:39:33.000000000 -0500
*************** catch_clause_parameter:
*** 1933,1939 ****
  		  declare_local_variables (0, TREE_VALUE ($3),
  					   build_tree_list (TREE_PURPOSE ($3),
  							    init));
! 		  $$ = build1 (CATCH_EXPR, NULL_TREE, ccpb);
  		  EXPR_WFL_LINECOL ($$) = $1.location;
  		}
  |	CATCH_TK error
--- 1933,1939 ----
  		  declare_local_variables (0, TREE_VALUE ($3),
  					   build_tree_list (TREE_PURPOSE ($3),
  							    init));
! 		  $$ = build1 (JAVA_CATCH_EXPR, NULL_TREE, ccpb);
  		  EXPR_WFL_LINECOL ($$) = $1.location;
  		}
  |	CATCH_TK error
*************** encapsulate_with_try_catch (location, ty
*** 15475,15482 ****
    /* Add the catch statements */
    add_stmt_to_block (catch_block, NULL_TREE, catch_stmts);
  
!   /* Now we can build a CATCH_EXPR */
!   catch_block = build1 (CATCH_EXPR, NULL_TREE, catch_block);
  
    return build_try_statement (location, try_block, catch_block);
  }
--- 15475,15482 ----
    /* Add the catch statements */
    add_stmt_to_block (catch_block, NULL_TREE, catch_stmts);
  
!   /* Now we can build a JAVA_CATCH_EXPR */
!   catch_block = build1 (JAVA_CATCH_EXPR, NULL_TREE, catch_block);
  
    return build_try_statement (location, try_block, catch_block);
  }
*************** patch_try_statement (node)
*** 15522,15528 ****
        int unreachable;
  
        /* At this point, the structure of the catch clause is
! 	   CATCH_EXPR		(catch node)
  	     BLOCK	        (with the decl of the parameter)
                 COMPOUND_EXPR
                   MODIFY_EXPR   (assignment of the catch parameter)
--- 15522,15528 ----
        int unreachable;
  
        /* At this point, the structure of the catch clause is
! 	   JAVA_CATCH_EXPR		(catch node)
  	     BLOCK	        (with the decl of the parameter)
                 COMPOUND_EXPR
                   MODIFY_EXPR   (assignment of the catch parameter)
*** ./java/java-tree.def.~1~	2003-01-02 12:14:46.000000000 -0500
--- ./java/java-tree.def	2003-01-02 00:23:28.000000000 -0500
*************** DEFTREECODE (TRY_EXPR, "try-catch", 'e',
*** 55,61 ****
  /* Catch clause.
     Operand 0 is the catch clause block, which contains the declaration of
     the catch clause parameter.  */
! DEFTREECODE (CATCH_EXPR, "catch", '1', 1)
  
  /* Synchronized statement.
     Operand 0 is the expression on which we wish to synchronize,
--- 55,61 ----
  /* Catch clause.
     Operand 0 is the catch clause block, which contains the declaration of
     the catch clause parameter.  */
! DEFTREECODE (JAVA_CATCH_EXPR, "catch", '1', 1)
  
  /* Synchronized statement.
     Operand 0 is the expression on which we wish to synchronize,
*** ./except.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./except.c	2003-01-01 20:21:33.000000000 -0500
*************** expand_eh_region_end ()
*** 534,539 ****
--- 534,573 ----
    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 (handler)
+      tree handler;
+ {
+   tree inner = handler;
+   while (TREE_CODE (inner) == COMPOUND_EXPR
+ 	 || TREE_CODE (inner) == EXPR_WITH_FILE_LOCATION)
+     inner = TREE_OPERAND (inner, 0);
+ 
+   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.  */
  
*** ./c-simplify.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./c-simplify.c	2003-01-02 16:28:04.000000000 -0500
*************** Software Foundation, 59 Temple Place - S
*** 44,49 ****
--- 44,50 ----
  #include "flags.h"
  #include "rtl.h"
  #include "toplev.h"
+ #include "tree-dump.h"
  
  /*  The simplification pass converts the language-dependent trees
      (ld-trees) emitted by the parser into language-independent trees
*************** static void pop_context              PAR
*** 89,94 ****
--- 90,96 ----
  static tree c_build_bind_expr	     PARAMS ((tree, tree));
  static void add_block_to_enclosing   PARAMS ((tree));
  static tree mostly_copy_tree_r       PARAMS ((tree *, int *, void *));
+ static void simplify_condition		PARAMS ((tree *));
  
  enum bc_t { bc_break = 0, bc_continue = 1 };
  static tree begin_bc_block PARAMS ((enum bc_t));
*************** c_genericize (fndecl)
*** 137,143 ****
    dump_file = dump_begin (TDI_original, &dump_flags);
    if (dump_file)
      {
!       fprintf (dump_file, "%s()\n", IDENTIFIER_POINTER (DECL_NAME (fndecl)));
  
        if (dump_flags & TDF_RAW)
  	dump_node (DECL_SAVED_TREE (fndecl), TDF_SLIM | dump_flags, dump_file);
--- 139,150 ----
    dump_file = dump_begin (TDI_original, &dump_flags);
    if (dump_file)
      {
!       fprintf (dump_file, "\n;; Function %s",
! 	       (*lang_hooks.decl_printable_name) (fndecl, 2));
!       fprintf (dump_file, " (%s)\n",
! 	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
!       fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
!       fprintf (dump_file, "\n");
  
        if (dump_flags & TDF_RAW)
  	dump_node (DECL_SAVED_TREE (fndecl), TDF_SLIM | dump_flags, dump_file);
*************** c_genericize (fndecl)
*** 154,172 ****
    pop_context ();
  
    /* Dump the genericized tree IR.  */
!   dump_file = dump_begin (TDI_generic, &dump_flags);
!   if (dump_file)
!     {
!       fprintf (dump_file, "%s()\n", IDENTIFIER_POINTER (DECL_NAME (fndecl)));
! 
!       if (dump_flags & TDF_RAW)
! 	dump_node (DECL_SAVED_TREE (fndecl), TDF_SLIM | dump_flags, dump_file);
!       else
! 	print_generic_stmt (dump_file, DECL_SAVED_TREE (fndecl), 0);
!       fprintf (dump_file, "\n");
! 
!       dump_end (TDI_generic, dump_file);
!     }
  }
  
  /*  Entry point for the tree lowering pass.  Recursively scan
--- 161,167 ----
    pop_context ();
  
    /* Dump the genericized tree IR.  */
!   dump_function (TDI_generic, fndecl);
  }
  
  /*  Entry point for the tree lowering pass.  Recursively scan
*************** simplify_block (stmt_p, next_p)
*** 398,408 ****
    for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
      if (TREE_CODE (*p) == SCOPE_STMT)
        {
! 	if (SCOPE_PARTIAL_P (*p))
! 	  /* Throw away partial scopes.  Hmm, that probably won't work;
! 	     we need to remember them to handle goto cleanups.  */
! 	  abort ();
! 	else if (SCOPE_BEGIN_P (*p))
  	  ++depth;
  	else if (--depth == 0)
  	  break;
--- 393,399 ----
    for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
      if (TREE_CODE (*p) == SCOPE_STMT)
        {
! 	if (SCOPE_BEGIN_P (*p))
  	  ++depth;
  	else if (--depth == 0)
  	  break;
*************** simplify_cleanup (stmt_p, next_p)
*** 428,439 ****
  {
    tree stmt = *stmt_p;
    tree body = TREE_CHAIN (stmt);
    enum tree_code code
      = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
  
    c_simplify_stmt (&body);
  
!   *stmt_p = build (code, void_type_node, body, CLEANUP_EXPR (stmt));
    *next_p = NULL_TREE;
  }
  
--- 419,433 ----
  {
    tree stmt = *stmt_p;
    tree body = TREE_CHAIN (stmt);
+   tree cleanup = CLEANUP_EXPR (stmt);
    enum tree_code code
      = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
  
+   cleanup = maybe_protect_cleanup (cleanup);
+ 
    c_simplify_stmt (&body);
  
!   *stmt_p = build (code, void_type_node, body, cleanup);
    *next_p = NULL_TREE;
  }
  
*************** simplify_expr_stmt (stmt_p)
*** 482,487 ****
--- 476,499 ----
    *stmt_p = stmt;
  }
  
+ /* If the condition for a loop (or the like) is a decl, it will be a
+    TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
+    a use of the decl.  Turn such a thing into a COMPOUND_EXPR.  */
+ 
+ static void
+ simplify_condition (cond_p)
+      tree *cond_p;
+ {
+   tree cond = *cond_p;
+   if (cond && TREE_CODE (cond) == TREE_LIST)
+     {
+       tree decl = TREE_PURPOSE (cond);
+       tree value = TREE_VALUE (cond);
+       c_simplify_stmt (&decl);
+       *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
+     }
+ }
+ 
  /* Begin a scope which can be exited by a break or continue statement.  BC
     indicates which.
  
*************** simplify_c_loop (cond, body, incr, cond_
*** 575,580 ****
--- 587,593 ----
  
    if (cond)
      {
+       simplify_condition (&cond);
        exit = build_bc_goto (bc_break);
        exit = build (COND_EXPR, void_type_node, cond, empty_stmt_node, exit);
        exit = fold (exit);
*************** simplify_if_stmt (stmt_p)
*** 662,667 ****
--- 675,682 ----
    tree else_ = ELSE_CLAUSE (stmt);
    tree cond = IF_COND (stmt);
  
+   simplify_condition (&cond);
+ 
    c_simplify_stmt (&then_);
    c_simplify_stmt (&else_);
  
*************** simplify_switch_stmt (stmt_p)
*** 679,684 ****
--- 694,701 ----
    tree break_block, switch_;
    tree cond = SWITCH_COND (stmt);
  
+   simplify_condition (&cond);
+ 
    break_block = begin_bc_block (bc_break);
  
    c_simplify_stmt (&body);
*************** simplify_decl_stmt (stmt_p, next_p)
*** 728,734 ****
    tree decl = DECL_STMT_DECL (stmt);
    tree pre = NULL_TREE;
  
!   if (TREE_CODE (decl) == VAR_DECL)
      {
        tree init = DECL_INITIAL (decl);
  
--- 745,751 ----
    tree decl = DECL_STMT_DECL (stmt);
    tree pre = NULL_TREE;
  
!   if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
      {
        tree init = DECL_INITIAL (decl);
  
*************** simplify_decl_stmt (stmt_p, next_p)
*** 739,744 ****
--- 756,763 ----
  	     its size, and so that any other local variables used in those
  	     expressions will have been initialized.  */
  
+ 	  /* FIXME break the allocation out into a separate statement.  */
+ 
  	  tree size = DECL_SIZE (decl);
  	  tree usize = DECL_SIZE_UNIT (decl);
  	  tree bind;
*************** simplify_decl_stmt (stmt_p, next_p)
*** 763,769 ****
  
  	  add_tree (bind, &pre);
  
! 	  *next_p = NULL_TREE;
  	}
  
        if (init && init != error_mark_node && !TREE_STATIC (decl))
--- 782,789 ----
  
  	  add_tree (bind, &pre);
  
! 	  if (next_p)
! 	    *next_p = NULL_TREE;
  	}
  
        if (init && init != error_mark_node && !TREE_STATIC (decl))
*************** simplify_decl_stmt (stmt_p, next_p)
*** 774,785 ****
  	    init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
  	  add_tree (init, &pre);
  	}
-     }
  
!   /* This decl isn't mentioned in the enclosing block, so add it to
!      the list of temps.  */
!   if (DECL_ARTIFICIAL (decl))
!     gimple_add_tmp_var (decl);
  
    *stmt_p = pre;
  }
--- 794,806 ----
  	    init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
  	  add_tree (init, &pre);
  	}
  
!       /* This decl isn't mentioned in the enclosing block, so add it to the
! 	 list of temps.  FIXME it seems a bit of a kludge to say that
! 	 anonymous artificial vars aren't pushed, but everything else is.  */
!       if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
! 	gimple_add_tmp_var (decl);
!     }
  
    *stmt_p = pre;
  }
*************** simplify_stmt_expr (expr_p)
*** 860,865 ****
--- 881,889 ----
  	}
  
        last_expr = EXPR_STMT_EXPR (last_expr_stmt);
+       if (stmts_are_full_exprs_p ())
+ 	last_expr = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (last_expr),
+ 			    last_expr);
        EXPR_STMT_EXPR (last_expr_stmt) = empty_stmt_node;
  #if defined ENABLE_CHECKING
        if (!is_last_stmt_of_scope (last_expr_stmt))
*************** simplify_stmt_expr (expr_p)
*** 890,895 ****
--- 914,921 ----
  	  BIND_EXPR_BODY (bind) = substmt;
  	  TREE_TYPE (bind) = TREE_TYPE (body) = TREE_TYPE (last_expr);
  	}
+       else
+ 	body = substmt;
      }
  
    *expr_p = body;
*** ./except.h.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./except.h	2002-11-28 10:04:35.000000000 -0500
*************** extern void expand_eh_region_end_throw		
*** 83,88 ****
--- 83,91 ----
     destroying an object twice.  */
  extern void expand_eh_region_end_fixup		PARAMS ((tree));
  
+ /* End some sort of EH region, depending on the argument.  */
+ extern void expand_eh_handler			PARAMS ((tree));
+ 
  /* Invokes CALLBACK for every exception handler label.  Only used by old
     loop hackery; should not be used by new code.  */
  extern void for_each_eh_label			PARAMS ((void (*) (rtx)));
*** ./expr.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./expr.c	2003-01-02 11:41:25.000000000 -0500
*************** expand_expr (exp, target, tmode, modifie
*** 6986,7010 ****
  	/* If VARS have not yet been expanded, expand them now.  */
  	for (vars = BIND_EXPR_VARS (exp); vars; vars = TREE_CHAIN (vars))
  	  {
! 	    if (DECL_EXTERNAL (vars))
! 	      /* Do nothing.  */;
! 	    else if (TREE_STATIC (vars)
! 		     ? !TREE_ASM_WRITTEN (vars)
! 		     : !DECL_RTL_SET_P (vars))
  	      {
! 		if ((*lang_hooks.expand_decl) (vars))
  		  /* OK.  */;
! 		else if (TREE_CODE (vars) == VAR_DECL && !TREE_STATIC (vars))
! 		  expand_decl (vars);
! 		else if (TREE_CODE (vars) == VAR_DECL && TREE_STATIC (vars))
! 		  rest_of_decl_compilation (vars, NULL, 0, 0);
! 		else if (TREE_CODE (vars) == TYPE_DECL
! 			 || TREE_CODE (vars) == CONST_DECL)
  		  /* No expansion needed.  */;
  		else
  		  abort ();
  	      }
! 	    expand_decl_init (vars);
  	  }
  
  	temp = expand_expr (BIND_EXPR_BODY (exp), target, tmode, modifier);
--- 6986,7018 ----
  	/* If VARS have not yet been expanded, expand them now.  */
  	for (vars = BIND_EXPR_VARS (exp); vars; vars = TREE_CHAIN (vars))
  	  {
! 	    tree var = vars;
! 
! 	    if (DECL_EXTERNAL (var))
! 	      continue;
! 
! 	    if (TREE_STATIC (var))
! 	      /* If this is an inlined copy of a static local variable,
! 		 look up the original decl.  */
! 	      var = DECL_ORIGIN (var);
! 
! 	    if (TREE_STATIC (var)
! 		? !TREE_ASM_WRITTEN (var)
! 		: !DECL_RTL_SET_P (var))
  	      {
! 		if ((*lang_hooks.expand_decl) (var))
  		  /* OK.  */;
! 		else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
! 		  expand_decl (var);
! 		else if (TREE_CODE (var) == VAR_DECL && TREE_STATIC (var))
! 		  rest_of_decl_compilation (var, NULL, 0, 0);
! 		else if (TREE_CODE (var) == TYPE_DECL
! 			 || TREE_CODE (var) == CONST_DECL)
  		  /* No expansion needed.  */;
  		else
  		  abort ();
  	      }
! 	    expand_decl_init (var);
  	  }
  
  	temp = expand_expr (BIND_EXPR_BODY (exp), target, tmode, modifier);
*************** expand_expr (exp, target, tmode, modifie
*** 7017,7022 ****
--- 7025,7031 ----
  	  {
  	    if (TREE_CODE (vars) == FUNCTION_DECL 
  		&& DECL_CONTEXT (vars) == current_function_decl
+ 		&& DECL_SAVED_INSNS (vars)
  		&& !TREE_ASM_WRITTEN (vars)
  		&& TREE_ADDRESSABLE (vars))
  	      {
*************** expand_expr (exp, target, tmode, modifie
*** 9248,9267 ****
  	tree handler = TREE_OPERAND (exp, 1);
  
  	expand_eh_region_start ();
- 
  	op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
! 
! 	expand_eh_region_end_cleanup (handler);
  
  	return op0;
        }
  
      case TRY_FINALLY_EXPR:
        {
  	tree try_block = TREE_OPERAND (exp, 0);
  	tree finally_block = TREE_OPERAND (exp, 1);
  
!         if (!optimize || 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.
--- 9257,9285 ----
  	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 op0;
+ 
+     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.
*** ./fold-const.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./fold-const.c	2002-12-31 16:27:42.000000000 -0500
*************** fold (expr)
*** 7003,7009 ****
  
  	      /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
  	      if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
! 		comp_type = type;
  
  	      switch (comp_code)
  		{
--- 7003,7013 ----
  
  	      /* Avoid adding NOP_EXPRs in case this is an lvalue.  */
  	      if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
! 		{
! 		  comp_type = type;
! 		  comp_op0 = arg1;
! 		  comp_op1 = arg2;
! 		}
  
  	      switch (comp_code)
  		{
*** ./gimplify.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./gimplify.c	2003-01-02 15:16:50.000000000 -0500
*************** Software Foundation, 59 Temple Place - S
*** 36,41 ****
--- 36,42 ----
  #include "langhooks-def.h"
  #include "tree-flow.h"
  #include "timevar.h"
+ #include "except.h"
  
  static void simplify_constructor     PARAMS ((tree, tree *, tree *));
  static void simplify_array_ref       PARAMS ((tree *, tree *, tree *));
*************** static void simplify_compound_lval   PAR
*** 43,54 ****
  static void simplify_component_ref   PARAMS ((tree *, tree *, tree *));
  static void simplify_call_expr       PARAMS ((tree *, tree *, tree *));
  static void simplify_tree_list       PARAMS ((tree *, tree *, tree *));
! static void simplify_modify_expr     PARAMS ((tree *, tree *, tree *));
  static void simplify_compound_expr   PARAMS ((tree *, tree *));
  static void simplify_save_expr       PARAMS ((tree *, tree *));
  static void simplify_addr_expr       PARAMS ((tree *, tree *, tree *));
  static void simplify_self_mod_expr   PARAMS ((tree *, tree *, tree *));
! static void simplify_cond_expr       PARAMS ((tree *, tree *));
  static void simplify_boolean_expr    PARAMS ((tree *, tree *));
  static void simplify_expr_wfl        PARAMS ((tree *, tree *, tree *,
                                                int (*) (tree)));
--- 44,55 ----
  static void simplify_component_ref   PARAMS ((tree *, tree *, tree *));
  static void simplify_call_expr       PARAMS ((tree *, tree *, tree *));
  static void simplify_tree_list       PARAMS ((tree *, tree *, tree *));
! static void simplify_modify_expr     PARAMS ((tree *, tree *, tree *, int));
  static void simplify_compound_expr   PARAMS ((tree *, tree *));
  static void simplify_save_expr       PARAMS ((tree *, tree *));
  static void simplify_addr_expr       PARAMS ((tree *, tree *, tree *));
  static void simplify_self_mod_expr   PARAMS ((tree *, tree *, tree *));
! static void simplify_cond_expr       PARAMS ((tree *, tree *, tree));
  static void simplify_boolean_expr    PARAMS ((tree *, tree *));
  static void simplify_expr_wfl        PARAMS ((tree *, tree *, tree *,
                                                int (*) (tree)));
*************** static void simplify_cleanup_point_expr 
*** 69,75 ****
  static bool gimple_conditional_context	PARAMS ((void));
  static void gimple_push_condition	PARAMS ((void));
  static void gimple_pop_condition	PARAMS ((tree *));
- static tree voidify_wrapper_expr	PARAMS ((tree));
  static void gimple_push_cleanup		PARAMS ((tree, tree *));
  static void gimplify_loop_expr		PARAMS ((tree *));
  static void gimplify_exit_expr		PARAMS ((tree *, tree *));
--- 70,75 ----
*************** simplify_function_tree (fndecl)
*** 165,170 ****
--- 165,171 ----
    tree fnbody;
    int done;
    tree oldfn;
+   tree tmp;
  
    /* Don't bother doing anything if the program has errors.  */
    if (errorcount || sorrycount)
*************** simplify_function_tree (fndecl)
*** 195,200 ****
--- 196,207 ----
    /* Unshare again, in case simplification was sloppy.  */
    unshare_all_trees (fnbody);
  
+   /* If there isn't an outer BIND_EXPR, add one.  */
+   tmp = fnbody;
+   STRIP_WFL (tmp);
+   if (TREE_CODE (tmp) != BIND_EXPR)
+     fnbody = build (BIND_EXPR, void_type_node, NULL_TREE, fnbody, NULL_TREE);
+ 
    DECL_SAVED_TREE (fndecl) = fnbody;
  
    /* Declare the new temporary variables.  */
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 270,289 ****
    if (post_p == NULL)
      post_p = &internal_post;
  
!   /* First strip any uselessness.  */
    STRIP_TYPE_NOPS (*expr_p);
  
    /* Loop over the specific simplifiers until the toplevel node remains the
       same.  */
    do
      {
!       /* First do any language-specific simplification.  */
        (*lang_hooks.simplify_expr) (expr_p, pre_p, post_p);
        if (*expr_p == NULL_TREE)
  	break;
! 
!       /* Then remember the expr.  */
!       save_expr = *expr_p;
  
        switch (TREE_CODE (*expr_p))
  	{
--- 277,298 ----
    if (post_p == NULL)
      post_p = &internal_post;
  
!   /* Strip any uselessness.  */
    STRIP_TYPE_NOPS (*expr_p);
  
    /* Loop over the specific simplifiers until the toplevel node remains the
       same.  */
    do
      {
!       /* Remember the expr.  */
!       save_expr = *expr_p;
! 
!       /* Do any language-specific simplification.  */
        (*lang_hooks.simplify_expr) (expr_p, pre_p, post_p);
        if (*expr_p == NULL_TREE)
  	break;
!       if (*expr_p != save_expr)
! 	continue;
  
        switch (TREE_CODE (*expr_p))
  	{
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 305,311 ****
  	  break;
        
  	case COND_EXPR:
! 	  simplify_cond_expr (expr_p, pre_p);
  	  break;
  
  	case CALL_EXPR:
--- 314,320 ----
  	  break;
        
  	case COND_EXPR:
! 	  simplify_cond_expr (expr_p, pre_p, NULL_TREE);
  	  break;
  
  	case CALL_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 331,337 ****
  
  	case MODIFY_EXPR:
  	case INIT_EXPR:
! 	  simplify_modify_expr (expr_p, pre_p, post_p);
  	  break;
  
  	case TRUTH_ANDIF_EXPR:
--- 340,346 ----
  
  	case MODIFY_EXPR:
  	case INIT_EXPR:
! 	  simplify_modify_expr (expr_p, pre_p, post_p, fallback != fb_none);
  	  break;
  
  	case TRUTH_ANDIF_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 388,393 ****
--- 397,406 ----
  	case COMPLEX_CST:
  	  break;
  
+ 	  /* FIXME make this a decl.  */
+ 	case EXC_PTR_EXPR:
+ 	  break;
+ 
  	case BIND_EXPR:
  	  simplify_bind_expr (expr_p, pre_p);
  	  break;
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 475,480 ****
--- 488,509 ----
  	  simplify_target_expr (expr_p, pre_p, post_p);
  	  break;
  
+ 	case CATCH_EXPR:
+ 	  simplify_stmt (&CATCH_BODY (*expr_p));
+ 	  break;
+ 
+ 	case EH_FILTER_EXPR:
+ 	  simplify_stmt (&EH_FILTER_FAILURE (*expr_p));
+ 	  break;
+ 
+ 	case VTABLE_REF:
+ 	  /* This moves much of the actual computation out of the
+ 	     VTABLE_REF.  Perhaps this should be revisited once we want to
+ 	     do clever things with VTABLE_REFs.  */
+ 	  simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
+ 			 is_simple_min_lval, fb_lvalue);
+ 	  break;
+ 
  	  /* FIXME
  	case MIN_EXPR:
  	case MAX_EXPR:
*************** simplify_expr (expr_p, pre_p, post_p, si
*** 589,595 ****
     and give it void_type_node.  Returns the temporary, or NULL_TREE if
     WRAPPER was already void.  */
  
! static tree
  voidify_wrapper_expr (wrapper)
       tree wrapper;
  {
--- 618,624 ----
     and give it void_type_node.  Returns the temporary, or NULL_TREE if
     WRAPPER was already void.  */
  
! tree
  voidify_wrapper_expr (wrapper)
       tree wrapper;
  {
*************** voidify_wrapper_expr (wrapper)
*** 625,630 ****
--- 654,668 ----
  	  /* The C++ frontend already did this for us.  */;
  	  temp = TREE_OPERAND (*p, 0);
  	}
+       else if (TREE_CODE (*p) == INDIRECT_REF)
+ 	{
+ 	  /* If we're returning a dereference, move the dereference outside
+ 	     the wrapper.  */
+ 	  tree ptr = TREE_OPERAND (*p, 0);
+ 	  temp = create_tmp_var (TREE_TYPE (ptr), "retval");
+ 	  *p = build (MODIFY_EXPR, TREE_TYPE (ptr), temp, ptr);
+ 	  temp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp)), temp);
+ 	}
        else
  	{
  	  temp = create_tmp_var (TREE_TYPE (wrapper), "retval");
*************** simplify_return_expr (stmt, pre_p)
*** 683,708 ****
  
    if (ret_expr)
      {
!       if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
  	{
! 	  /* We are trying to return an expression in a void function.
! 	     Move the expression to before the return.  */
! 	  simplify_stmt (&ret_expr);
  	  add_tree (ret_expr, pre_p);
  	  TREE_OPERAND (stmt, 0) = NULL_TREE;
  	}
        else
  	{
! #if defined ENABLE_CHECKING
! 	  /* A return expression is represented by a MODIFY_EXPR node that
! 	     assigns the return value into a RESULT_DECL.  */
! 	  if (TREE_CODE (ret_expr) != MODIFY_EXPR
! 	      && TREE_CODE (ret_expr) != INIT_EXPR)
! 	    abort ();
! #endif
! 
  	  simplify_expr (&TREE_OPERAND (ret_expr, 1), pre_p, NULL,
  			 is_simple_rhs, fb_rvalue);
  	}
      }
  }
--- 721,745 ----
  
    if (ret_expr)
      {
!       /* We need to pass the full MODIFY_EXPR down so that special handling
! 	 can replace it with something else.  FIXME this code is way too
! 	 complicated.  */
!       simplify_expr (&ret_expr, pre_p, NULL, is_simple_stmt, fb_none);
!       if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))
! 	  || TREE_CODE (ret_expr) != MODIFY_EXPR)
  	{
! 	  /* We are trying to return an expression in a void function, or
! 	     our return expression isn't a simple bitwise copy.  Move the
! 	     expression to before the return.  */
  	  add_tree (ret_expr, pre_p);
  	  TREE_OPERAND (stmt, 0) = NULL_TREE;
  	}
        else
  	{
! 	  /* Make sure the RHS is really simple.  */
  	  simplify_expr (&TREE_OPERAND (ret_expr, 1), pre_p, NULL,
  			 is_simple_rhs, fb_rvalue);
+ 	  TREE_OPERAND (stmt, 0) = ret_expr;
  	}
      }
  }
*************** simplify_tree_list (expr_p, pre_p, post_
*** 1089,1097 ****
          *EXPR_P should be stored.  */
  
  static void
! simplify_cond_expr (expr_p, pre_p)
       tree *expr_p;
       tree *pre_p;
  {
    tree tmp = NULL_TREE;
    tree expr = *expr_p;
--- 1126,1135 ----
          *EXPR_P should be stored.  */
  
  static void
! simplify_cond_expr (expr_p, pre_p, target)
       tree *expr_p;
       tree *pre_p;
+      tree target;
  {
    tree tmp = NULL_TREE;
    tree expr = *expr_p;
*************** simplify_cond_expr (expr_p, pre_p)
*** 1100,1114 ****
       the arms.  */
    if (! VOID_TYPE_P (TREE_TYPE (expr)))
        {
! 	tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
! 
! 	/* Build the then clause, 't1 = a;'.  */
! 	TREE_OPERAND (expr, 1)
! 	  = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 1));
  
  	/* Build the else clause, 't1 = b;'.  */
! 	TREE_OPERAND (expr, 2)
! 	  = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 2));
  
  	TREE_TYPE (expr) = void_type_node;
  	recalculate_side_effects (expr);
--- 1138,1158 ----
       the arms.  */
    if (! VOID_TYPE_P (TREE_TYPE (expr)))
        {
! 	if (target)
! 	  tmp = target;
! 	else
! 	  tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
! 
! 	/* Build the then clause, 't1 = a;'.  But don't build an assignment
! 	   if this branch is void; in C++ it can be, if it's a throw.  */
! 	if (TREE_TYPE (TREE_OPERAND (expr, 1)) != void_type_node)
! 	  TREE_OPERAND (expr, 1)
! 	    = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 1));
  
  	/* Build the else clause, 't1 = b;'.  */
! 	if (TREE_TYPE (TREE_OPERAND (expr, 2)) != void_type_node)
! 	  TREE_OPERAND (expr, 2)
! 	    = build (MODIFY_EXPR, void_type_node, tmp, TREE_OPERAND (expr, 2));
  
  	TREE_TYPE (expr) = void_type_node;
  	recalculate_side_effects (expr);
*************** simplify_cond_expr (expr_p, pre_p)
*** 1157,1168 ****
          *EXPR_P should be stored.  */
  
  static void
! simplify_modify_expr (expr_p, pre_p, post_p)
       tree *expr_p;
       tree *pre_p;
       tree *post_p;
  {
!   tree *from;
    
  #if defined ENABLE_CHECKING
    if (TREE_CODE (*expr_p) != MODIFY_EXPR
--- 1201,1215 ----
          *EXPR_P should be stored.  */
  
  static void
! simplify_modify_expr (expr_p, pre_p, post_p, want_value)
       tree *expr_p;
       tree *pre_p;
       tree *post_p;
+      int want_value;
  {
!   tree *from_p = &TREE_OPERAND (*expr_p, 1);
!   tree *to_p = &TREE_OPERAND (*expr_p, 0);
!   tree type = TREE_TYPE (*expr_p);
    
  #if defined ENABLE_CHECKING
    if (TREE_CODE (*expr_p) != MODIFY_EXPR
*************** simplify_modify_expr (expr_p, pre_p, pos
*** 1170,1197 ****
      abort ();
  #endif
  
    /* If we are initializing something from a TARGET_EXPR, strip the
       TARGET_EXPR and initialize it directly.  */
    /* What about code that pulls out the temp and uses it elsewhere?  I
       think that such code never uses the TARGET_EXPR as an initializer.  If
       I'm wrong, we'll abort because the temp won't have any RTL.  In that
       case, I guess we'll need to replace references somehow.  */
!   from = &TREE_OPERAND (*expr_p, 1);
!   if (TREE_CODE (*from) == TARGET_EXPR)
!     *from = TARGET_EXPR_INITIAL (*from);
  
    /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer
       useful.  */
    if (TREE_CODE (*expr_p) == INIT_EXPR)
      TREE_SET_CODE (*expr_p, MODIFY_EXPR);
  
!   simplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
! 		 is_simple_modify_expr_lhs, fb_lvalue);
!   simplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, is_simple_rhs,
!                  fb_rvalue);
  
!   add_tree (*expr_p, pre_p);
!   *expr_p = TREE_OPERAND (*expr_p, 0);
  }
  
  
--- 1217,1289 ----
      abort ();
  #endif
  
+   simplify_expr (to_p, pre_p, post_p, is_simple_modify_expr_lhs, fb_lvalue);
+ 
    /* If we are initializing something from a TARGET_EXPR, strip the
       TARGET_EXPR and initialize it directly.  */
    /* What about code that pulls out the temp and uses it elsewhere?  I
       think that such code never uses the TARGET_EXPR as an initializer.  If
       I'm wrong, we'll abort because the temp won't have any RTL.  In that
       case, I guess we'll need to replace references somehow.  */
!   if (TREE_CODE (*from_p) == TARGET_EXPR)
!     *from_p = TARGET_EXPR_INITIAL (*from_p);
! 
!   /* If we're assigning from a ?: expression with ADDRESSABLE type, push
!      the assignment down into the branches, since we can't generate a
!      temporary of such a type.  */
!   if (TREE_CODE (*from_p) == COND_EXPR
!       && TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
!     {
!       simplify_cond_expr (from_p, pre_p, *to_p);
!       *expr_p = *from_p;
!       /* Try again.  */
!       return;
!     }
  
    /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer
       useful.  */
    if (TREE_CODE (*expr_p) == INIT_EXPR)
      TREE_SET_CODE (*expr_p, MODIFY_EXPR);
  
!   /* Break out elements of a constructor into separate MODIFY_EXPRs.  FIXME
!      should also handle arrays/vectors.
  
!      Note that we still need to clear any elements that don't have explicit
!      initializers, so we keep the original MODIFY_EXPR, we just remove all
!      of the constructor elements.  FIXME should try to avoid clearing
!      initialized elts, a la store_constructor.  */
!   if (TREE_CODE (*from_p) == CONSTRUCTOR && !TREE_STATIC (*from_p)
!       && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
! 	  || TREE_CODE (type) == QUAL_UNION_TYPE))
!     {
!       tree elt_list = CONSTRUCTOR_ELTS (*from_p);
!       CONSTRUCTOR_ELTS (*from_p) = NULL_TREE;
!       add_tree (*expr_p, pre_p);
!       for (; elt_list; elt_list = TREE_CHAIN (elt_list))
! 	{
! 	  tree purpose = TREE_PURPOSE (elt_list);
! 	  tree value = TREE_VALUE (elt_list);
! 	  tree cref = build (COMPONENT_REF, TREE_TYPE (purpose),
! 			     *to_p, purpose);
! 	  tree init = build (MODIFY_EXPR, TREE_TYPE (purpose), cref, value);
! 	  simplify_expr (&init, pre_p, NULL, is_simple_stmt, fb_none);
! 	  add_tree (init, pre_p);
! 	}
!       *expr_p = TREE_OPERAND (*expr_p, 0);
!       return;
!     }
! 
!   /* If this is for a RETURN_EXPR, we can't have any posteffects.  */
!   if (!want_value)
!     post_p = NULL;
! 
!   simplify_expr (from_p, pre_p, post_p, is_simple_rhs, fb_rvalue);
! 
!   if (want_value)
!     {
!       add_tree (*expr_p, pre_p);
!       *expr_p = TREE_OPERAND (*expr_p, 0);
!     }
  }
  
  
*************** foreach_stmt (stmt_p, fn)
*** 1465,1471 ****
        tree *sub_p = &TREE_OPERAND (*stmt_p, 0);
        if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
  	foreach_stmt (sub_p, fn);
!       fn (sub_p);
      }
    fn (stmt_p);
  }
--- 1557,1564 ----
        tree *sub_p = &TREE_OPERAND (*stmt_p, 0);
        if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
  	foreach_stmt (sub_p, fn);
!       else
! 	fn (sub_p);
      }
    fn (stmt_p);
  }
*************** create_tmp_var (type, prefix)
*** 1567,1574 ****
    ASM_FORMAT_PRIVATE_NAME (tmp_name, (prefix ? prefix : "T"), id_num++);
  
  #if defined ENABLE_CHECKING
!   /* If the type is an array, something is wrong.  */
!   if (TREE_CODE (type) == ARRAY_TYPE)
      abort ();
  #endif
  
--- 1660,1668 ----
    ASM_FORMAT_PRIVATE_NAME (tmp_name, (prefix ? prefix : "T"), id_num++);
  
  #if defined ENABLE_CHECKING
!   /* If the type is an array or a type which must be created by the
!      frontend, something is wrong.  */
!   if (TREE_CODE (type) == ARRAY_TYPE || TREE_ADDRESSABLE (type))
      abort ();
  #endif
  
*************** mostly_copy_tree_r (tp, walk_subtrees, d
*** 1840,1850 ****
       void *data;
  {
    enum tree_code code = TREE_CODE (*tp);
!   /* Don't unshare decls, blocks, types and SAVE_EXPR nodes.  */
    if (TREE_CODE_CLASS (code) == 't'
-       || TREE_CODE_CLASS (code) == 'd'
-       || TREE_CODE_CLASS (code) == 'c'
-       || TREE_CODE_CLASS (code) == 'b'
        || code == SAVE_EXPR
        || *tp == empty_stmt_node)
      *walk_subtrees = 0;
--- 1934,1941 ----
       void *data;
  {
    enum tree_code code = TREE_CODE (*tp);
!   /* Don't unshare types and SAVE_EXPR nodes.  */
    if (TREE_CODE_CLASS (code) == 't'
        || code == SAVE_EXPR
        || *tp == empty_stmt_node)
      *walk_subtrees = 0;
*************** mostly_copy_tree_r (tp, walk_subtrees, d
*** 1861,1866 ****
--- 1952,1969 ----
    return NULL_TREE;
  }
  
+ /* Unconditionally make an unshared copy of EXPR.  This is used when using
+    stored expressions which span multiple functions, such as BINFO_VTABLE,
+    as the normal unsharing process can't tell that they're shared.  */
+ 
+ tree
+ unshare_expr (expr)
+      tree expr;
+ {
+   walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
+   return expr;
+ }
+ 
  void
  mark_not_simple (expr_p)
       tree *expr_p;
*************** mark_not_simple (expr_p)
*** 1868,1873 ****
--- 1971,1988 ----
    TREE_NOT_GIMPLE (*expr_p) = 1;
  }
  
+ /* A terser interface for building a representation of a exception
+    specification.  */
+ 
+ tree
+ gimple_build_eh_filter (body, allowed, failure)
+      tree body, allowed, failure;
+ {
+   /* FIXME should the allowed types go in TREE_TYPE?  */
+   tree filter = build (EH_FILTER_EXPR, void_type_node, allowed, failure);
+   return build (TRY_CATCH_EXPR, void_type_node, body, filter);
+ }
+ 
  /* Simplify a CLEANUP_POINT_EXPR.  Currently this works by adding
     WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
     simplifying the body, and converting them to TRY_FINALLY_EXPRs when we
*************** simplify_cleanup_point_expr (expr_p, pre
*** 1913,1919 ****
  	  if (TREE_CODE (*container) == COMPOUND_EXPR)
  	    next = TREE_OPERAND (*container, 1);
  	  else
! 	    next = NULL_TREE;
  
  	  tfe = build (TRY_FINALLY_EXPR, void_type_node,
  		       next, TREE_OPERAND (wce, 1));
--- 2028,2034 ----
  	  if (TREE_CODE (*container) == COMPOUND_EXPR)
  	    next = TREE_OPERAND (*container, 1);
  	  else
! 	    next = empty_stmt_node;
  
  	  tfe = build (TRY_FINALLY_EXPR, void_type_node,
  		       next, TREE_OPERAND (wce, 1));
*************** simplify_cleanup_point_expr (expr_p, pre
*** 1933,1938 ****
--- 2048,2081 ----
      *expr_p = body;
  }
  
+ /* If the language requires some sort of exception protection of cleanup
+    actions (i.e. calling terminate in C++), modify the cleanup to reflect
+    that.  */
+ 
+ tree
+ maybe_protect_cleanup (cleanup)
+      tree cleanup;
+ {
+ #if 0
+   /* Ack!  We only want to protect the cleanup if it's run in the EH path.
+      There's currently no reasonable way to express this in GENERIC.  FIXME
+      FIXME FIXME!  Don't mess with this for now; it will still get handled
+      properly in the expander.  */
+   tree protect_cleanup_actions
+     = (lang_protect_cleanup_actions
+        ? (*lang_protect_cleanup_actions) ()
+        : NULL_TREE);
+ 
+   if (protect_cleanup_actions)
+     /* Wrap cleanups in MUST_NOT_THROW equivalent if appropriate.  FIXME
+        perhaps this should be done earlier in the frontend so we don't need
+        a hook.  */
+     cleanup = gimple_build_eh_filter (cleanup, NULL_TREE,
+ 				      protect_cleanup_actions);
+ #endif
+   return cleanup;
+ }
+ 
  /* Insert a cleanup marker for simplify_cleanup_point_expr.  CLEANUP
     is the cleanup action required.  */
  
*************** gimple_push_cleanup (cleanup, pre_p)
*** 1943,1948 ****
--- 2086,2093 ----
  {
    tree wce;
  
+   cleanup = maybe_protect_cleanup (cleanup);
+ 
    if (gimple_conditional_context ())
      {
        /* If we're in a conditional context, this is more complex.  We only
*************** simplify_target_expr (expr_p, pre_p, pos
*** 2000,2015 ****
       temps list.  */
    gimple_add_tmp_var (temp);
  
!   /* Add the initialization to pre_p.  In some cases, such as C++
!      constructors, the initialization will happen by side-effect in init;
!      in such cases, init will simplify to temp, so we mustn't build a
!      MODIFY_EXPR.  */
!   simplify_expr (&init, pre_p, post_p, is_simple_rhs, fb_rvalue);
!   if (init != temp)
!     {
!       init = build (MODIFY_EXPR, void_type_node, temp, init);
!       add_tree (init, pre_p);
!     }
  
    /* If needed, push the cleanup for the temp.  */
    if (TARGET_EXPR_CLEANUP (targ))
--- 2145,2154 ----
       temps list.  */
    gimple_add_tmp_var (temp);
  
!   /* Build up the initialization and add it to pre_p.  */
!   init = build (MODIFY_EXPR, void_type_node, temp, init);
!   simplify_expr (&init, pre_p, post_p, is_simple_stmt, fb_none);
!   add_tree (init, pre_p);
  
    /* If needed, push the cleanup for the temp.  */
    if (TARGET_EXPR_CLEANUP (targ))
*** ./integrate.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./integrate.c	2003-01-02 11:41:36.000000000 -0500
*************** copy_decl_for_inlining (decl, from_fn, t
*** 394,400 ****
    DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
  
    /* The new variable/label has no RTL, yet.  */
!   SET_DECL_RTL (copy, NULL_RTX);
  
    /* These args would always appear unused, if not for this.  */
    TREE_USED (copy) = 1;
--- 394,401 ----
    DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl);
  
    /* The new variable/label has no RTL, yet.  */
!   if (!TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
!     SET_DECL_RTL (copy, NULL_RTX);
  
    /* These args would always appear unused, if not for this.  */
    TREE_USED (copy) = 1;
*************** copy_decl_for_inlining (decl, from_fn, t
*** 405,414 ****
      ;
    else if (DECL_CONTEXT (decl) != from_fn)
      /* Things that weren't in the scope of the function we're inlining
!        from aren't in the scope we're inlining too, either.  */
      ;
    else if (TREE_STATIC (decl))
!     /* Function-scoped static variables should say in the original
         function.  */
      ;
    else
--- 406,415 ----
      ;
    else if (DECL_CONTEXT (decl) != from_fn)
      /* Things that weren't in the scope of the function we're inlining
!        from aren't in the scope we're inlining to, either.  */
      ;
    else if (TREE_STATIC (decl))
!     /* Function-scoped static variables should stay in the original
         function.  */
      ;
    else
*** ./tree-dump.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree-dump.c	2002-12-16 12:09:42.000000000 -0500
*************** dump_switch_p (arg)
*** 850,852 ****
--- 850,878 ----
  
    return 0;
  }
+ 
+ /* Dump FUNCTION_DECL FN as tree dump PHASE.  */
+ 
+ void
+ dump_function (enum tree_dump_index phase, tree fn)
+ {
+   FILE *stream;
+   int flags;
+ 
+   stream = dump_begin (phase, &flags);
+   if (stream)
+     {
+       fprintf (stream, "\n;; Function %s",
+ 	       (*lang_hooks.decl_printable_name) (fn, 2));
+       fprintf (stream, " (%s)\n",
+ 	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn)));
+       fprintf (stream, ";; enabled by -%s\n", dump_flag_name (phase));
+       fprintf (stream, "\n");
+       
+       if (flags & TDF_RAW)
+ 	dump_node (fn, TDF_SLIM | flags, stream);
+       else
+ 	print_generic_stmt (stream, DECL_SAVED_TREE (fn), 0);
+       dump_end (phase, stream);
+     }
+ }
*** ./tree-dump.h.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree-dump.h	2002-12-16 12:10:40.000000000 -0500
*************** extern void queue_and_dump_index
*** 91,95 ****
--- 91,97 ----
    PARAMS ((dump_info_p, const char *, tree, int));
  extern void queue_and_dump_type
    PARAMS ((dump_info_p, tree));
+ extern void dump_function
+   PARAMS ((enum tree_dump_index, tree));
  
  #endif /* ! GCC_TREE_DUMP_H */
*** ./tree-inline.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree-inline.c	2003-01-02 11:41:53.000000000 -0500
*************** static void remap_block PARAMS ((tree *,
*** 112,117 ****
--- 112,119 ----
  static void copy_bind_expr PARAMS ((tree *, int *, inline_data *));
  static tree find_alloca_call_1 PARAMS ((tree *, int *, void *));
  static tree find_alloca_call PARAMS ((tree));
+ static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *));
+ static tree unsave_r PARAMS ((tree *, int *, void *));
  
  /* The approximate number of instructions per statement.  This number
     need not be particularly accurate; it is used only to make
*************** remap_decl (decl, id)
*** 130,137 ****
--- 132,144 ----
  
    /* We only remap local variables in the current function.  */
    fn = VARRAY_TOP_TREE (id->fns);
+ #if 0
+   /* We need to remap statics, too, so that they get expanded even if the
+      inline function is never emitted out of line.  We might as well also
+      remap extern decls so that they show up in the debug info.  */
    if (! (*lang_hooks.tree_inlining.auto_var_in_fn_p) (decl, fn))
      return NULL_TREE;
+ #endif
  
    /* See if we have remapped this declaration.  */
    n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl);
*************** initialize_inlined_parameters (id, args,
*** 603,609 ****
  
  static tree
  declare_return_variable (id, return_slot_addr, use_p)
!      struct inline_data *id;
       tree return_slot_addr;
       tree *use_p;
  {
--- 610,616 ----
  
  static tree
  declare_return_variable (id, return_slot_addr, use_p)
!      inline_data *id;
       tree return_slot_addr;
       tree *use_p;
  {
*************** declare_return_variable (id, return_slot
*** 635,640 ****
--- 642,652 ----
       promoted, convert it back to the expected type.  */
    if (TREE_TYPE (var) == TREE_TYPE (TREE_TYPE (fn)))
      *use_p = var;
+   else if (TREE_CODE (var) == INDIRECT_REF)
+     *use_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (fn)),
+ 		     TREE_OPERAND (var, 0));
+   else if (TREE_ADDRESSABLE (TREE_TYPE (var)))
+     abort ();
    else
      *use_p = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), var);
  
*************** expand_call_inline (tp, walk_subtrees, d
*** 908,913 ****
--- 920,926 ----
      {
        return_slot_addr = TREE_VALUE (args);
        args = TREE_CHAIN (args);
+       TREE_TYPE (expr) = void_type_node;
      }
  
    arg_inits = initialize_inlined_parameters (id, args, fn, expr);
*************** walk_tree (tp, func, data, htab_)
*** 1240,1342 ****
      {
        WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
      }
!   else if (TREE_CODE_CLASS (code) == 't')
      {
!       WALK_SUBTREE (TYPE_SIZE (*tp));
!       WALK_SUBTREE (TYPE_SIZE_UNIT (*tp));
!       /* Also examine various special fields, below.  */
!     }
! 
!   /* Not one of the easy cases.  We must explicitly go through the
!      children.  */
!   else switch (code)
!     {
!     case ERROR_MARK:
!     case IDENTIFIER_NODE:
!     case INTEGER_CST:
!     case REAL_CST:
!     case VECTOR_CST:
!     case STRING_CST:
!     case REAL_TYPE:
!     case COMPLEX_TYPE:
!     case VECTOR_TYPE:
!     case VOID_TYPE:
!     case BOOLEAN_TYPE:
!     case UNION_TYPE:
!     case ENUMERAL_TYPE:
!     case BLOCK:
!     case RECORD_TYPE:
!       /* None of thse have subtrees other than those already walked
!          above.  */
!       break;
  
!     case POINTER_TYPE:
!     case REFERENCE_TYPE:
!       WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
!       break;
  
!     case TREE_LIST:
!       WALK_SUBTREE (TREE_VALUE (*tp));
!       WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
!       break;
! 
!     case TREE_VEC:
!       {
! 	int len = TREE_VEC_LENGTH (*tp);
  
! 	if (len == 0)
  	  break;
  
! 	/* Walk all elements but the first.  */
! 	while (--len)
! 	  WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
! 
! 	/* Now walk the first one as a tail call.  */
! 	WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
!       }
! 
!     case COMPLEX_CST:
!       WALK_SUBTREE (TREE_REALPART (*tp));
!       WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
! 
!     case CONSTRUCTOR:
!       WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
! 
!     case METHOD_TYPE:
!       WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
!       /* Fall through.  */
! 
!     case FUNCTION_TYPE:
!       WALK_SUBTREE (TREE_TYPE (*tp));
!       {
! 	tree arg = TYPE_ARG_TYPES (*tp);
! 
! 	/* We never want to walk into default arguments.  */
! 	for (; arg; arg = TREE_CHAIN (arg))
! 	  WALK_SUBTREE (TREE_VALUE (arg));
!       }
!       break;
! 
!     case ARRAY_TYPE:
!       WALK_SUBTREE (TREE_TYPE (*tp));
!       WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp));
! 
!     case INTEGER_TYPE:
!       WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
!       WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp));
! 
!     case OFFSET_TYPE:
!       WALK_SUBTREE (TREE_TYPE (*tp));
!       WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
  
!     case EXIT_BLOCK_EXPR:
!       WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
  
!     case SAVE_EXPR:
!       WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
  
!     default:
!       abort ();
      }
  
    /* We didn't find what we were looking for.  */
--- 1253,1358 ----
      {
        WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
      }
!   else
      {
!       if (TREE_CODE_CLASS (code) == 't')
! 	{
! 	  WALK_SUBTREE (TYPE_SIZE (*tp));
! 	  WALK_SUBTREE (TYPE_SIZE_UNIT (*tp));
! 	  /* Also examine various special fields, below.  */
! 	}
  
!       /* Not one of the easy cases.  We must explicitly go through the
! 	 children.  */
!       switch (code)
! 	{
! 	case ERROR_MARK:
! 	case IDENTIFIER_NODE:
! 	case INTEGER_CST:
! 	case REAL_CST:
! 	case VECTOR_CST:
! 	case STRING_CST:
! 	case REAL_TYPE:
! 	case COMPLEX_TYPE:
! 	case VECTOR_TYPE:
! 	case VOID_TYPE:
! 	case BOOLEAN_TYPE:
! 	case UNION_TYPE:
! 	case ENUMERAL_TYPE:
! 	case BLOCK:
! 	case RECORD_TYPE:
! 	  /* None of thse have subtrees other than those already walked
! 	     above.  */
! 	  break;
  
! 	case POINTER_TYPE:
! 	case REFERENCE_TYPE:
! 	  WALK_SUBTREE_TAIL (TREE_TYPE (*tp));
! 	  break;
  
! 	case TREE_LIST:
! 	  WALK_SUBTREE (TREE_VALUE (*tp));
! 	  WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
  	  break;
  
! 	case TREE_VEC:
! 	  {
! 	    int len = TREE_VEC_LENGTH (*tp);
! 
! 	    if (len == 0)
! 	      break;
! 
! 	    /* Walk all elements but the first.  */
! 	    while (--len)
! 	      WALK_SUBTREE (TREE_VEC_ELT (*tp, len));
! 
! 	    /* Now walk the first one as a tail call.  */
! 	    WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0));
! 	  }
! 
! 	case COMPLEX_CST:
! 	  WALK_SUBTREE (TREE_REALPART (*tp));
! 	  WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp));
! 
! 	case CONSTRUCTOR:
! 	  WALK_SUBTREE_TAIL (CONSTRUCTOR_ELTS (*tp));
! 
! 	case METHOD_TYPE:
! 	  WALK_SUBTREE (TYPE_METHOD_BASETYPE (*tp));
! 	  /* Fall through.  */
! 
! 	case FUNCTION_TYPE:
! 	  WALK_SUBTREE (TREE_TYPE (*tp));
! 	  {
! 	    tree arg = TYPE_ARG_TYPES (*tp);
! 
! 	    /* We never want to walk into default arguments.  */
! 	    for (; arg; arg = TREE_CHAIN (arg))
! 	      WALK_SUBTREE (TREE_VALUE (arg));
! 	  }
! 	  break;
  
! 	case ARRAY_TYPE:
! 	  WALK_SUBTREE (TREE_TYPE (*tp));
! 	  WALK_SUBTREE_TAIL (TYPE_DOMAIN (*tp));
! 
! 	case INTEGER_TYPE:
! 	  WALK_SUBTREE (TYPE_MIN_VALUE (*tp));
! 	  WALK_SUBTREE_TAIL (TYPE_MAX_VALUE (*tp));
! 
! 	case OFFSET_TYPE:
! 	  WALK_SUBTREE (TREE_TYPE (*tp));
! 	  WALK_SUBTREE_TAIL (TYPE_OFFSET_BASETYPE (*tp));
  
! 	case EXIT_BLOCK_EXPR:
! 	  WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 1));
  
! 	case SAVE_EXPR:
! 	  WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0));
! 
! 	default:
! 	  abort ();
! 	}
      }
  
    /* We didn't find what we were looking for.  */
*************** copy_tree_r (tp, walk_subtrees, data)
*** 1404,1409 ****
--- 1420,1427 ----
    else if (TREE_CODE_CLASS (code) == 't' && !variably_modified_type_p (*tp))
      /* Types only need to be copied if they are variably modified.  */
      *walk_subtrees = 0;
+   else if (TREE_CODE_CLASS (code) == 'd')
+     *walk_subtrees = 0;
  
    return NULL_TREE;
  }
*************** add_stmt_to_compound (existing, type, st
*** 1467,1469 ****
--- 1485,1605 ----
    else
      return stmt;
  }
+ 
+ /* Called via walk_tree.  If *TP points to a DECL_STMT for a local
+    declaration, copies the declaration and enters it in the splay_tree
+    in DATA (which is really an `inline_data *').  */
+ 
+ static tree
+ mark_local_for_remap_r (tp, walk_subtrees, data)
+      tree *tp;
+      int *walk_subtrees ATTRIBUTE_UNUSED;
+      void *data;
+ {
+   tree t = *tp;
+   inline_data *id = (inline_data *) data;
+   splay_tree st = id->decl_map;
+   tree decl;
+ 
+   /* Don't walk into types.  */
+   if (TYPE_P (t))
+     {
+       *walk_subtrees = 0;
+       return NULL_TREE;
+     }
+ 
+   if (TREE_CODE (t) == LABEL_EXPR)
+     decl = TREE_OPERAND (t, 0);
+   else
+     /* We don't need to handle anything else ahead of time.  */
+     decl = NULL_TREE;
+ 
+   if (decl)
+     {
+       tree copy;
+ 
+       /* Make a copy.  */
+       copy = copy_decl_for_inlining (decl, 
+ 				     DECL_CONTEXT (decl), 
+ 				     DECL_CONTEXT (decl));
+ 
+       /* Remember the copy.  */
+       splay_tree_insert (st,
+ 			 (splay_tree_key) decl, 
+ 			 (splay_tree_value) copy);
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ /* Called via walk_tree when an expression is unsaved.  Using the
+    splay_tree pointed to by ST (which is really a `splay_tree'),
+    remaps all local declarations to appropriate replacements.  */
+ 
+ static tree
+ unsave_r (tp, walk_subtrees, data)
+      tree *tp;
+      int *walk_subtrees;
+      void *data;
+ {
+   inline_data *id = (inline_data *) data;
+   splay_tree st = id->decl_map;
+   splay_tree_node n;
+ 
+   /* Only a local declaration (variable or label).  */
+   if ((TREE_CODE (*tp) == VAR_DECL && !TREE_STATIC (*tp))
+       || TREE_CODE (*tp) == LABEL_DECL)
+     {
+       /* Lookup the declaration.  */
+       n = splay_tree_lookup (st, (splay_tree_key) *tp);
+       
+       /* If it's there, remap it.  */
+       if (n)
+ 	*tp = (tree) n->value;
+     }
+   else if (TREE_CODE (*tp) == BIND_EXPR)
+     copy_bind_expr (tp, walk_subtrees, id);
+   else if (TREE_CODE (*tp) == SAVE_EXPR)
+     remap_save_expr (tp, st, current_function_decl, walk_subtrees);
+   else
+     {
+       copy_tree_r (tp, walk_subtrees, NULL);
+ 
+       /* Do whatever unsaving is required.  */
+       unsave_expr_1 (*tp);
+     }
+ 
+   /* Keep iterating.  */
+   return NULL_TREE;
+ }
+ 
+ /* Default lang hook for "unsave_expr_now".  Copies everything in EXPR and replaces
+    variables, labels and SAVE_EXPRs local to EXPR.  */
+ 
+ tree
+ lhd_unsave_expr_now (expr)
+      tree expr;
+ {
+   inline_data id;
+ 
+   /* There's nothing to do for NULL_TREE.  */
+   if (expr == 0)
+     return expr;
+ 
+   /* Set up ID.  */
+   memset (&id, 0, sizeof (id));
+   VARRAY_TREE_INIT (id.fns, 1, "fns");
+   VARRAY_PUSH_TREE (id.fns, current_function_decl);
+   id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
+ 
+   /* Walk the tree once to find local labels.  */
+   walk_tree_without_duplicates (&expr, mark_local_for_remap_r, &id);
+ 
+   /* Walk the tree again, copying, remapping, and unsaving.  */
+   walk_tree (&expr, unsave_r, &id, NULL);
+ 
+   /* Clean up.  */
+   splay_tree_delete (id.decl_map);
+ 
+   return expr;
+ }
*** ./tree.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree.c	2003-01-02 11:41:55.000000000 -0500
*************** unsave_expr_1 (expr)
*** 1531,1588 ****
      }
  }
  
- /* Default lang hook for "unsave_expr_now".  */
- 
- tree
- lhd_unsave_expr_now (expr)
-      tree expr;
- {
-   enum tree_code code;
- 
-   /* There's nothing to do for NULL_TREE.  */
-   if (expr == 0)
-     return expr;
- 
-   unsave_expr_1 (expr);
- 
-   code = TREE_CODE (expr);
-   switch (TREE_CODE_CLASS (code))
-     {
-     case 'c':  /* a constant */
-     case 't':  /* a type node */
-     case 'd':  /* A decl node */
-     case 'b':  /* A block node */
-       break;
- 
-     case 'x':  /* miscellaneous: e.g., identifier, TREE_LIST or ERROR_MARK.  */
-       if (code == TREE_LIST)
- 	{
- 	  lhd_unsave_expr_now (TREE_VALUE (expr));
- 	  lhd_unsave_expr_now (TREE_CHAIN (expr));
- 	}
-       break;
- 
-     case 'e':  /* an expression */
-     case 'r':  /* a reference */
-     case 's':  /* an expression with side effects */
-     case '<':  /* a comparison expression */
-     case '2':  /* a binary arithmetic expression */
-     case '1':  /* a unary arithmetic expression */
-       {
- 	int i;
- 
- 	for (i = first_rtl_op (code) - 1; i >= 0; i--)
- 	  lhd_unsave_expr_now (TREE_OPERAND (expr, i));
-       }
-       break;
- 
-     default:
-       abort ();
-     }
- 
-   return expr;
- }
- 
  /* Return 0 if it is safe to evaluate EXPR multiple times,
     return 1 if it is safe if EXPR is unsaved afterward, or
     return 2 if it is completely unsafe.
--- 1531,1536 ----
*************** unsafe_for_reeval (expr)
*** 1619,1629 ****
      {
      case SAVE_EXPR:
      case RTL_EXPR:
  
        /* A label can only be emitted once.  */
      case LABEL_EXPR:
      case BIND_EXPR:
!       return 2;
  
      case TREE_LIST:
        for (exp = expr; exp != 0; exp = TREE_CHAIN (exp))
--- 1567,1581 ----
      {
      case SAVE_EXPR:
      case RTL_EXPR:
+       return 2;
  
        /* A label can only be emitted once.  */
      case LABEL_EXPR:
+       return 1;
+ 
      case BIND_EXPR:
!       unsafeness = 1;
!       break;
  
      case TREE_LIST:
        for (exp = expr; exp != 0; exp = TREE_CHAIN (exp))
*** ./tree-simple.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree-simple.c	2003-01-02 11:41:54.000000000 -0500
*************** is_simple_unary_expr (t)
*** 444,450 ****
    /* Additions to the original grammar.  Allow NON_LVALUE_EXPR and
       EXPR_WITH_FILE_LOCATION wrappers.  */
    if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
!       || TREE_CODE (t) == NON_LVALUE_EXPR)
      return is_simple_unary_expr (TREE_OPERAND (t, 0));
  
    if (is_simple_varname (t) || is_simple_const (t))
--- 444,451 ----
    /* Additions to the original grammar.  Allow NON_LVALUE_EXPR and
       EXPR_WITH_FILE_LOCATION wrappers.  */
    if (TREE_CODE (t) == EXPR_WITH_FILE_LOCATION
!       || TREE_CODE (t) == NON_LVALUE_EXPR
!       || TREE_CODE (t) == VTABLE_REF)
      return is_simple_unary_expr (TREE_OPERAND (t, 0));
  
    if (is_simple_varname (t) || is_simple_const (t))
*************** is_simple_id (t)
*** 682,689 ****
--- 683,693 ----
    return (TREE_CODE (t) == VAR_DECL
  	  || TREE_CODE (t) == FUNCTION_DECL
  	  || TREE_CODE (t) == PARM_DECL
+ 	  || TREE_CODE (t) == RESULT_DECL
  	  || TREE_CODE (t) == FIELD_DECL
  	  || TREE_CODE (t) == LABEL_DECL
+ 	  /* FIXME make this a decl.  */
+ 	  || TREE_CODE (t) == EXC_PTR_EXPR
  	  /* Allow the address of a function decl.  */
  	  || (TREE_CODE (t) == ADDR_EXPR
  	      && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
*************** right_assocify_expr (top)
*** 897,903 ****
  		TREE_SIDE_EFFECTS (lhs) = 1;
  	    }
  
! 	  /* Walk through the rhs chain from there until we find something
  	     with a different code.  In this case, c.  */
  	  for (q = &TREE_OPERAND (lhs, 1); TREE_CODE (*q) == code;
  	       q = &TREE_OPERAND (*q, 1))
--- 901,907 ----
  		TREE_SIDE_EFFECTS (lhs) = 1;
  	    }
  
! 	  /* Walk through the op1 chain from there until we find something
  	     with a different code.  In this case, c.  */
  	  for (q = &TREE_OPERAND (lhs, 1); TREE_CODE (*q) == code;
  	       q = &TREE_OPERAND (*q, 1))
*** ./tree-pretty-print.c.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree-pretty-print.c	2003-01-02 15:50:43.000000000 -0500
*************** Software Foundation, 59 Temple Place - S
*** 29,34 ****
--- 29,35 ----
  #include "real.h"
  #include "hashtab.h"
  #include "tree-flow.h"
+ #include "langhooks.h"
  
  /* Local functions, macros and variables.  */
  static int op_prio				PARAMS ((tree));
*************** static void print_struct_decl			PARAMS (
*** 45,68 ****
        							 int));
  static void dump_block_info			PARAMS ((output_buffer *,
  						         basic_block, int));
  
  #define INDENT(SPACE) do { \
    int i; for (i = 0; i<SPACE; i++) output_add_space (buffer); } while (0)
  
! #define NIY do { \
!   output_add_string (buffer, "<<< Unknown tree >>>\n"); } while (0)
  
  #define PRINT_FUNCTION_NAME(NODE)  output_printf             \
    (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ?              \
!    IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (NODE, 0))) : \
!    IDENTIFIER_POINTER (DECL_NAME (NODE)))
  
  static output_buffer buffer;
  static int initialized = 0;
  static int last_bb;
  static bool dumping_stmts;
  
  
  /* Print tree T, and its successors, on file FILE.  FLAGS specifies details
     to show in the dump.  See TDF_* in tree.h.  */
  
--- 46,91 ----
        							 int));
  static void dump_block_info			PARAMS ((output_buffer *,
  						         basic_block, int));
+ static void do_niy				PARAMS ((output_buffer *,
+ 							 tree));
  
  #define INDENT(SPACE) do { \
    int i; for (i = 0; i<SPACE; i++) output_add_space (buffer); } while (0)
  
! #define NIY do_niy(buffer,node)
  
  #define PRINT_FUNCTION_NAME(NODE)  output_printf             \
    (buffer, "%s", TREE_CODE (NODE) == NOP_EXPR ?              \
!    (*lang_hooks.decl_printable_name) (TREE_OPERAND (NODE, 0), 1) : \
!    (*lang_hooks.decl_printable_name) (NODE, 1))
  
  static output_buffer buffer;
  static int initialized = 0;
  static int last_bb;
  static bool dumping_stmts;
  
+ /* Try to print something for an unknown tree code.  */
  
+ static void
+ do_niy (buffer, node)
+      output_buffer *buffer;
+      tree node;
+ {
+   int i, len;
+ 
+   output_add_string (buffer, "<<< Unknown tree: ");
+   output_add_string (buffer, tree_code_name[(int) TREE_CODE (node)]);
+ 
+   len = first_rtl_op (TREE_CODE (node));
+   for (i = 0; i < len; ++i)
+     {
+       newline_and_indent (buffer, 2);
+       dump_generic_node (buffer, TREE_OPERAND (node, i), 2, 0);
+     }
+ 
+   output_add_string (buffer, " >>>\n");
+ }
+      
  /* Print tree T, and its successors, on file FILE.  FLAGS specifies details
     to show in the dump.  See TDF_* in tree.h.  */
  
*************** dump_generic_node (buffer, node, spc, fl
*** 288,296 ****
  	  {
  	    output_add_character (buffer, '[');
  	    if (TYPE_SIZE (tmp))
! 	      output_decimal (buffer,
! 			      TREE_INT_CST_LOW (TYPE_SIZE (tmp)) / 
! 			      TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tmp))));
  	    output_add_character (buffer, ']');
  	    tmp = TREE_TYPE (tmp);
  	  }
--- 311,326 ----
  	  {
  	    output_add_character (buffer, '[');
  	    if (TYPE_SIZE (tmp))
! 	      {
! 		tree size = TYPE_SIZE (tmp);
! 		if (TREE_CODE (size) == INTEGER_CST)
! 		  output_decimal (buffer,
! 				  TREE_INT_CST_LOW (TYPE_SIZE (tmp)) / 
! 				  TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tmp))));
! 		else if (TREE_CODE (size) == MULT_EXPR)
! 		  dump_generic_node (buffer, TREE_OPERAND (size, 0), spc, flags);
! 		/* else punt.  */
! 	      }
  	    output_add_character (buffer, ']');
  	    tmp = TREE_TYPE (tmp);
  	  }
*************** dump_generic_node (buffer, node, spc, fl
*** 704,710 ****
        output_add_character (buffer, '(');
        op1 = TREE_OPERAND (node, 1);
        if (op1)
! 	dump_generic_node (buffer, op1, 0, flags);
        output_add_character (buffer, ')');
        break;
  
--- 734,740 ----
        output_add_character (buffer, '(');
        op1 = TREE_OPERAND (node, 1);
        if (op1)
! 	dump_generic_node (buffer, op1, spc, flags);
        output_add_character (buffer, ')');
        break;
  
*************** dump_generic_node (buffer, node, spc, fl
*** 717,723 ****
        break;
  
      case CLEANUP_POINT_EXPR:
!       NIY;
        break;
  
      case PLACEHOLDER_EXPR:
--- 747,755 ----
        break;
  
      case CLEANUP_POINT_EXPR:
!       output_add_string (buffer, "<<cleanup_point ");
!       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags);
!       output_add_string (buffer, ">>");
        break;
  
      case PLACEHOLDER_EXPR:
*************** dump_generic_node (buffer, node, spc, fl
*** 992,997 ****
--- 1024,1047 ----
        output_add_string (buffer, "}");
        break;
  
+     case CATCH_EXPR:
+       output_add_string (buffer, "catch (");
+       dump_generic_node (buffer, CATCH_TYPES (node), spc+2, flags);
+       output_add_string (buffer, ")");
+       newline_and_indent (buffer, spc+2);
+       output_add_string (buffer, "{");
+       newline_and_indent (buffer, spc+4);
+       dump_generic_node (buffer, CATCH_BODY (node), spc+4, flags);
+       newline_and_indent (buffer, spc+2);
+       output_add_string (buffer, "}");
+       break;
+ 
+     case EH_FILTER_EXPR:
+       output_add_string (buffer, "<<<eh_filter (");
+       dump_generic_node (buffer, EH_FILTER_TYPES (node), spc+2, flags);
+       output_add_string (buffer, ")>>>");
+       break;
+ 
      case GOTO_SUBROUTINE_EXPR:
        NIY;
        break;
*************** dump_generic_node (buffer, node, spc, fl
*** 1057,1063 ****
        break;
  
      case EXC_PTR_EXPR:
!       NIY;
        break;
  
      case LOOP_EXPR:
--- 1107,1113 ----
        break;
  
      case EXC_PTR_EXPR:
!       output_add_string (buffer, "<<<exception object>>>");
        break;
  
      case LOOP_EXPR:
*************** dump_generic_node (buffer, node, spc, fl
*** 1175,1180 ****
--- 1225,1240 ----
        output_add_character (buffer, ':');
        break;
  
+     case VTABLE_REF:
+       output_add_string (buffer, "VTABLE_REF <(");
+       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags);
+       output_add_string (buffer, "),");
+       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags);
+       output_add_character (buffer, ',');
+       dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags);
+       output_add_character (buffer, '>');
+       break;
+ 
      default:
        NIY;
      }
*************** op_prio (op)
*** 1434,1439 ****
--- 1494,1500 ----
      case FIX_CEIL_EXPR:
      case FIX_FLOOR_EXPR:
      case FIX_ROUND_EXPR:
+     case TARGET_EXPR:
        return 14;
  
      case CALL_EXPR:
*** ./tree-simple.h.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree-simple.h	2002-12-15 14:39:17.000000000 -0500
*************** void gimple_push_bind_expr	        PARAM
*** 96,101 ****
--- 96,104 ----
  void gimple_pop_bind_expr	        PARAMS ((void));
  void mark_not_simple			PARAMS ((tree *));
  void unshare_all_trees			PARAMS ((tree));
+ tree voidify_wrapper_expr		PARAMS ((tree));
+ tree gimple_build_eh_filter		PARAMS ((tree, tree, tree));
+ tree maybe_protect_cleanup		PARAMS ((tree));
  
  
  /* Iterator object for GIMPLE statements.  */
*************** gsi_stmt (i)
*** 165,170 ****
--- 168,175 ----
       gimple_stmt_iterator i;
  {
    tree t = *(gsi_stmt_ptr (i));
+   STRIP_WFL (t);
+   STRIP_NOPS (t);
    if (t == empty_stmt_node || t == error_mark_node)
      t = NULL_TREE;
    return t;
*** ./tree.def.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree.def	2003-01-02 15:30:19.000000000 -0500
*************** DEFTREECODE (CASE_LABEL_EXPR, "case_labe
*** 863,868 ****
--- 863,878 ----
     for the statement.  */
  DEFTREECODE (ASM_EXPR, "asm_expr", 's', 4)
  
+ /* Used to represent a typed exception handler.  CATCH_TYPES is the type (or
+    list of types) handled, and CATCH_BODY is the code for the handler.  */
+ DEFTREECODE (CATCH_EXPR, "catch_expr", 's', 2)
+ 
+ /* Used to represent an exception specification.  EH_FILTER_TYPES is a list
+    of allowed types, and EH_FILTER_FAILURE is an expression to evaluate on
+    failure.  EH_FILTER_MUST_NOT_THROW controls which range type to use when
+    expanding.  */
+ DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", 's', 2)
+ 
  /*
  Local variables:
  mode:c
*** ./tree.h.~1~	2003-01-02 12:14:45.000000000 -0500
--- ./tree.h	2003-01-02 11:41:55.000000000 -0500
*************** struct tree_common GTY(())
*** 188,193 ****
--- 188,194 ----
  	   TREE_LIST elements of a block's cleanup list.
         ASM_INPUT_P in
             ASM_EXPR
+        EH_FILTER_MUST_NOT_THROW in EH_FILTER_EXPR
  
     public_flag:
  
*************** struct tree_vec GTY(())
*** 872,878 ****
  #define SAVE_EXPR_NOPLACEHOLDER(NODE) TREE_UNSIGNED (SAVE_EXPR_CHECK (NODE))
  /* Nonzero if the SAVE_EXPRs value should be kept, even if it occurs
     both in normal code and in a handler.  (Normally, in a handler, all
!    SAVE_EXPRs are unsaved, meaning that there values are
     recalculated.)  */
  #define SAVE_EXPR_PERSISTENT_P(NODE) TREE_ASM_WRITTEN (SAVE_EXPR_CHECK (NODE))
  
--- 873,879 ----
  #define SAVE_EXPR_NOPLACEHOLDER(NODE) TREE_UNSIGNED (SAVE_EXPR_CHECK (NODE))
  /* Nonzero if the SAVE_EXPRs value should be kept, even if it occurs
     both in normal code and in a handler.  (Normally, in a handler, all
!    SAVE_EXPRs are unsaved, meaning that their values are
     recalculated.)  */
  #define SAVE_EXPR_PERSISTENT_P(NODE) TREE_ASM_WRITTEN (SAVE_EXPR_CHECK (NODE))
  
*************** struct tree_vec GTY(())
*** 971,976 ****
--- 972,986 ----
     the given label expression.  */
  #define LABEL_EXPR_LABEL(NODE)  TREE_OPERAND (LABEL_EXPR_CHECK (NODE), 0)
  
+ /* CATCH_EXPR accessors.  */
+ #define CATCH_TYPES(NODE)	TREE_OPERAND (CATCH_EXPR_CHECK (NODE), 0)
+ #define CATCH_BODY(NODE)	TREE_OPERAND (CATCH_EXPR_CHECK (NODE), 1)
+ 
+ /* EH_FILTER_EXPR accessors.  */
+ #define EH_FILTER_TYPES(NODE)	TREE_OPERAND (EH_FILTER_EXPR_CHECK (NODE), 0)
+ #define EH_FILTER_FAILURE(NODE)	TREE_OPERAND (EH_FILTER_EXPR_CHECK (NODE), 1)
+ #define EH_FILTER_MUST_NOT_THROW(NODE) TREE_STATIC (EH_FILTER_EXPR_CHECK (NODE))
+ 
  struct tree_exp GTY(())
  {
    struct tree_common common;
*************** const char *dump_flag_name		PARAMS ((enu
*** 3285,3290 ****
--- 3295,3301 ----
  
  extern int simplify_function_tree	PARAMS ((tree));
  extern const char *get_name		PARAMS ((tree));
+ extern tree unshare_expr		PARAMS ((tree));
  
  /* Redefine abort to report an internal error w/o coredump, and
     reporting the location of the error in the source file.  This logic

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