C++ PATCH: Using __cxa_atexit for globals

Mark Mitchell mark@codesourcery.com
Sun Jan 23 10:41:00 GMT 2000


This patch makes __cxa_atexit be used for global objects as well as
local objects when -fuse-cxa-atexit is used.  This is required by the
new ABI, and ensures that destructors for objects with static storage
duration are run in the opposite order from that in which they are
constructed.

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

2000-01-23  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (register_dtor_fn): New function.
	* decl.c (destroy_local_static): Rename to ...
	(register_dtor_fn): ... this.  Give it external linkage.
	(expand_static_init): Use it.
	* decl2.c (do_static_initialization): Likewise, if using
	__cxa_atexit.
	(do_static_destruction): Check that __cxa_atexit is not in use.
	(finish_file): Don't call do_static_destruction if using
	__cxa_atexit.

Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.388
diff -c -p -r1.388 cp-tree.h
*** cp-tree.h	2000/01/18 10:23:31	1.388
--- cp-tree.h	2000/01/23 18:36:46
*************** extern void make_rtl_for_local_static   
*** 3680,3685 ****
--- 3680,3686 ----
  extern int local_variable_p                     PROTO((tree));
  extern int nonstatic_local_decl_p               PROTO((tree));
  extern tree declare_global_var                  PROTO((tree, tree));
+ extern void register_dtor_fn                    PROTO((tree));
  
  /* in decl2.c */
  extern void init_decl2				PROTO((void));
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.534
diff -c -p -r1.534 decl.c
*** decl.c	2000/01/17 20:18:39	1.534
--- decl.c	2000/01/23 18:36:56
*************** static void mark_lang_function PROTO((st
*** 173,179 ****
  static void mark_stmt_tree PROTO((struct stmt_tree *));
  static void save_function_data PROTO((tree));
  static void check_function_type PROTO((tree));
- static void destroy_local_static PROTO((tree));
  static void destroy_local_var PROTO((tree));
  static void finish_constructor_body PROTO((void));
  static void finish_destructor_body PROTO((void));
--- 173,178 ----
*************** end_cleanup_fn ()
*** 8054,8064 ****
    pop_from_top_level ();
  }
  
! /* Generate code to handle the destruction of the function-scoped
!    static variable DECL.  */
  
! static void
! destroy_local_static (decl)
       tree decl;
  {
    tree cleanup;
--- 8053,8063 ----
    pop_from_top_level ();
  }
  
! /* Generate code to handle the destruction of DECL, an object with
!    static storage duration.  */
  
! void
! register_dtor_fn (decl)
       tree decl;
  {
    tree cleanup;
*************** destroy_local_static (decl)
*** 8068,8073 ****
--- 8067,8075 ----
  
    int saved_flag_access_control;
  
+   if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+     return;
+ 
    /* Call build_cleanup before we enter the anonymous function so that
       any access checks will be done relative to the current scope,
       rather than the scope of the anonymous function.  */
*************** expand_static_init (decl, init)
*** 8193,8200 ****
  
        /* Use atexit to register a function for destroying this static
  	 variable.  */
!       if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
! 	destroy_local_static (decl);
  
        finish_compound_stmt (/*has_no_scope=*/0, then_clause);
        finish_then_clause (if_stmt);
--- 8195,8201 ----
  
        /* Use atexit to register a function for destroying this static
  	 variable.  */
!       register_dtor_fn (decl);
  
        finish_compound_stmt (/*has_no_scope=*/0, then_clause);
        finish_then_clause (if_stmt);
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.300
diff -c -p -r1.300 decl2.c
*** decl2.c	2000/01/19 11:34:03	1.300
--- decl2.c	2000/01/23 18:36:59
*************** do_static_initialization (decl, init)
*** 3204,3209 ****
--- 3204,3214 ----
      }
    finish_expr_stmt (expr);
  
+   /* If we're using __cxa_atexit, register a a function that calls the
+      destructor for the object.  */
+   if (flag_use_cxa_atexit)
+     register_dtor_fn (decl);
+ 
    /* Finsh up.  */
    finish_static_initialization_or_destruction (sentry_if_stmt);
  }
*************** do_static_destruction (decl)
*** 3219,3228 ****
  {
    tree sentry_if_stmt;
  
    /* If we don't need a destructor, there's nothing to do.  */
    if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
      return;
!     
    /* Actually do the destruction.  */
    sentry_if_stmt = start_static_initialization_or_destruction (decl,
  							       /*initp=*/0);
--- 3224,3237 ----
  {
    tree sentry_if_stmt;
  
+   /* If we're using __cxa_atexit, then destructors are registered
+      immediately after objects are initialized.  */
+   my_friendly_assert (!flag_use_cxa_atexit, 20000121);
+ 
    /* If we don't need a destructor, there's nothing to do.  */
    if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
      return;
! 
    /* Actually do the destruction.  */
    sentry_if_stmt = start_static_initialization_or_destruction (decl,
  							       /*initp=*/0);
*************** finish_file ()
*** 3468,3477 ****
  
  	  /* Then, generate code to do all the destructions.  Do these
  	     in reverse order so that the most recently constructed
! 	     variable is the first destroyed.  */
! 	  vars = nreverse (vars);
! 	  for (v = vars; v; v = TREE_CHAIN (v))
! 	    do_static_destruction (TREE_VALUE (v));
  
  	  /* Finish up the static storage duration function for this
  	     round.  */
--- 3477,3494 ----
  
  	  /* Then, generate code to do all the destructions.  Do these
  	     in reverse order so that the most recently constructed
! 	     variable is the first destroyed.  If we're using
! 	     __cxa_atexit, then we don't need to do this; functions
! 	     we're registered at initialization time to destroy the
! 	     local statics.  */
! 	  if (!flag_use_cxa_atexit)
! 	    {
! 	      vars = nreverse (vars);
! 	      for (v = vars; v; v = TREE_CHAIN (v))
! 		do_static_destruction (TREE_VALUE (v));
! 	    }
! 	  else
! 	    vars = NULL_TREE;
  
  	  /* Finish up the static storage duration function for this
  	     round.  */


More information about the Gcc-patches mailing list