Commit 0352cfc8 by Mark Mitchell Committed by Mark Mitchell

class.c (build_vtable): Use build_lang_decl when building vtables, not just build_decl.

	* class.c (build_vtable): Use build_lang_decl when building
	vtables, not just build_decl.
	(prepare_fresh_vtable): Likewise.
	* decl.c (wrapup_globals_for_namespace): Mark vtables as
	DECL_EXTERNAL when calling wrapup_global_declarations.
	* decl2.c (priority_info_s): Add initializations_p and
	destructions_p members.
	(finish_vtable_vardecl): Use TREE_SYMBOL_REFERENCED, not TREE_USED,
	when deciding what vtables to write out.
	(ssdf_decls): New variable.
	(ssdf_decls_used): Likewise.
	(start_static_storage_duration_function): Deal with being called
	multiple times.  Avoid inlining this function.
	(generate_inits_for_priority): Deal with reuse of priority map.
	(get_priority_info): Clear initializations_p and destructions_p.
	(do_static_initialization): Tweak comment.
	(do_static_destruction): Likewise.  Fix condition on sentries for
	destruction.
	(generate_ctor_or_dtor_function): Call all of the static storage
	duration functions.
	(generate_ctor_or_dtor_function_for_priority): Check
	initializations_p and destructions_p to see what priorities need
	initialization functions.
	(finish_file): Rework to generate multiple static storage duration
	functions, rather than just one.

From-SVN: r26713
parent 3fd91cbd
1999-04-30 Mark Mitchell <mark@codesourcery.com> 1999-04-30 Mark Mitchell <mark@codesourcery.com>
* class.c (build_vtable): Use build_lang_decl when building
vtables, not just build_decl.
(prepare_fresh_vtable): Likewise.
* decl.c (wrapup_globals_for_namespace): Mark vtables as
DECL_EXTERNAL when calling wrapup_global_declarations.
* decl2.c (priority_info_s): Add initializations_p and
destructions_p members.
(finish_vtable_vardecl): Use TREE_SYMBOL_REFERENCED, not TREE_USED,
when deciding what vtables to write out.
(ssdf_decls): New variable.
(ssdf_decls_used): Likewise.
(start_static_storage_duration_function): Deal with being called
multiple times. Avoid inlining this function.
(generate_inits_for_priority): Deal with reuse of priority map.
(get_priority_info): Clear initializations_p and destructions_p.
(do_static_initialization): Tweak comment.
(do_static_destruction): Likewise. Fix condition on sentries for
destruction.
(generate_ctor_or_dtor_function): Call all of the static storage
duration functions.
(generate_ctor_or_dtor_function_for_priority): Check
initializations_p and destructions_p to see what priorities need
initialization functions.
(finish_file): Rework to generate multiple static storage duration
functions, rather than just one.
* typeck.c (build_const_cast): Tweak last change to handle * typeck.c (build_const_cast): Tweak last change to handle
templates correctly. templates correctly.
......
...@@ -712,7 +712,7 @@ build_vtable (binfo, type) ...@@ -712,7 +712,7 @@ build_vtable (binfo, type)
tree offset; tree offset;
virtuals = copy_list (BINFO_VIRTUALS (binfo)); virtuals = copy_list (BINFO_VIRTUALS (binfo));
decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo))); decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
/* Now do rtti stuff. */ /* Now do rtti stuff. */
offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE); offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
...@@ -722,7 +722,7 @@ build_vtable (binfo, type) ...@@ -722,7 +722,7 @@ build_vtable (binfo, type)
else else
{ {
virtuals = NULL_TREE; virtuals = NULL_TREE;
decl = build_decl (VAR_DECL, name, void_type_node); decl = build_lang_decl (VAR_DECL, name, void_type_node);
} }
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
...@@ -872,7 +872,7 @@ prepare_fresh_vtable (binfo, for_type) ...@@ -872,7 +872,7 @@ prepare_fresh_vtable (binfo, for_type)
buf2 = new_buf2; buf2 = new_buf2;
} }
new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
/* Remember which class this vtable is really for. */ /* Remember which class this vtable is really for. */
DECL_CONTEXT (new_decl) = for_type; DECL_CONTEXT (new_decl) = for_type;
......
...@@ -1988,6 +1988,7 @@ wrapup_globals_for_namespace (namespace, data) ...@@ -1988,6 +1988,7 @@ wrapup_globals_for_namespace (namespace, data)
int len = list_length (globals); int len = list_length (globals);
tree *vec = (tree *) alloca (sizeof (tree) * len); tree *vec = (tree *) alloca (sizeof (tree) * len);
int i; int i;
int result;
tree decl; tree decl;
int last_time = (data != 0); int last_time = (data != 0);
...@@ -2001,11 +2002,35 @@ wrapup_globals_for_namespace (namespace, data) ...@@ -2001,11 +2002,35 @@ wrapup_globals_for_namespace (namespace, data)
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[len - i - 1] = decl; vec[len - i - 1] = decl;
if (!last_time) if (last_time)
return wrapup_global_declarations (vec, len); {
check_global_declarations (vec, len);
return 0;
}
check_global_declarations (vec, len); /* Temporarily mark vtables as external. That prevents
return 0; wrapup_global_declarations from writing them out; we must process
them ourselves in finish_vtable_vardecl. */
for (i = 0; i < len; ++i)
if (vtable_decl_p (vec[i], /*data=*/0))
{
DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
DECL_EXTERNAL (vec[i]) = 1;
}
/* Write out any globals that need to be output. */
result = wrapup_global_declarations (vec, len);
/* Undo the hack to DECL_EXTERNAL above. */
for (i = 0; i < len; ++i)
if (vtable_decl_p (vec[i], /*data=*/0)
&& DECL_NOT_REALLY_EXTERN (vec[i]))
{
DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
DECL_EXTERNAL (vec[i]) = 0;
}
return result;
} }
......
...@@ -59,6 +59,12 @@ typedef struct priority_info_s { ...@@ -59,6 +59,12 @@ typedef struct priority_info_s {
/* A label indicating where we should generate the next destruction /* A label indicating where we should generate the next destruction
with this priority. */ with this priority. */
rtx destruction_sequence; rtx destruction_sequence;
/* Non-zero if there have been any initializations at this priority
throughout the translation unit. */
int initializations_p;
/* Non-zero if there have been any destructions at this priority
throughout the translation unit. */
int destructions_p;
} *priority_info; } *priority_info;
static tree get_sentry PROTO((tree)); static tree get_sentry PROTO((tree));
...@@ -2655,7 +2661,9 @@ finish_vtable_vardecl (t, data) ...@@ -2655,7 +2661,9 @@ finish_vtable_vardecl (t, data)
import_export_vtable (vars, ctype, 1); import_export_vtable (vars, ctype, 1);
if (! DECL_EXTERNAL (vars) if (! DECL_EXTERNAL (vars)
&& (DECL_INTERFACE_KNOWN (vars) || TREE_USED (vars)) && (DECL_INTERFACE_KNOWN (vars)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars))
|| (hack_decl_function_context (vars) && TREE_USED (vars)))
&& ! TREE_ASM_WRITTEN (vars)) && ! TREE_ASM_WRITTEN (vars))
{ {
/* Write it out. */ /* Write it out. */
...@@ -2700,7 +2708,7 @@ finish_vtable_vardecl (t, data) ...@@ -2700,7 +2708,7 @@ finish_vtable_vardecl (t, data)
return 1; return 1;
} }
else if (! TREE_USED (vars)) else if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (vars)))
/* We don't know what to do with this one yet. */ /* We don't know what to do with this one yet. */
return 0; return 0;
...@@ -2973,6 +2981,11 @@ static tree priority_decl; ...@@ -2973,6 +2981,11 @@ static tree priority_decl;
/* The declaration for the static storage duration function. */ /* The declaration for the static storage duration function. */
static tree ssdf_decl; static tree ssdf_decl;
/* All the static storage duration functions created in this
translation unit. */
static varray_type ssdf_decls;
static size_t ssdf_decls_used;
/* A map from priority levels to information about that priority /* A map from priority levels to information about that priority
level. There may be many such levels, so efficient lookup is level. There may be many such levels, so efficient lookup is
important. */ important. */
...@@ -2993,8 +3006,22 @@ static splay_tree priority_info_map; ...@@ -2993,8 +3006,22 @@ static splay_tree priority_info_map;
static void static void
start_static_storage_duration_function () start_static_storage_duration_function ()
{ {
static unsigned ssdf_number;
tree parm_types; tree parm_types;
tree type; tree type;
char id[sizeof (SSDF_IDENTIFIER) + 1 /* '\0' */ + 32];
/* Create the identifier for this function. It will be of the form
SSDF_IDENTIFIER_<number>. */
sprintf (id, "%s_%u", SSDF_IDENTIFIER, ssdf_number++);
if (ssdf_number == 0)
{
/* Overflow occurred. That means there are at least 4 billion
initialization functions. */
sorry ("too many initialization functions required");
my_friendly_abort (19990430);
}
/* Create the parameters. */ /* Create the parameters. */
parm_types = void_list_node; parm_types = void_list_node;
...@@ -3004,11 +3031,35 @@ start_static_storage_duration_function () ...@@ -3004,11 +3031,35 @@ start_static_storage_duration_function ()
/* Create the FUNCTION_DECL itself. */ /* Create the FUNCTION_DECL itself. */
ssdf_decl = build_lang_decl (FUNCTION_DECL, ssdf_decl = build_lang_decl (FUNCTION_DECL,
get_identifier (SSDF_IDENTIFIER), get_identifier (id),
type); type);
TREE_PUBLIC (ssdf_decl) = 0; TREE_PUBLIC (ssdf_decl) = 0;
DECL_ARTIFICIAL (ssdf_decl) = 1; DECL_ARTIFICIAL (ssdf_decl) = 1;
DECL_INLINE (ssdf_decl) = 1;
/* Put this function in the list of functions to be called from the
static constructors and destructors. */
if (!ssdf_decls)
{
VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
/* Take this opportunity to initialize the map from priority
numbers to information about that priority level. */
priority_info_map = splay_tree_new (splay_tree_compare_ints,
/*delete_key_fn=*/0,
/*delete_value_fn=*/
(splay_tree_delete_value_fn) &free);
/* We always need to generate functions for the
DEFAULT_INIT_PRIORITY so enter it now. That way when we walk
priorities later, we'll be sure to find the
DEFAULT_INIT_PRIORITY. */
get_priority_info (DEFAULT_INIT_PRIORITY);
}
if (ssdf_decls_used == ssdf_decls->num_elements)
VARRAY_GROW (ssdf_decls, 2 * ssdf_decls_used);
VARRAY_TREE (ssdf_decls, ssdf_decls_used) = ssdf_decl;
++ssdf_decls_used;
/* Create the argument list. */ /* Create the argument list. */
initialize_p_decl = build_decl (PARM_DECL, initialize_p_decl = build_decl (PARM_DECL,
...@@ -3045,12 +3096,10 @@ start_static_storage_duration_function () ...@@ -3045,12 +3096,10 @@ start_static_storage_duration_function ()
push_momentary (); push_momentary ();
expand_start_bindings (0); expand_start_bindings (0);
/* Initialize the map from priority numbers to information about /* This function must not be deferred because we are depending on
that priority level. */ its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
priority_info_map = splay_tree_new (splay_tree_compare_ints, current_function_cannot_inline
/*delete_key_fn=*/0, = "static storage duration functions cannot be inlined";
/*delete_value_fn=*/
(splay_tree_delete_value_fn) &free);
} }
/* Generate the initialization code for the priority indicated in N. */ /* Generate the initialization code for the priority indicated in N. */
...@@ -3093,6 +3142,8 @@ generate_inits_for_priority (n, data) ...@@ -3093,6 +3142,8 @@ generate_inits_for_priority (n, data)
end_sequence (); end_sequence ();
emit_insn (insns); emit_insn (insns);
pi->initialization_sequence = NULL_RTX;
pi->initializations_p = 1;
} }
/* Do the destructions. */ /* Do the destructions. */
...@@ -3106,6 +3157,8 @@ generate_inits_for_priority (n, data) ...@@ -3106,6 +3157,8 @@ generate_inits_for_priority (n, data)
end_sequence (); end_sequence ();
emit_insn (insns); emit_insn (insns);
pi->destruction_sequence = NULL_RTX;
pi->destructions_p = 1;
} }
/* Close out the conditionals. */ /* Close out the conditionals. */
...@@ -3154,6 +3207,8 @@ get_priority_info (priority) ...@@ -3154,6 +3207,8 @@ get_priority_info (priority)
pi = (priority_info) xmalloc (sizeof (struct priority_info_s)); pi = (priority_info) xmalloc (sizeof (struct priority_info_s));
pi->initialization_sequence = NULL_RTX; pi->initialization_sequence = NULL_RTX;
pi->destruction_sequence = NULL_RTX; pi->destruction_sequence = NULL_RTX;
pi->initializations_p = 0;
pi->destructions_p = 0;
splay_tree_insert (priority_info_map, splay_tree_insert (priority_info_map,
(splay_tree_key) priority, (splay_tree_key) priority,
(splay_tree_value) pi); (splay_tree_value) pi);
...@@ -3221,7 +3276,7 @@ do_static_initialization (decl, init, sentry, priority) ...@@ -3221,7 +3276,7 @@ do_static_initialization (decl, init, sentry, priority)
expand_end_target_temps (); expand_end_target_temps ();
/* Cleanup any deferred pops from function calls. This would be done /* Cleanup any deferred pops from function calls. This would be done
by expand_end_cond, but we also need it when !sentry, since we are by expand_end_cond, but we also need it when !SENTRY, since we are
constructing these sequences by parts. */ constructing these sequences by parts. */
do_pending_stack_adjust (); do_pending_stack_adjust ();
...@@ -3266,21 +3321,21 @@ do_static_destruction (decl, sentry, priority) ...@@ -3266,21 +3321,21 @@ do_static_destruction (decl, sentry, priority)
variable in question. */ variable in question. */
emit_note (input_filename, lineno); emit_note (input_filename, lineno);
/* If there's a SENTRY, we only do the initialization if it is /* If there's a SENTRY, we only do the destruction if it is one,
one, i.e., if we are the last to initialize it. */ i.e., if we are the last to destroy it. */
if (sentry) if (sentry)
expand_start_cond (build_binary_op (EQ_EXPR, expand_start_cond (build_binary_op (EQ_EXPR,
build_unary_op (PREDECREMENT_EXPR, build_unary_op (PREDECREMENT_EXPR,
sentry, sentry,
/*nonconvert=*/1), /*nonconvert=*/1),
integer_one_node), integer_zero_node),
/*exit_flag=*/0); /*exit_flag=*/0);
/* Actually to the destruction. */ /* Actually to the destruction. */
expand_expr_stmt (build_cleanup (decl)); expand_expr_stmt (build_cleanup (decl));
/* Cleanup any deferred pops from function calls. This would be done /* Cleanup any deferred pops from function calls. This would be done
by expand_end_cond, but we also need it when !sentry, since we are by expand_end_cond, but we also need it when !SENTRY, since we are
constructing these sequences by parts. */ constructing these sequences by parts. */
do_pending_stack_adjust (); do_pending_stack_adjust ();
...@@ -3390,6 +3445,7 @@ generate_ctor_or_dtor_function (constructor_p, priority) ...@@ -3390,6 +3445,7 @@ generate_ctor_or_dtor_function (constructor_p, priority)
{ {
char function_key; char function_key;
tree arguments; tree arguments;
size_t i;
/* We use `I' to indicate initialization and `D' to indicate /* We use `I' to indicate initialization and `D' to indicate
destruction. */ destruction. */
...@@ -3403,11 +3459,15 @@ generate_ctor_or_dtor_function (constructor_p, priority) ...@@ -3403,11 +3459,15 @@ generate_ctor_or_dtor_function (constructor_p, priority)
/* Call the static storage duration function with appropriate /* Call the static storage duration function with appropriate
arguments. */ arguments. */
arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0), for (i = 0; i < ssdf_decls_used; ++i)
NULL_TREE); {
arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0), arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
arguments); NULL_TREE);
expand_expr_stmt (build_function_call (ssdf_decl, arguments)); arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
arguments);
expand_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
arguments));
}
/* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in /* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
calls to any functions marked with attributes indicating that calls to any functions marked with attributes indicating that
...@@ -3427,28 +3487,23 @@ generate_ctor_or_dtor_function (constructor_p, priority) ...@@ -3427,28 +3487,23 @@ generate_ctor_or_dtor_function (constructor_p, priority)
} }
/* Generate constructor and destructor functions for the priority /* Generate constructor and destructor functions for the priority
indicated by N. DATA is really an `int*', and it set to `1' if we indicated by N. */
process the DEFAULT_INIT_PRIORITY. */
static int static int
generate_ctor_and_dtor_functions_for_priority (n, data) generate_ctor_and_dtor_functions_for_priority (n, data)
splay_tree_node n; splay_tree_node n;
void *data; void *data ATTRIBUTE_UNUSED;
{ {
int priority = (int) n->key; int priority = (int) n->key;
priority_info pi = (priority_info) n->value; priority_info pi = (priority_info) n->value;
int *did_default_priority_p = (int*) data;
if (priority == DEFAULT_INIT_PRIORITY)
*did_default_priority_p = 1;
/* Generate the functions themselves, but only if they are really /* Generate the functions themselves, but only if they are really
needed. */ needed. */
if (pi->initialization_sequence if (pi->initializations_p
|| (priority == DEFAULT_INIT_PRIORITY && static_ctors)) || (priority == DEFAULT_INIT_PRIORITY && static_ctors))
generate_ctor_or_dtor_function (/*constructor_p=*/1, generate_ctor_or_dtor_function (/*constructor_p=*/1,
priority); priority);
if (pi->destruction_sequence if (pi->destructions_p
|| (priority == DEFAULT_INIT_PRIORITY && static_dtors)) || (priority == DEFAULT_INIT_PRIORITY && static_dtors))
generate_ctor_or_dtor_function (/*constructor_p=*/0, generate_ctor_or_dtor_function (/*constructor_p=*/0,
priority); priority);
...@@ -3467,7 +3522,6 @@ finish_file () ...@@ -3467,7 +3522,6 @@ finish_file ()
{ {
extern int lineno; extern int lineno;
int start_time, this_time; int start_time, this_time;
int did_default_priority_p = 0;
tree vars; tree vars;
int reconsider; int reconsider;
size_t i; size_t i;
...@@ -3509,18 +3563,18 @@ finish_file () ...@@ -3509,18 +3563,18 @@ finish_file ()
start_time = get_run_time (); start_time = get_run_time ();
permanent_allocation (1); permanent_allocation (1);
/* Create the function that will contain all initializations and
destructions for objects with static storage duration. We cannot
conclude that because a symbol is not TREE_SYMBOL_REFERENCED the
corresponding entity is not used until we call finish_function
for the static storage duration function. We give C linkage to
static constructors and destructors. */
push_lang_context (lang_name_c);
start_static_storage_duration_function ();
push_to_top_level ();
do do
{ {
/* 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
isn't computed until a function is finished, and written out.
That's a deficiency in the back-end. When this is fixed,
these initialization functions could all become inline, with
resulting performance improvements. */
start_static_storage_duration_function ();
push_to_top_level ();
reconsider = 0; reconsider = 0;
/* If there are templates that we've put off instantiating, do /* If there are templates that we've put off instantiating, do
...@@ -3560,8 +3614,11 @@ finish_file () ...@@ -3560,8 +3614,11 @@ finish_file ()
reconsider = 1; reconsider = 1;
vars = TREE_CHAIN (vars); vars = TREE_CHAIN (vars);
} }
push_to_top_level ();
/* Finish up the static storage duration function for this
round. */
finish_static_storage_duration_function ();
/* Go through the various inline functions, and see if any need /* Go through the various inline functions, and see if any need
synthesizing. */ synthesizing. */
for (i = 0; i < saved_inlines_used; ++i) for (i = 0; i < saved_inlines_used; ++i)
...@@ -3586,81 +3643,24 @@ finish_file () ...@@ -3586,81 +3643,24 @@ finish_file ()
reconsider = 1; reconsider = 1;
} }
} }
}
while (reconsider);
/* Finish up the static storage duration function, now that we now
there can be no more things in need of initialization or
destruction. */
pop_from_top_level ();
finish_static_storage_duration_function ();
/* Generate initialization and destruction functions for all
priorities for which they are required. */
if (priority_info_map)
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
&did_default_priority_p);
if (!did_default_priority_p)
{
/* Even if there were no explicit initializations or
destructions required, we may still have to handle the
default priority if there functions declared as constructors
or destructors via attributes. */
if (static_ctors)
generate_ctor_or_dtor_function (/*constructor_p=*/1,
DEFAULT_INIT_PRIORITY);
if (static_dtors)
generate_ctor_or_dtor_function (/*constructor_p=*/0,
DEFAULT_INIT_PRIORITY);
}
/* We're done with the splay-tree now. */
if (priority_info_map)
splay_tree_delete (priority_info_map);
/* We're done with static constructors, so we can go back to "C++"
linkage now. */
pop_lang_context ();
/* Mark all functions that might deal with exception-handling as
referenced. */
mark_all_runtime_matches ();
/* Now delete from the chain of variables all virtual function tables.
We output them all ourselves, because each will be treated
specially. */
walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0);
/* We'll let wrapup_global_declarations handle the inline functions, /* Mark all functions that might deal with exception-handling as
but it will be fooled by DECL_NOT_REALL_EXTERN funtions, so we referenced. */
fix them up here. */ mark_all_runtime_matches ();
for (i = 0; i < saved_inlines_used; ++i)
{
tree decl = VARRAY_TREE (saved_inlines, i);
if (DECL_NOT_REALLY_EXTERN (decl) && !DECL_COMDAT (decl)
&& DECL_INITIAL (decl))
DECL_EXTERNAL (decl) = 0;
}
/* We haven't handled non-local objects that don't need dynamic /* We lie to the back-end, pretending that some functions are
initialization. Do that now. */ not defined when they really are. This keeps these functions
do from being put out unncessarily. But, we must stop lying
{ when the functions are referenced, or if they are not comdat
reconsider = 0; since they need to be put out now. */
/* Above, we hung back on weak functions; they will be defined
where they are needed. But, here we loop again, so that we
output the things that *are* needed. */
for (i = 0; i < saved_inlines_used; ++i) for (i = 0; i < saved_inlines_used; ++i)
{ {
tree decl = VARRAY_TREE (saved_inlines, i); tree decl = VARRAY_TREE (saved_inlines, i);
if (DECL_NOT_REALLY_EXTERN (decl) if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl) && DECL_INITIAL (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) && (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
|| !DECL_COMDAT (decl)))
DECL_EXTERNAL (decl) = 0; DECL_EXTERNAL (decl) = 0;
} }
...@@ -3668,7 +3668,6 @@ finish_file () ...@@ -3668,7 +3668,6 @@ finish_file ()
&& wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0), && wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0),
saved_inlines_used)) saved_inlines_used))
reconsider = 1; reconsider = 1;
if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0)) if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
reconsider = 1; reconsider = 1;
...@@ -3686,9 +3685,32 @@ finish_file () ...@@ -3686,9 +3685,32 @@ finish_file ()
&& wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0), && wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
pending_statics_used)) pending_statics_used))
reconsider = 1; reconsider = 1;
} }
while (reconsider); while (reconsider);
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
/* Generate initialization and destruction functions for all
priorities for which they are required. */
if (priority_info_map)
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
/*data=*/0);
/* We're done with the splay-tree now. */
if (priority_info_map)
splay_tree_delete (priority_info_map);
/* We're done with static constructors, so we can go back to "C++"
linkage now. */
pop_lang_context ();
/* Now delete from the chain of variables all virtual function tables.
We output them all ourselves, because each will be treated
specially. */
walk_globals (vtable_decl_p, prune_vtable_vardecl, /*data=*/0);
/* Now, issue warnings about static, but not defined, functions, /* Now, issue warnings about static, but not defined, functions,
etc. */ etc. */
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider); walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment