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