From f0105ed3b9568fba5d49d279a4bc12546763ad89 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Fri, 10 Sep 1999 08:30:08 +0000 Subject: [PATCH] cp-tree.h (CPTI_ATEXIT): New macro. * cp-tree.h (CPTI_ATEXIT): New macro. (atexit_node): Likewise. * decl.c (destroy_local_static): New function, broken out from ... (expand_static_init): Here. From-SVN: r29260 --- gcc/cp/ChangeLog | 5 ++ gcc/cp/cp-tree.h | 4 ++ gcc/cp/decl.c | 142 +++++++++++++++++++++++++---------------------- 3 files changed, 85 insertions(+), 66 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1d7475e28c3..a8f032292f2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 1999-09-10 Mark Mitchell + * cp-tree.h (CPTI_ATEXIT): New macro. + (atexit_node): Likewise. + * decl.c (destroy_local_static): New function, broken out from ... + (expand_static_init): Here. + * rtti.c (get_tinfo_var): These should always be global (expand_si_desc): Use tree, not RTL, functions to generate code. (expand_class_desc): Likewise. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bb47e9bd621..a35da1fa85e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -429,6 +429,7 @@ enum cp_tree_index CPTI_JCLASS, CPTI_MINUS_ONE, CPTI_TERMINATE, + CPTI_ATEXIT, CPTI_MAX }; @@ -520,6 +521,9 @@ extern tree cp_global_trees[CPTI_MAX]; /* The declaration for `std::terminate'. */ #define terminate_node cp_global_trees[CPTI_TERMINATE] +/* The declaration for `std::atexit'. */ +#define atexit_node cp_global_trees[CPTI_ATEXIT] + /* Global state. */ struct saved_scope { diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 00f7bddd8e6..21d88ae1cb3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -206,6 +206,7 @@ static void mark_binding_level PROTO((void *)); static void mark_cp_function_context PROTO((struct function *)); static void mark_saved_scope PROTO((void *)); static void check_function_type PROTO((tree)); +static void destroy_local_static PROTO((tree)); #if defined (DEBUG_CP_BINDING_LEVELS) static void indent PROTO((void)); @@ -8043,6 +8044,77 @@ finish_decl (decl, init, asmspec_tree) cp_finish_decl (decl, init, asmspec_tree, 1, 0); } +/* Generate code to handle the destruction of the function-scoped + static variable DECL. */ + +static void +destroy_local_static (decl) + tree decl; +{ + tree cleanup, fcall; + tree compound_stmt; + int saved_flag_access_control; + + if (atexit_node == 0) + { + tree atexit_fndecl, PFV, pfvlist; + /* Remember this information until end of file. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + PFV = build_pointer_type (build_function_type + (void_type_node, void_list_node)); + + pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); + + push_lang_context (lang_name_c); + /* Note that we do not call pushdecl for this function; + there's no reason that this declaration should be + accessible to anyone. */ + atexit_fndecl + = define_function ("atexit", + build_function_type (void_type_node, + pfvlist), + NOT_BUILT_IN, + /*pfn=*/0, + NULL_PTR); + mark_used (atexit_fndecl); + atexit_node = default_conversion (atexit_fndecl); + pop_lang_context (); + pop_obstacks (); + } + + /* 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. */ + build_cleanup (decl); + + /* Now start the function. */ + cleanup = start_anon_func (); + + /* Now, recompute the cleanup. It may contain SAVE_EXPRs that refer + to the original function, rather than the anonymous one. That + will make the back-end think that nested functions are in use, + which causes confusion. */ + saved_flag_access_control = flag_access_control; + flag_access_control = 0; + fcall = build_cleanup (decl); + flag_access_control = saved_flag_access_control; + + /* Create the body of the anonymous function. */ + compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); + finish_expr_stmt (fcall); + finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); + end_anon_func (); + + /* Call atexit with the cleanup function. */ + mark_addressable (cleanup); + cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); + fcall = build_function_call (atexit_node, + tree_cons (NULL_TREE, + cleanup, + NULL_TREE)); + finish_expr_stmt (fcall); +} + void expand_static_init (decl, init) tree decl; @@ -8060,6 +8132,7 @@ expand_static_init (decl, init) /* Emit code to perform this initialization but once. */ tree temp; tree if_stmt; + tree then_clause; tree assignment; tree temp_init; @@ -8098,6 +8171,7 @@ expand_static_init (decl, init) finish_if_stmt_cond (build_binary_op (EQ_EXPR, temp, integer_zero_node), if_stmt); + then_clause = begin_compound_stmt (/*has_no_scope=*/0); /* Do the initialization itself. */ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) @@ -8133,73 +8207,9 @@ expand_static_init (decl, init) /* Use atexit to register a function for destroying this static variable. */ if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl))) - { - tree cleanup, fcall; - static tree Atexit = 0; - int saved_flag_access_control; - - if (Atexit == 0) - { - tree atexit_fndecl, PFV, pfvlist; - - ggc_add_tree_root (&Atexit, 1); - - /* Remember this information until end of file. */ - push_obstacks (&permanent_obstack, &permanent_obstack); - PFV = build_pointer_type (build_function_type - (void_type_node, void_list_node)); - - pfvlist = tree_cons (NULL_TREE, PFV, void_list_node); - - push_lang_context (lang_name_c); - /* Note that we do not call pushdecl for this function; - there's no reason that this declaration should be - accessible to anyone. */ - atexit_fndecl - = define_function ("atexit", - build_function_type (void_type_node, - pfvlist), - NOT_BUILT_IN, - /*pfn=*/0, - NULL_PTR); - mark_used (atexit_fndecl); - Atexit = default_conversion (atexit_fndecl); - pop_lang_context (); - pop_obstacks (); - } - - /* 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. */ - build_cleanup (decl); - - /* Now start the function. */ - cleanup = start_anon_func (); - - /* Now, recompute the cleanup. It may contain SAVE_EXPRs - that refer to the original function, rather than the - anonymous one. That will make the back-end think that - nested functions are in use, which causes confusion. */ - saved_flag_access_control = flag_access_control; - flag_access_control = 0; - fcall = build_cleanup (decl); - flag_access_control = saved_flag_access_control; - - /* Finish off the function. */ - expand_expr_stmt (fcall); - end_anon_func (); - - /* Call atexit with the cleanup function. */ - mark_addressable (cleanup); - cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); - fcall = build_function_call (Atexit, - tree_cons (NULL_TREE, - cleanup, - NULL_TREE)); - finish_expr_stmt (fcall); - } + destroy_local_static (decl); + finish_compound_stmt (/*has_no_scope=*/0, then_clause); finish_then_clause (if_stmt); finish_if_stmt ();