C++ PATCH for explicit cleanup representation

Mark Mitchell mark@codesourcery.com
Sat Sep 11 18:15:00 GMT 1999


This patch moves the declaration of __FUNCTION__, etc., to the
semantic analysis pass (where they belong) rather than to the RTL
generation pass.  (In function-at-a-time mode, of course.)  And, we
also now explicitly represent cleanups for local variables in the
statement-tree.  (Eventually, all tree generation will be done in the
fisrt pass; the second pass will just go through calling expand_* to
build RTL.)

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

1999-09-11  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.def (CLEANUP_STMT): New node.
	* cp-tree.h (language_function): Add name_declared.
	(current_function_name_declared): New macro.
	(CLEANUP_DECL): New macro.
	(CLEANUP_EXPR): Likewise.
	(emit_local_var): Likewise.
	(finish_decl_cleanup): New function.
	* cvt.c (build_up_reference): Simplify.
	(ocp_convert): Remove dead code.
	* decl.c (start_decl): Remove call to add_decl_stmt.
	(grok_reference_init): Adjust, to handle bindings temporaries to
	references.  Remove dead code.
	(initialize_local_var): Don't generate RTL for
	declarations here, or build cleanups here.  Don't fuss with
	obstacks.  Replace expand_start_target_temps calls with explicit
	setting of stms_are_full_exprs_p.
	(destroy_local_var): New function.
	(emit_local_var): Likewise.
	(cp_finish_decl): Use them, as appropriate.
	(start_function): Announce template functions.
	(store_parm_decls): Don't call declare_function_name here.
	(finish_stmt): Don't start emit base-initialization code when just
	building the statement-tree.
	* init.c (create_temporary_var): Move add_decl_stmt call ...
	(get_temp_regvar): Here.
	* pt.c (tsubst_expr): Make DECL_INITIAL look like what
	cp_finish_decl would expect.  Don't call add_decl_stmt.
	* semantics.c (begin_compound_stmt): Call declare_function_name,
	if appropriate.
	(finish_decl_cleanup): New function.
	(expand_stmt): Use emit_local_var to output variables.		
	(expand_body): Set current_funtion_name_declared.
	
Index: cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.35
diff -c -p -r1.35 cp-tree.def
*** cp-tree.def	1999/09/07 16:07:19	1.35
--- cp-tree.def	1999/09/12 01:11:39
*************** DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 
*** 235,240 ****
--- 235,244 ----
     run if an exception is thrown before the end of the enclosing
     function.  */
  DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
+ /* A CLEANUP_STMT marks the point at which a declaration is fully
+    constructed.  If, after this point, the CLEANUP_DECL goes out of
+    scope, the CLEANUP_EXPR must be run.  */
+ DEFTREECODE (CLEANUP_STMT, "cleanup", 'e', 2)
  DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
  DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
  DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.302
diff -c -p -r1.302 cp-tree.h
*** cp-tree.h	1999/09/10 10:35:53	1.302
--- cp-tree.h	1999/09/12 01:11:42
*************** struct language_function
*** 636,641 ****
--- 636,642 ----
    int in_function_try_handler;
    int x_expanding_p;
    int stmts_are_full_exprs_p; 
+   int name_declared;
  
    struct named_label_list *x_named_label_uses;
    struct binding_level *bindings;
*************** struct language_function
*** 708,713 ****
--- 709,720 ----
  #define current_function_parms_stored \
    cp_function_chain->parms_stored
  
+ /* Non-zero if we have already declared __FUNCTION__ (and related
+    variables) in the current function.  */
+ 
+ #define current_function_name_declared \
+   cp_function_chain->name_declared
+ 
  /* Used to help generate temporary names which are unique within
     a function.  Reset to 0 by start_function.  */
  
*************** extern int flag_new_for_scope;
*** 2437,2442 ****
--- 2444,2451 ----
  #define DECL_STMT_DECL(NODE)    TREE_OPERAND (NODE, 0)
  #define STMT_EXPR_STMT(NODE)    TREE_OPERAND (NODE, 0)
  #define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (NODE, 0)
+ #define CLEANUP_DECL(NODE)      TREE_OPERAND (NODE, 0)
+ #define CLEANUP_EXPR(NODE)      TREE_OPERAND (NODE, 1)
  #define LABEL_STMT_LABEL(NODE)  TREE_OPERAND (NODE, 0)
  
  /* Nonzero for an ASM_STMT if the assembly statement is volatile.  */
*************** extern int wrapup_globals_for_namespace 
*** 3237,3242 ****
--- 3246,3252 ----
  extern tree cp_namespace_decls                  PROTO((tree));
  extern tree create_implicit_typedef             PROTO((tree, tree));
  extern tree maybe_push_decl                     PROTO((tree));
+ extern void emit_local_var                      PROTO((tree));
  
  /* in decl2.c */
  extern void init_decl2				PROTO((void));
*************** extern void finish_member_declaration   
*** 3651,3656 ****
--- 3661,3667 ----
  extern void check_multiple_declarators          PROTO((void));
  extern tree finish_typeof			PROTO((tree));
  extern void add_decl_stmt                       PROTO((tree));
+ extern void finish_decl_cleanup                 PROTO((tree, tree));
  extern void finish_named_return_value           PROTO((tree, tree));
  extern tree expand_stmt                         PROTO((tree));
  extern void expand_body                         PROTO((tree));
Index: cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.65
diff -c -p -r1.65 cvt.c
*** cvt.c	1999/09/09 12:07:43	1.65
--- cvt.c	1999/09/12 01:11:42
*************** build_up_reference (type, arg, flags)
*** 345,352 ****
  
    if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
      {
-       tree compound_stmt;
- 
        /* Create a new temporary variable.  */
        tree targ = arg;
        if (toplevel_bindings_p ())
--- 345,350 ----
*************** build_up_reference (type, arg, flags)
*** 355,379 ****
  	{
  	  arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
  	  DECL_ARTIFICIAL (arg) = 1;
- 	  /* Generate code to initialize it.  We wrap it in a
- 	     statement-expression so that when we are building a
- 	     statement-tree we will have a representation of this
- 	     declaration.  */
- 	  begin_init_stmts (&stmt_expr, &compound_stmt);
  	}
  
        /* Process the initializer for the declaration.  */
        DECL_INITIAL (arg) = targ;
        cp_finish_decl (arg, targ, NULL_TREE, 0,
  		      LOOKUP_ONLYCONVERTING|DIRECT_BIND);
- 
-       /* And wrap up the statement-expression, if necessary.  */
-       if (!toplevel_bindings_p ())
- 	{
- 	  if (building_stmt_tree ())
- 	    add_decl_stmt (arg);
- 	  stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
- 	}
      }
    else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
      {
--- 353,364 ----
*************** ocp_convert (type, expr, convtype, flags
*** 719,744 ****
        return e;
      }
  
- #if 0
-   /* This is incorrect.  A truncation can't be stripped this way.
-      Extensions will be stripped by the use of get_unwidened.  */
-   if (TREE_CODE (e) == NOP_EXPR)
-     return cp_convert (type, TREE_OPERAND (e, 0));
- #endif
- 
    /* Just convert to the type of the member.  */
    if (code == OFFSET_TYPE)
      {
        type = TREE_TYPE (type);
        code = TREE_CODE (type);
      }
- 
- #if 0
-   if (code == REFERENCE_TYPE)
-     return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));
-   else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
-     e = convert_from_reference (e);
- #endif
  
    if (TREE_CODE (e) == OFFSET_REF)
      e = resolve_offset_ref (e);
--- 704,715 ----
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.444
diff -c -p -r1.444 decl.c
*** decl.c	1999/09/10 10:35:53	1.444
--- decl.c	1999/09/12 01:11:51
*************** static void mark_cp_function_context PRO
*** 179,184 ****
--- 179,185 ----
  static void mark_saved_scope PROTO((void *));
  static void check_function_type PROTO((tree));
  static void destroy_local_static PROTO((tree));
+ static void destroy_local_var PROTO((tree));
  
  #if defined (DEBUG_CP_BINDING_LEVELS)
  static void indent PROTO((void));
*************** start_decl (declarator, declspecs, initi
*** 6843,6857 ****
      {
        if (at_function_scope_p ())
  	push_permanent_obstack ();
- 
        tem = push_template_decl (tem);
-       /* In a a local scope, add a representation of this declaration
- 	 to the statement tree.  */
        if (at_function_scope_p ())
! 	{
! 	  add_decl_stmt (decl);
! 	  pop_obstacks ();
! 	}
      }
  
  
--- 6844,6852 ----
      {
        if (at_function_scope_p ())
  	push_permanent_obstack ();
        tem = push_template_decl (tem);
        if (at_function_scope_p ())
! 	pop_obstacks ();
      }
  
  
*************** grok_reference_init (decl, type, init)
*** 6987,6993 ****
        /* Note: default conversion is only called in very special cases.  */
        init = default_conversion (init);
      }
! 
    tmp = convert_to_reference
      (type, init, CONV_IMPLICIT,
       LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
--- 6982,6995 ----
        /* Note: default conversion is only called in very special cases.  */
        init = default_conversion (init);
      }
!   
!   /* Convert INIT to the reference type TYPE.  This may involve the
!      creation of a temporary, whose lifetime must be the same as that
!      of the reference.  If so, a DECL_STMT for the temporary will be
!      added just after the DECL_STMT for DECL.  That's why we don't set
!      DECL_INITIAL for local references (instead assigning to them
!      explicitly); we need to allow the temporary to be initialized
!      first.  */
    tmp = convert_to_reference
      (type, init, CONV_IMPLICIT,
       LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
*************** grok_reference_init (decl, type, init)
*** 6997,7003 ****
    else if (tmp != NULL_TREE)
      {
        init = tmp;
!       DECL_INITIAL (decl) = save_expr (init);
      }
    else
      {
--- 6999,7016 ----
    else if (tmp != NULL_TREE)
      {
        init = tmp;
!       tmp = save_expr (tmp);
!       if (building_stmt_tree ())
! 	{
! 	  /* Initialize the declaration.  */
! 	  tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
! 	  /* Setting TREE_SIDE_EFFECTS prevents expand_expr from
! 	     omitting this expression entirely.  */
! 	  TREE_SIDE_EFFECTS (tmp) = 1;
! 	  finish_expr_stmt (tmp);
! 	}
!       else
! 	DECL_INITIAL (decl) = tmp;
      }
    else
      {
*************** grok_reference_init (decl, type, init)
*** 7005,7015 ****
        return;
      }
  
-   /* ?? Can this be optimized in some cases to
-      hand back the DECL_INITIAL slot??  */
-   if (TYPE_SIZE (TREE_TYPE (type)))
-     init = convert_from_reference (decl);
- 
    if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl)))
      {
        expand_static_init (decl, DECL_INITIAL (decl));
--- 7018,7023 ----
*************** initialize_local_var (decl, init, flags)
*** 7526,7537 ****
       int flags;
  {
    tree type;
-   tree cleanup;
  
    type = complete_type (TREE_TYPE (decl));
  
-   cleanup = build_cleanup_on_safe_obstack (decl);
- 
    if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
      {
        /* If we used it already as memory, it must stay in memory.  */
--- 7534,7542 ----
*************** initialize_local_var (decl, init, flags)
*** 7539,7554 ****
        TREE_ADDRESSABLE (decl) = TREE_USED (decl);
      }
  
-   if (DECL_RTL (decl))
-     /* Only a RESULT_DECL should have non-NULL RTL when arriving here.
-        All other local variables are assigned RTL in this function.  */
-     my_friendly_assert (TREE_CODE (decl) == RESULT_DECL, 19990828);
-   else
-     /* Create RTL for this variable.  */
-     expand_decl (decl);
- 
-   expand_start_target_temps ();
- 
    if (DECL_SIZE (decl) && type != error_mark_node)
      {
        int already_used;
--- 7544,7549 ----
*************** initialize_local_var (decl, init, flags)
*** 7558,7578 ****
  
        if (init || TYPE_NEEDS_CONSTRUCTING (type))
  	{
  	  emit_line_note (DECL_SOURCE_FILE (decl),
  			  DECL_SOURCE_LINE (decl));
! 	  /* We call push_momentary here so that when
! 	     finish_expr_stmt clears the momentary obstack it
! 	     doesn't destory any momentary expressions we may
! 	     have lying around.  Although cp_finish_decl is
! 	     usually called at the end of a declaration
! 	     statement, it may also be called for a temporary
! 	     object in the middle of an expression.  */
! 	  push_momentary ();
  	  finish_expr_stmt (build_aggr_init (decl, init, flags));
! 	  pop_momentary ();
  	}
-       else
- 	expand_decl_init (decl);
  
        /* Set this to 0 so we can tell whether an aggregate which was
  	 initialized was ever used.  Don't do this if it has a
--- 7553,7567 ----
  
        if (init || TYPE_NEEDS_CONSTRUCTING (type))
  	{
+ 	  int saved_stmts_are_full_exprs_p;
+ 
  	  emit_line_note (DECL_SOURCE_FILE (decl),
  			  DECL_SOURCE_LINE (decl));
! 	  saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
! 	  stmts_are_full_exprs_p = 1;
  	  finish_expr_stmt (build_aggr_init (decl, init, flags));
! 	  stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
  	}
  
        /* Set this to 0 so we can tell whether an aggregate which was
  	 initialized was ever used.  Don't do this if it has a
*************** initialize_local_var (decl, init, flags)
*** 7582,7605 ****
  	 marked used. (see TREE_USED, above.)  */
        if (TYPE_NEEDS_CONSTRUCTING (type)
  	  && ! already_used
! 	  && cleanup == NULL_TREE
  	  && DECL_NAME (decl))
  	TREE_USED (decl) = 0;
        else if (already_used)
  	TREE_USED (decl) = 1;
      }
  
!   /* Cleanup any temporaries needed for the initial value.  */
!   expand_end_target_temps ();
  
    /* Record the cleanup required for this declaration.  */
!   if (DECL_SIZE (decl) 
!       && type != error_mark_node
!       && cleanup
!       && !expand_decl_cleanup (decl, cleanup))
!     cp_error ("parser lost in parsing declaration of `%D'", decl);
  }
  
  /* Finish processing of a declaration;
     install its line number and initial value.
     If the length of an array type is not known before,
--- 7571,7620 ----
  	 marked used. (see TREE_USED, above.)  */
        if (TYPE_NEEDS_CONSTRUCTING (type)
  	  && ! already_used
! 	  && !TYPE_NEEDS_DESTRUCTOR (type) 
  	  && DECL_NAME (decl))
  	TREE_USED (decl) = 0;
        else if (already_used)
  	TREE_USED (decl) = 1;
      }
+ }
  
! /* Generate code to destroy DECL (a local variable).  */
! 
! void 
! destroy_local_var (decl)
!      tree decl;
! {
!   tree cleanup = build_cleanup_on_safe_obstack (decl);
  
    /* Record the cleanup required for this declaration.  */
!   if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
!       && cleanup)
!     finish_decl_cleanup (decl, cleanup);
  }
  
+ /* Let the back-end know about DECL.  */
+ 
+ void
+ emit_local_var (decl)
+      tree decl;
+ {
+   /* Create RTL for this variable.  */
+   if (DECL_RTL (decl))
+     /* Only a RESULT_DECL should have non-NULL RTL when
+ 		     arriving here.  All other local variables are
+ 		     assigned RTL in this function.  */
+     my_friendly_assert (TREE_CODE (decl) == RESULT_DECL, 
+ 			19990828);
+   else
+     expand_decl (decl);
+ 
+   /* Actually do the initialization.  */
+   expand_start_target_temps ();
+   expand_decl_init (decl);
+   expand_end_target_temps ();
+ }
+ 
  /* Finish processing of a declaration;
     install its line number and initial value.
     If the length of an array type is not known before,
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7680,7688 ****
        return;
      }
  
    if (TYPE_HAS_MUTABLE_P (type))
      TREE_READONLY (decl) = 0;
!   
    if (processing_template_decl)
      {
        if (init && DECL_INITIAL (decl))
--- 7695,7708 ----
        return;
      }
  
+   /* Add this declaration to the statement-tree.  */
+   if (building_stmt_tree () 
+       && TREE_CODE (current_scope ()) == FUNCTION_DECL)
+     add_decl_stmt (decl);
+ 
    if (TYPE_HAS_MUTABLE_P (type))
      TREE_READONLY (decl) = 0;
! 
    if (processing_template_decl)
      {
        if (init && DECL_INITIAL (decl))
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7808,7817 ****
  	  /* Initialize the local variable.  But, if we're building a
  	     statement-tree, we'll do the initialization when we
  	     expand the tree.  */
! 	  if (!building_stmt_tree ())
! 	    initialize_local_var (decl, init, flags);
! 	  else if (init || DECL_INITIAL (decl) == error_mark_node)
! 	    DECL_INITIAL (decl) = init;
  	}
      finish_end0:
  
--- 7828,7846 ----
  	  /* Initialize the local variable.  But, if we're building a
  	     statement-tree, we'll do the initialization when we
  	     expand the tree.  */
! 	  if (processing_template_decl)
! 	    {
! 	      if (init || DECL_INITIAL (decl) == error_mark_node)
! 		DECL_INITIAL (decl) = init;
! 	    }
! 	  else
! 	    {
! 	      if (!building_stmt_tree ())
! 		emit_local_var (decl);
! 	      initialize_local_var (decl, init, flags);
! 	      /* Clean up the variable.  */
! 	      destroy_local_var (decl);
! 	    }
  	}
      finish_end0:
  
*************** start_function (declspecs, declarator, a
*** 12900,12906 ****
    get_pending_sizes ();
  
    /* Let the user know we're compiling this function.  */
!   if (!building_stmt_tree ())
      announce_function (decl1);
  
    /* Record the decl so that the function name is defined.
--- 12929,12935 ----
    get_pending_sizes ();
  
    /* Let the user know we're compiling this function.  */
!   if (processing_template_decl || !building_stmt_tree ())
      announce_function (decl1);
  
    /* Record the decl so that the function name is defined.
*************** store_parm_decls ()
*** 13210,13218 ****
  
    storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
  
-   /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function.  */
-   declare_function_name ();
- 
    /* Initialize the RTL code for the function.  */
    DECL_SAVED_INSNS (fndecl) = 0;
    if (! building_stmt_tree ())
--- 13239,13244 ----
*************** finish_stmt ()
*** 14222,14228 ****
    if (!current_function_assigns_this
        && current_function_just_assigned_this)
      {
!       if (DECL_CONSTRUCTOR_P (current_function_decl))
  	{
  	  /* Constructors must wait until we are out of control
  	     zones before calling base constructors.  */
--- 14248,14255 ----
    if (!current_function_assigns_this
        && current_function_just_assigned_this)
      {
!       if (DECL_CONSTRUCTOR_P (current_function_decl) 
! 	  && !building_stmt_tree ())
  	{
  	  /* Constructors must wait until we are out of control
  	     zones before calling base constructors.  */
Index: init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.133
diff -c -p -r1.133 init.c
*** init.c	1999/09/10 10:19:46	1.133
--- init.c	1999/09/12 01:11:53
*************** create_temporary_var (type)
*** 2668,2676 ****
    DECL_SOURCE_LINE (decl) = lineno;
    DECL_IGNORED_P (decl) = 1;
  
-   if (building_stmt_tree ())
-     add_decl_stmt (decl);
- 
    return decl;
  }
  
--- 2668,2673 ----
*************** get_temp_regvar (type, init)
*** 2688,2693 ****
--- 2685,2692 ----
    tree decl;
  
    decl = create_temporary_var (type);
+   if (building_stmt_tree ())
+     add_decl_stmt (decl);
    DECL_REGISTER (decl) = 1;
    if (!building_stmt_tree ())
      DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.356
diff -c -p -r1.356 pt.c
*** pt.c	1999/09/10 09:21:36	1.356
--- pt.c	1999/09/12 01:11:59
*************** tsubst_expr (t, args, complain, in_decl)
*** 7284,7290 ****
  	    init = DECL_INITIAL (decl);
  	    decl = tsubst (decl, args, complain, in_decl);
  	    init = tsubst_expr (init, args, complain, in_decl);
! 	    DECL_INITIAL (decl) = init;
  	    /* By marking the declaration as instantiated, we avoid
  	       trying to instantiate it.  Since instantiate_decl can't
  	       handle local variables, and since we've already done
--- 7284,7291 ----
  	    init = DECL_INITIAL (decl);
  	    decl = tsubst (decl, args, complain, in_decl);
  	    init = tsubst_expr (init, args, complain, in_decl);
! 	    if (init)
! 	      DECL_INITIAL (decl) = error_mark_node;
  	    /* By marking the declaration as instantiated, we avoid
  	       trying to instantiate it.  Since instantiate_decl can't
  	       handle local variables, and since we've already done
*************** tsubst_expr (t, args, complain, in_decl)
*** 7293,7300 ****
  	    if (TREE_CODE (decl) == VAR_DECL)
  	      DECL_TEMPLATE_INSTANTIATED (decl) = 1;
  	    maybe_push_decl (decl);
! 	    cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
! 	    add_decl_stmt (decl);
  	  }
  	resume_momentary (i);
  	return decl;
--- 7294,7300 ----
  	    if (TREE_CODE (decl) == VAR_DECL)
  	      DECL_TEMPLATE_INSTANTIATED (decl) = 1;
  	    maybe_push_decl (decl);
! 	    cp_finish_decl (decl, init, NULL_TREE, 0, 0);
  	  }
  	resume_momentary (i);
  	return decl;
Index: semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.80
diff -c -p -r1.80 semantics.c
*** semantics.c	1999/09/10 10:19:47	1.80
--- semantics.c	1999/09/12 01:12:00
*************** begin_compound_stmt (has_no_scope)
*** 869,874 ****
--- 869,882 ----
         to accidentally keep a block *inside* the scopeless block.  */ 
      keep_next_level (0);
  
+   /* If this is the outermost block of the function, declare the
+      variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
+   if (!current_function_name_declared && !processing_template_decl)
+     {
+       declare_function_name ();
+       current_function_name_declared = 1;
+     }
+ 
    return r;
  }
  
*************** finish_subobject (cleanup)
*** 1027,1032 ****
--- 1035,1053 ----
      add_partial_entry (cleanup);
  }
  
+ /* When DECL goes out of scope, make sure that CLEANUP is executed.  */
+ 
+ void 
+ finish_decl_cleanup (decl, cleanup)
+      tree decl;
+      tree cleanup;
+ {
+   if (building_stmt_tree ())
+     add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
+   else if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node)
+     expand_decl_cleanup (decl, cleanup);
+ }
+ 
  /* Bind a name and initialization to the return value of
     the current function.  */
  
*************** expand_stmt (t)
*** 2153,2165 ****
  		       compatibility.  */
  		    maybe_inject_for_scope_var (decl);
  		    /* Let the back-end know about this variable.  */
! 		    initialize_local_var (decl, DECL_INITIAL (decl), 0);
  		  }
  	      }
  	    resume_momentary (i);
  	  }
  	  break;
  
  	case FOR_STMT:
  	  {
  	    tree tmp;
--- 2174,2190 ----
  		       compatibility.  */
  		    maybe_inject_for_scope_var (decl);
  		    /* Let the back-end know about this variable.  */
! 		    emit_local_var (decl);
  		  }
  	      }
  	    resume_momentary (i);
  	  }
  	  break;
  
+ 	case CLEANUP_STMT:
+ 	  finish_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
+ 	  break;
+ 
  	case FOR_STMT:
  	  {
  	    tree tmp;
*************** expand_body (fn)
*** 2337,2342 ****
--- 2362,2372 ----
  
    start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
    store_parm_decls ();
+ 
+   /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
+      any of the other magic variables we set up when starting a
+      function body.  */
+   current_function_name_declared = 1;
  
    /* There are a few things that we do not handle recursively.  For
       example, a function try-block is handled differently from an


More information about the Gcc-patches mailing list