diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b77388c2fd57033e8f5cd050a69c8e31c1966463..44109ef82f54925e44ec91ca342314c8b0090a96 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2005-09-26 Richard Guenther <rguenther@suse.de> + + PR middle-end/15855 + * decl2.c (do_static_destruction): Remove. + (finish_static_initialization_or_destruction): Likewise. + (DECL_EFFECTIVE_INIT_PRIORITY): New macro. + (NEEDS_GUARD_P): Likewise. + (do_static_initialization): Rename to + do_static_initialization_or_destruction. Process all + initializers/destructors and handle common conditionalizing. + (start_static_initialization_or_destruction): Rename to + one_static_initialization_or_destruction. Handle only + decl-specific conditionalizing. + (cp_finish_file): Call do_static_initialization_or_destruction. + 2005-09-22 Jakub Jelinek <jakub@redhat.com> PR c++/21983 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c2a90fc5bc564c23462c3f450769805cbe2afbde..1e812838435f5226fb5aa7d2cf0ac061a7e6c615 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -73,10 +73,8 @@ static void finish_objects (int, int, tree); static tree start_static_storage_duration_function (unsigned); static void finish_static_storage_duration_function (tree); static priority_info get_priority_info (int); -static void do_static_initialization (tree, tree); -static void do_static_destruction (tree); -static tree start_static_initialization_or_destruction (tree, int); -static void finish_static_initialization_or_destruction (tree); +static void do_static_initialization_or_destruction (tree, bool); +static void one_static_initialization_or_destruction (tree, tree, bool); static void generate_ctor_or_dtor_function (bool, int, location_t *); static int generate_ctor_and_dtor_functions_for_priority (splay_tree_node, void *); @@ -2316,33 +2314,34 @@ get_priority_info (int priority) return pi; } +/* The effective initialization priority of a DECL. */ + +#define DECL_EFFECTIVE_INIT_PRIORITY(decl) \ + ((!DECL_HAS_INIT_PRIORITY_P (decl) || DECL_INIT_PRIORITY (decl) == 0) \ + ? DEFAULT_INIT_PRIORITY : DECL_INIT_PRIORITY (decl)) + +/* Wether a DECL needs a guard to protect it against multiple + initialization. */ + +#define NEEDS_GUARD_P(decl) (TREE_PUBLIC (decl) && (DECL_COMMON (decl) \ + || DECL_ONE_ONLY (decl) \ + || DECL_WEAK (decl))) + /* Set up to handle the initialization or destruction of DECL. If INITP is nonzero, we are initializing the variable. Otherwise, we are destroying it. */ -static tree -start_static_initialization_or_destruction (tree decl, int initp) +static void +one_static_initialization_or_destruction (tree decl, tree init, bool initp) { tree guard_if_stmt = NULL_TREE; - int priority = 0; - tree cond; tree guard; - tree init_cond; - priority_info pi; - - /* Figure out the priority for this declaration. */ - if (DECL_HAS_INIT_PRIORITY_P (decl)) - priority = DECL_INIT_PRIORITY (decl); - if (!priority) - priority = DEFAULT_INIT_PRIORITY; - /* Remember that we had an initialization or finalization at this - priority. */ - pi = get_priority_info (priority); - if (initp) - pi->initializations_p = 1; - else - pi->destructions_p = 1; + /* If we are supposed to destruct and there's a trivial destructor, + nothing has to be done. */ + if (!initp + && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) + return; /* Trick the compiler into thinking we are at the file and line where DECL was declared so that error-messages make sense, and so @@ -2368,27 +2367,13 @@ start_static_initialization_or_destruction (tree decl, int initp) DECL_STATIC_FUNCTION_P (current_function_decl) = 1; } - /* Conditionalize this initialization on being in the right priority - and being initializing/finalizing appropriately. */ - guard_if_stmt = begin_if_stmt (); - cond = cp_build_binary_op (EQ_EXPR, - priority_decl, - build_int_cst (NULL_TREE, priority)); - init_cond = initp ? integer_one_node : integer_zero_node; - init_cond = cp_build_binary_op (EQ_EXPR, - initialize_p_decl, - init_cond); - cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond); - /* Assume we don't need a guard. */ guard = NULL_TREE; /* We need a guard if this is an object with external linkage that might be initialized in more than one place. (For example, a static data member of a template, when the data member requires construction.) */ - if (TREE_PUBLIC (decl) && (DECL_COMMON (decl) - || DECL_ONE_ONLY (decl) - || DECL_WEAK (decl))) + if (NEEDS_GUARD_P (decl)) { tree guard_cond; @@ -2425,28 +2410,36 @@ start_static_initialization_or_destruction (tree decl, int initp) /*noconvert=*/1), integer_zero_node); - cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, guard_cond); + guard_if_stmt = begin_if_stmt (); + finish_if_stmt_cond (guard_cond, guard_if_stmt); } - finish_if_stmt_cond (cond, guard_if_stmt); /* If we're using __cxa_atexit, we have not already set the GUARD, so we must do so now. */ if (guard && initp && flag_use_cxa_atexit) finish_expr_stmt (set_guard (guard)); - return guard_if_stmt; -} + /* Perform the initialization or destruction. */ + if (initp) + { + if (init) + finish_expr_stmt (init); -/* We've just finished generating code to do an initialization or - finalization. GUARD_IF_STMT is the if-statement we used to guard - the initialization. */ + /* If we're using __cxa_atexit, register a function that calls the + destructor for the object. */ + if (flag_use_cxa_atexit) + finish_expr_stmt (register_dtor_fn (decl)); + } + else + finish_expr_stmt (build_cleanup (decl)); -static void -finish_static_initialization_or_destruction (tree guard_if_stmt) -{ - finish_then_clause (guard_if_stmt); - finish_if_stmt (guard_if_stmt); + /* Finish the guard if-stmt, if necessary. */ + if (guard) + { + finish_then_clause (guard_if_stmt); + finish_if_stmt (guard_if_stmt); + } /* Now that we're done with DECL we don't need to pretend to be a member of its class any longer. */ @@ -2454,55 +2447,72 @@ finish_static_initialization_or_destruction (tree guard_if_stmt) DECL_STATIC_FUNCTION_P (current_function_decl) = 0; } -/* Generate code to do the initialization of DECL, a VAR_DECL with - static storage duration. The initialization is INIT. */ +/* Generate code to do the initialization or destruction of the decls in VARS, + a TREE_LIST of VAR_DECL with static storage duration. + Whether initialization or destruction is performed is specified by INITP. */ static void -do_static_initialization (tree decl, tree init) +do_static_initialization_or_destruction (tree vars, bool initp) { - tree guard_if_stmt; - - /* Set up for the initialization. */ - guard_if_stmt - = start_static_initialization_or_destruction (decl, - /*initp=*/1); - - /* Perform the initialization. */ - if (init) - finish_expr_stmt (init); - - /* If we're using __cxa_atexit, register a function that calls the - destructor for the object. */ - if (flag_use_cxa_atexit) - finish_expr_stmt (register_dtor_fn (decl)); + tree node, init_if_stmt, cond; - /* Finish up. */ - finish_static_initialization_or_destruction (guard_if_stmt); -} - -/* Generate code to do the static destruction of DECL. If DECL may be - initialized more than once in different object files, GUARD is the - guard variable to check. PRIORITY is the priority for the - destruction. */ - -static void -do_static_destruction (tree decl) -{ - tree guard_if_stmt; - - /* If we're using __cxa_atexit, then destructors are registered - immediately after objects are initialized. */ - gcc_assert (!flag_use_cxa_atexit); - - /* If we don't need a destructor, there's nothing to do. */ - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) - return; + /* Build the outer if-stmt to check for initialization or destruction. */ + init_if_stmt = begin_if_stmt (); + cond = initp ? integer_one_node : integer_zero_node; + cond = cp_build_binary_op (EQ_EXPR, + initialize_p_decl, + cond); + finish_if_stmt_cond (cond, init_if_stmt); + + node = vars; + do { + tree decl = TREE_VALUE (node); + tree priority_if_stmt; + int priority; + priority_info pi; + + /* If we don't need a destructor, there's nothing to do. Avoid + creating a possibly empty if-stmt. */ + if (!initp && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) + { + node = TREE_CHAIN (node); + continue; + } - /* Actually do the destruction. */ - guard_if_stmt = start_static_initialization_or_destruction (decl, - /*initp=*/0); - finish_expr_stmt (build_cleanup (decl)); - finish_static_initialization_or_destruction (guard_if_stmt); + /* Remember that we had an initialization or finalization at this + priority. */ + priority = DECL_EFFECTIVE_INIT_PRIORITY (decl); + pi = get_priority_info (priority); + if (initp) + pi->initializations_p = 1; + else + pi->destructions_p = 1; + + /* Conditionalize this initialization on being in the right priority + and being initializing/finalizing appropriately. */ + priority_if_stmt = begin_if_stmt (); + cond = cp_build_binary_op (EQ_EXPR, + priority_decl, + build_int_cst (NULL_TREE, priority)); + finish_if_stmt_cond (cond, priority_if_stmt); + + /* Process initializers with same priority. */ + for (; node + && DECL_EFFECTIVE_INIT_PRIORITY (TREE_VALUE (node)) == priority; + node = TREE_CHAIN (node)) + /* Do one initialization or destruction. */ + one_static_initialization_or_destruction (TREE_VALUE (node), + TREE_PURPOSE (node), initp); + + /* Finish up the priority if-stmt body. */ + finish_then_clause (priority_if_stmt); + finish_if_stmt (priority_if_stmt); + + } while (node); + + /* Finish up the init/destruct if-stmt body. */ + finish_then_clause (init_if_stmt); + finish_if_stmt (init_if_stmt); } /* VARS is a list of variables with static storage duration which may @@ -2900,8 +2910,6 @@ cp_finish_file (void) if (vars) { - tree v; - /* We need to start a new initialization function each time through the loop. That's because we need to know which vtables have been referenced, and TREE_SYMBOL_REFERENCED @@ -2920,9 +2928,8 @@ cp_finish_file (void) write_out_vars (vars); /* First generate code to do all the initializations. */ - for (v = vars; v; v = TREE_CHAIN (v)) - do_static_initialization (TREE_VALUE (v), - TREE_PURPOSE (v)); + if (vars) + do_static_initialization_or_destruction (vars, /*initp=*/true); /* Then, generate code to do all the destructions. Do these in reverse order so that the most recently constructed @@ -2930,11 +2937,10 @@ cp_finish_file (void) __cxa_atexit, then we don't need to do this; functions were registered at initialization time to destroy the local statics. */ - if (!flag_use_cxa_atexit) + if (!flag_use_cxa_atexit && vars) { vars = nreverse (vars); - for (v = vars; v; v = TREE_CHAIN (v)) - do_static_destruction (TREE_VALUE (v)); + do_static_initialization_or_destruction (vars, /*initp=*/false); } else vars = NULL_TREE;