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
This commit is contained in:
parent
3fd91cbd4f
commit
0352cfc868
|
@ -1,5 +1,31 @@
|
|||
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
|
||||
templates correctly.
|
||||
|
||||
|
|
|
@ -712,7 +712,7 @@ build_vtable (binfo, type)
|
|||
tree offset;
|
||||
|
||||
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. */
|
||||
offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
|
||||
|
@ -722,7 +722,7 @@ build_vtable (binfo, type)
|
|||
else
|
||||
{
|
||||
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
|
||||
|
@ -872,7 +872,7 @@ prepare_fresh_vtable (binfo, for_type)
|
|||
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. */
|
||||
DECL_CONTEXT (new_decl) = for_type;
|
||||
|
||||
|
|
|
@ -1988,6 +1988,7 @@ wrapup_globals_for_namespace (namespace, data)
|
|||
int len = list_length (globals);
|
||||
tree *vec = (tree *) alloca (sizeof (tree) * len);
|
||||
int i;
|
||||
int result;
|
||||
tree decl;
|
||||
int last_time = (data != 0);
|
||||
|
||||
|
@ -2001,13 +2002,37 @@ wrapup_globals_for_namespace (namespace, data)
|
|||
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
|
||||
vec[len - i - 1] = decl;
|
||||
|
||||
if (!last_time)
|
||||
return wrapup_global_declarations (vec, len);
|
||||
|
||||
if (last_time)
|
||||
{
|
||||
check_global_declarations (vec, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Temporarily mark vtables as external. That prevents
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* For debugging. */
|
||||
static int no_print_functions = 0;
|
||||
|
|
224
gcc/cp/decl2.c
224
gcc/cp/decl2.c
|
@ -59,6 +59,12 @@ typedef struct priority_info_s {
|
|||
/* A label indicating where we should generate the next destruction
|
||||
with this priority. */
|
||||
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;
|
||||
|
||||
static tree get_sentry PROTO((tree));
|
||||
|
@ -2655,7 +2661,9 @@ finish_vtable_vardecl (t, data)
|
|||
import_export_vtable (vars, ctype, 1);
|
||||
|
||||
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))
|
||||
{
|
||||
/* Write it out. */
|
||||
|
@ -2700,7 +2708,7 @@ finish_vtable_vardecl (t, data)
|
|||
|
||||
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. */
|
||||
return 0;
|
||||
|
||||
|
@ -2973,6 +2981,11 @@ static tree priority_decl;
|
|||
/* The declaration for the static storage duration function. */
|
||||
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
|
||||
level. There may be many such levels, so efficient lookup is
|
||||
important. */
|
||||
|
@ -2993,8 +3006,22 @@ static splay_tree priority_info_map;
|
|||
static void
|
||||
start_static_storage_duration_function ()
|
||||
{
|
||||
static unsigned ssdf_number;
|
||||
|
||||
tree parm_types;
|
||||
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. */
|
||||
parm_types = void_list_node;
|
||||
|
@ -3004,11 +3031,35 @@ start_static_storage_duration_function ()
|
|||
|
||||
/* Create the FUNCTION_DECL itself. */
|
||||
ssdf_decl = build_lang_decl (FUNCTION_DECL,
|
||||
get_identifier (SSDF_IDENTIFIER),
|
||||
get_identifier (id),
|
||||
type);
|
||||
TREE_PUBLIC (ssdf_decl) = 0;
|
||||
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. */
|
||||
initialize_p_decl = build_decl (PARM_DECL,
|
||||
|
@ -3045,12 +3096,10 @@ start_static_storage_duration_function ()
|
|||
push_momentary ();
|
||||
expand_start_bindings (0);
|
||||
|
||||
/* 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);
|
||||
/* This function must not be deferred because we are depending on
|
||||
its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
|
||||
current_function_cannot_inline
|
||||
= "static storage duration functions cannot be inlined";
|
||||
}
|
||||
|
||||
/* Generate the initialization code for the priority indicated in N. */
|
||||
|
@ -3093,6 +3142,8 @@ generate_inits_for_priority (n, data)
|
|||
end_sequence ();
|
||||
|
||||
emit_insn (insns);
|
||||
pi->initialization_sequence = NULL_RTX;
|
||||
pi->initializations_p = 1;
|
||||
}
|
||||
|
||||
/* Do the destructions. */
|
||||
|
@ -3106,6 +3157,8 @@ generate_inits_for_priority (n, data)
|
|||
end_sequence ();
|
||||
|
||||
emit_insn (insns);
|
||||
pi->destruction_sequence = NULL_RTX;
|
||||
pi->destructions_p = 1;
|
||||
}
|
||||
|
||||
/* Close out the conditionals. */
|
||||
|
@ -3154,6 +3207,8 @@ get_priority_info (priority)
|
|||
pi = (priority_info) xmalloc (sizeof (struct priority_info_s));
|
||||
pi->initialization_sequence = NULL_RTX;
|
||||
pi->destruction_sequence = NULL_RTX;
|
||||
pi->initializations_p = 0;
|
||||
pi->destructions_p = 0;
|
||||
splay_tree_insert (priority_info_map,
|
||||
(splay_tree_key) priority,
|
||||
(splay_tree_value) pi);
|
||||
|
@ -3221,7 +3276,7 @@ do_static_initialization (decl, init, sentry, priority)
|
|||
expand_end_target_temps ();
|
||||
|
||||
/* 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. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
|
@ -3266,21 +3321,21 @@ do_static_destruction (decl, sentry, priority)
|
|||
variable in question. */
|
||||
emit_note (input_filename, lineno);
|
||||
|
||||
/* If there's a SENTRY, we only do the initialization if it is
|
||||
one, i.e., if we are the last to initialize it. */
|
||||
/* If there's a SENTRY, we only do the destruction if it is one,
|
||||
i.e., if we are the last to destroy it. */
|
||||
if (sentry)
|
||||
expand_start_cond (build_binary_op (EQ_EXPR,
|
||||
build_unary_op (PREDECREMENT_EXPR,
|
||||
sentry,
|
||||
/*nonconvert=*/1),
|
||||
integer_one_node),
|
||||
integer_zero_node),
|
||||
/*exit_flag=*/0);
|
||||
|
||||
/* Actually to the destruction. */
|
||||
expand_expr_stmt (build_cleanup (decl));
|
||||
|
||||
/* 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. */
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
|
@ -3390,6 +3445,7 @@ generate_ctor_or_dtor_function (constructor_p, priority)
|
|||
{
|
||||
char function_key;
|
||||
tree arguments;
|
||||
size_t i;
|
||||
|
||||
/* We use `I' to indicate initialization and `D' to indicate
|
||||
destruction. */
|
||||
|
@ -3403,11 +3459,15 @@ generate_ctor_or_dtor_function (constructor_p, priority)
|
|||
|
||||
/* Call the static storage duration function with appropriate
|
||||
arguments. */
|
||||
for (i = 0; i < ssdf_decls_used; ++i)
|
||||
{
|
||||
arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
|
||||
NULL_TREE);
|
||||
arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
|
||||
arguments);
|
||||
expand_expr_stmt (build_function_call (ssdf_decl, 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
|
||||
calls to any functions marked with attributes indicating that
|
||||
|
@ -3427,28 +3487,23 @@ generate_ctor_or_dtor_function (constructor_p, priority)
|
|||
}
|
||||
|
||||
/* Generate constructor and destructor functions for the priority
|
||||
indicated by N. DATA is really an `int*', and it set to `1' if we
|
||||
process the DEFAULT_INIT_PRIORITY. */
|
||||
indicated by N. */
|
||||
|
||||
static int
|
||||
generate_ctor_and_dtor_functions_for_priority (n, data)
|
||||
splay_tree_node n;
|
||||
void *data;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int priority = (int) n->key;
|
||||
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
|
||||
needed. */
|
||||
if (pi->initialization_sequence
|
||||
if (pi->initializations_p
|
||||
|| (priority == DEFAULT_INIT_PRIORITY && static_ctors))
|
||||
generate_ctor_or_dtor_function (/*constructor_p=*/1,
|
||||
priority);
|
||||
if (pi->destruction_sequence
|
||||
if (pi->destructions_p
|
||||
|| (priority == DEFAULT_INIT_PRIORITY && static_dtors))
|
||||
generate_ctor_or_dtor_function (/*constructor_p=*/0,
|
||||
priority);
|
||||
|
@ -3467,7 +3522,6 @@ finish_file ()
|
|||
{
|
||||
extern int lineno;
|
||||
int start_time, this_time;
|
||||
int did_default_priority_p = 0;
|
||||
tree vars;
|
||||
int reconsider;
|
||||
size_t i;
|
||||
|
@ -3509,18 +3563,18 @@ finish_file ()
|
|||
start_time = get_run_time ();
|
||||
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);
|
||||
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 ();
|
||||
|
||||
do
|
||||
{
|
||||
reconsider = 0;
|
||||
|
||||
/* If there are templates that we've put off instantiating, do
|
||||
|
@ -3560,7 +3614,10 @@ finish_file ()
|
|||
reconsider = 1;
|
||||
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
|
||||
synthesizing. */
|
||||
|
@ -3586,81 +3643,24 @@ finish_file ()
|
|||
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,
|
||||
but it will be fooled by DECL_NOT_REALL_EXTERN funtions, so we
|
||||
fix them up here. */
|
||||
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
|
||||
initialization. Do that now. */
|
||||
do
|
||||
{
|
||||
reconsider = 0;
|
||||
|
||||
/* 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. */
|
||||
/* We lie to the back-end, pretending that some functions are
|
||||
not defined when they really are. This keeps these functions
|
||||
from being put out unncessarily. But, we must stop lying
|
||||
when the functions are referenced, or if they are not comdat
|
||||
since they need to be put out now. */
|
||||
for (i = 0; i < saved_inlines_used; ++i)
|
||||
{
|
||||
tree decl = VARRAY_TREE (saved_inlines, i);
|
||||
|
||||
if (DECL_NOT_REALLY_EXTERN (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;
|
||||
}
|
||||
|
||||
|
@ -3668,7 +3668,6 @@ finish_file ()
|
|||
&& wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0),
|
||||
saved_inlines_used))
|
||||
reconsider = 1;
|
||||
|
||||
if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
|
||||
reconsider = 1;
|
||||
|
||||
|
@ -3689,6 +3688,29 @@ finish_file ()
|
|||
}
|
||||
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,
|
||||
etc. */
|
||||
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
|
||||
|
|
Loading…
Reference in New Issue