This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Using __cxa_atexit for globals
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: Using __cxa_atexit for globals
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 23 Jan 2000 10:42:46 -0800
- Organization: CodeSourcery, LLC
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. */