Commit 961ec1a5 by Jason Merrill Committed by Jason Merrill

decl2.c (start_objects, [...]): Split out from...

	* decl2.c (start_objects, finish_objects, do_dtors,
	do_ctors): Split out from...
	(finish_file): ...here.

From-SVN: r19904
parent 2a321561
Wed May 20 02:16:01 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (start_objects, finish_objects, do_dtors,
do_ctors): Split out from...
(finish_file): ...here.
Tue May 19 20:36:23 1998 Jason Merrill <jason@yorick.cygnus.com> Tue May 19 20:36:23 1998 Jason Merrill <jason@yorick.cygnus.com>
* tree.c (is_overloaded_fn): Don't abort on placeholders from * tree.c (is_overloaded_fn): Don't abort on placeholders from
...@@ -65,10 +71,6 @@ Tue May 19 02:43:25 1998 Jason Merrill <jason@yorick.cygnus.com> ...@@ -65,10 +71,6 @@ Tue May 19 02:43:25 1998 Jason Merrill <jason@yorick.cygnus.com>
Mon May 18 23:22:52 1998 Jason Merrill <jason@yorick.cygnus.com> Mon May 18 23:22:52 1998 Jason Merrill <jason@yorick.cygnus.com>
* decl2.c (setup_initp, start_objects, finish_objects): New fns.
(do_dtors, do_ctors): Split out from...
(finish_file): ...here. Support init_priority.
* decl2.c (get_sentry): Use end_temporary_allocation. * decl2.c (get_sentry): Use end_temporary_allocation.
Don't declare permanent_obstack. Don't declare permanent_obstack.
...@@ -9610,10 +9612,3 @@ Wed Oct 11 16:30:34 1995 Brendan Kehoe <brendan@lisa.cygnus.com> ...@@ -9610,10 +9612,3 @@ Wed Oct 11 16:30:34 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
* parse.y (fn.def1): Call split_specs_attrs in * parse.y (fn.def1): Call split_specs_attrs in
declmods notype_declarator case. declmods notype_declarator case.
Use a consistent time stamp format in ChangeLog entries.
Not everyone has Emacs 20 yet, so stick with Emacs 19 format for now.
Local Variables:
add-log-time-format: current-time-string
End:
...@@ -3926,12 +3926,10 @@ compare_ics (ics1, ics2) ...@@ -3926,12 +3926,10 @@ compare_ics (ics1, ics2)
if (is_subseq (ics2, ics1)) if (is_subseq (ics2, ics1))
return -1; return -1;
} }
else /* Otherwise, one sequence cannot be a subsequence of the other; they
/* One sequence cannot be a subsequence of the other; they don't don't start with the same type. This can happen when comparing the
start with the same type. This can happen when comparing the second standard conversion sequence in two user-defined conversion
second standard conversion sequence in two user-defined sequences. */
conversion sequences. */
;
/* [over.ics.rank] /* [over.ics.rank]
......
...@@ -2800,147 +2800,78 @@ get_sentry (base) ...@@ -2800,147 +2800,78 @@ get_sentry (base)
return sentry; return sentry;
} }
/* This routine is called from the last rule in yyparse (). /* Start the process of running a particular set of global constructors
Its job is to create all the code needed to initialize and or destructors. Subroutine of do_[cd]tors. */
destroy the global aggregates. We do the destruction
first, since that way we only need to reverse the decls once. */
void static void
finish_file () start_objects (method_type)
int method_type;
{ {
extern int lineno;
int start_time, this_time;
tree fnname; tree fnname;
tree vars;
int needs_cleaning = 0, needs_messing_up = 0;
at_eof = 1;
/* Bad parse errors. Just forget about it. */
if (! global_bindings_p () || current_class_type)
return;
start_time = get_run_time (); /* Make ctor or dtor function. METHOD_TYPE may be 'I' or 'D'. */
/* Otherwise, GDB can get confused, because in only knows fnname = get_file_function_name (method_type);
about source for LINENO-1 lines. */
lineno -= 1;
interface_unknown = 1; start_function (void_list_node,
interface_only = 0; make_call_declarator (fnname, void_list_node, NULL_TREE,
NULL_TREE),
for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname)) NULL_TREE, 0);
{
tree decl = TREE_VALUE (fnname);
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
{
instantiate_class_template (decl);
if (CLASSTYPE_TEMPLATE_INSTANTIATION (decl))
for (vars = TYPE_METHODS (decl); vars; vars = TREE_CHAIN (vars))
if (! DECL_ARTIFICIAL (vars))
instantiate_decl (vars);
}
else
instantiate_decl (decl);
}
for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
{
tree args, fn, decl = TREE_VALUE (fnname);
if (DECL_INITIAL (decl))
continue;
fn = TREE_PURPOSE (fnname);
args = get_bindings (fn, decl, NULL_TREE);
fn = instantiate_template (fn, args);
instantiate_decl (fn);
}
cat_namespace_levels();
/* Push into C language context, because that's all store_parm_decls ();
we'll need here. */ pushlevel (0);
push_lang_context (lang_name_c); clear_last_expr ();
push_momentary ();
expand_start_bindings (0);
}
#if 1 /* Finish the process of running a particular set of global constructors
/* The reason for pushing garbage onto the global_binding_level is to or destructors. Subroutine of do_[cd]tors. */
ensure that we can slice out _DECLs which pertain to virtual function
tables. If the last thing pushed onto the global_binding_level was a
virtual function table, then slicing it out would slice away all the
decls (i.e., we lose the head of the chain).
There are several ways of getting the same effect, from changing the static void
way that iterators over the chain treat the elements that pertain to finish_objects (method_type)
virtual function tables, moving the implementation of this code to int method_type;
decl.c (where we can manipulate global_binding_level directly), {
popping the garbage after pushing it and slicing away the vtable char *fnname;
stuff, or just leaving it alone. */
/* Make last thing in global scope not be a virtual function table. */ tree list = (method_type == 'I' ? static_ctors : static_dtors);
#if 0 /* not yet, should get fixed properly later */
vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
#else
vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
#endif
DECL_IGNORED_P (vars) = 1;
SET_DECL_ARTIFICIAL (vars);
pushdecl (vars);
#endif
/* Walk to mark the inline functions we need, then output them so if (! current_function_decl && list)
that we can pick up any other tdecls that those routines need. */ start_objects (method_type);
walk_vtables ((void (*) PROTO ((tree, tree))) 0,
finish_prevtable_vardecl);
for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars)) for (; list; list = TREE_CHAIN (list))
if (! TREE_ASM_WRITTEN (TREE_VALUE (vars))) expand_expr_stmt (build_function_call (TREE_VALUE (list), NULL_TREE));
rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
vars = static_aggregates;
if (static_ctors || vars) if (! current_function_decl)
needs_messing_up = 1; return;
if (static_dtors)
needs_cleaning = 1;
/* See if we really need the hassle. */ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
while (vars && needs_cleaning == 0)
{
tree decl = TREE_VALUE (vars);
tree type = TREE_TYPE (decl);
if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars))
{
needs_cleaning = 1;
break;
}
vars = TREE_CHAIN (vars); /* Finish up. */
} expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 0, 0);
pop_momentary ();
finish_function (lineno, 0, 0);
if (needs_cleaning == 0) if (method_type == 'I')
goto mess_up; assemble_constructor (fnname);
else
assemble_destructor (fnname);
}
fnname = get_file_function_name ('D'); /* Generate a function to run a set of global destructors. Subroutine of
start_function (void_list_node, finish_file. */
make_call_declarator (fnname, void_list_node, NULL_TREE,
NULL_TREE),
NULL_TREE, 0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls ();
pushlevel (0); static void
clear_last_expr (); do_dtors ()
push_momentary (); {
expand_start_bindings (0); tree vars = static_aggregates;
/* These must be done in backward order to destroy, for (; vars; vars = TREE_CHAIN (vars))
in which they happen to be! */
for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars))
{ {
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
tree temp = TREE_PURPOSE (vars); tree temp;
if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars) if (TYPE_NEEDS_DESTRUCTOR (type) && ! TREE_STATIC (vars)
&& ! DECL_EXTERNAL (decl)) && ! DECL_EXTERNAL (decl))
...@@ -2949,6 +2880,9 @@ finish_file () ...@@ -2949,6 +2880,9 @@ finish_file ()
|| DECL_ONE_ONLY (decl) || DECL_ONE_ONLY (decl)
|| DECL_WEAK (decl))); || DECL_WEAK (decl)));
if (! current_function_decl)
start_objects ('D');
temp = build_cleanup (decl); temp = build_cleanup (decl);
if (protect) if (protect)
...@@ -2966,39 +2900,21 @@ finish_file () ...@@ -2966,39 +2900,21 @@ finish_file ()
} }
} }
for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors)) finish_objects ('D');
expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors), }
NULL_TREE));
expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 0, 0);
pop_momentary ();
finish_function (lineno, 0, 0);
assemble_destructor (IDENTIFIER_POINTER (fnname));
/* If it needed cleaning, then it will need messing up: drop through. */ /* Generate a function to run a set of global constructors. Subroutine of
finish_file. */
mess_up: static void
/* Must do this while we think we are at the top level. */ do_ctors ()
vars = nreverse (static_aggregates); {
if (needs_messing_up) tree vars = static_aggregates;
{
fnname = get_file_function_name ('I');
start_function (void_list_node,
make_call_declarator (fnname, void_list_node, NULL_TREE,
NULL_TREE),
NULL_TREE, 0);
fnname = DECL_ASSEMBLER_NAME (current_function_decl);
store_parm_decls ();
pushlevel (0); /* Reverse the list so it's in the right order for ctors. */
clear_last_expr (); vars = nreverse (vars);
push_momentary ();
expand_start_bindings (0);
while (vars) for (; vars; vars = TREE_CHAIN (vars))
{ {
tree decl = TREE_VALUE (vars); tree decl = TREE_VALUE (vars);
tree init = TREE_PURPOSE (vars); tree init = TREE_PURPOSE (vars);
...@@ -3010,7 +2926,7 @@ finish_file () ...@@ -3010,7 +2926,7 @@ finish_file ()
|| DECL_EXTERNAL (decl) || DECL_EXTERNAL (decl)
|| (init && TREE_CODE (init) == TREE_LIST || (init && TREE_CODE (init) == TREE_LIST
&& value_member (error_mark_node, init))) && value_member (error_mark_node, init)))
goto next_mess; continue;
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
{ {
...@@ -3018,6 +2934,9 @@ finish_file () ...@@ -3018,6 +2934,9 @@ finish_file ()
|| DECL_ONE_ONLY (decl) || DECL_ONE_ONLY (decl)
|| DECL_WEAK (decl))); || DECL_WEAK (decl)));
if (! current_function_decl)
start_objects ('I');
/* Set these global variables so that GDB at least puts /* Set these global variables so that GDB at least puts
us near the declaration which required the initialization. */ us near the declaration which required the initialization. */
input_filename = DECL_SOURCE_FILE (decl); input_filename = DECL_SOURCE_FILE (decl);
...@@ -3071,23 +2990,128 @@ finish_file () ...@@ -3071,23 +2990,128 @@ finish_file ()
DECL_STATIC_FUNCTION_P (current_function_decl) = 0; DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
} }
else if (decl == error_mark_node) else if (decl == error_mark_node)
; /* OK */;
else my_friendly_abort (22); else
my_friendly_abort (22);
}
finish_objects ('I');
}
next_mess: /* This routine is called from the last rule in yyparse ().
vars = TREE_CHAIN (vars); Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
first, since that way we only need to reverse the decls once. */
void
finish_file ()
{
extern int lineno;
int start_time, this_time;
tree fnname;
tree vars;
int needs_cleaning = 0, needs_messing_up = 0;
at_eof = 1;
/* Bad parse errors. Just forget about it. */
if (! global_bindings_p () || current_class_type)
return;
start_time = get_run_time ();
/* Otherwise, GDB can get confused, because in only knows
about source for LINENO-1 lines. */
lineno -= 1;
interface_unknown = 1;
interface_only = 0;
for (fnname = pending_templates; fnname; fnname = TREE_CHAIN (fnname))
{
tree decl = TREE_VALUE (fnname);
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
{
instantiate_class_template (decl);
if (CLASSTYPE_TEMPLATE_INSTANTIATION (decl))
for (vars = TYPE_METHODS (decl); vars; vars = TREE_CHAIN (vars))
if (! DECL_ARTIFICIAL (vars))
instantiate_decl (vars);
}
else
instantiate_decl (decl);
} }
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors)) for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors), {
NULL_TREE)); tree args, fn, decl = TREE_VALUE (fnname);
expand_end_bindings (getdecls (), 1, 0); if (DECL_INITIAL (decl))
poplevel (1, 0, 0); continue;
pop_momentary ();
finish_function (lineno, 0, 0); fn = TREE_PURPOSE (fnname);
assemble_constructor (IDENTIFIER_POINTER (fnname)); args = get_bindings (fn, decl, NULL_TREE);
fn = instantiate_template (fn, args);
instantiate_decl (fn);
}
cat_namespace_levels();
/* Push into C language context, because that's all
we'll need here. */
push_lang_context (lang_name_c);
#if 1
/* The reason for pushing garbage onto the global_binding_level is to
ensure that we can slice out _DECLs which pertain to virtual function
tables. If the last thing pushed onto the global_binding_level was a
virtual function table, then slicing it out would slice away all the
decls (i.e., we lose the head of the chain).
There are several ways of getting the same effect, from changing the
way that iterators over the chain treat the elements that pertain to
virtual function tables, moving the implementation of this code to
decl.c (where we can manipulate global_binding_level directly),
popping the garbage after pushing it and slicing away the vtable
stuff, or just leaving it alone. */
/* Make last thing in global scope not be a virtual function table. */
#if 0 /* not yet, should get fixed properly later */
vars = make_type_decl (get_identifier (" @%$#@!"), integer_type_node);
#else
vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node);
#endif
DECL_IGNORED_P (vars) = 1;
SET_DECL_ARTIFICIAL (vars);
pushdecl (vars);
#endif
/* Walk to mark the inline functions we need, then output them so
that we can pick up any other tdecls that those routines need. */
walk_vtables ((void (*) PROTO ((tree, tree))) 0,
finish_prevtable_vardecl);
for (vars = static_aggregates; vars; vars = TREE_CHAIN (vars))
if (! TREE_ASM_WRITTEN (TREE_VALUE (vars)))
rest_of_decl_compilation (TREE_VALUE (vars), 0, 1, 1);
vars = static_aggregates;
if (static_ctors || vars)
needs_messing_up = 1;
if (static_dtors || vars)
needs_cleaning = 1;
/* The aggregates are listed in reverse declaration order, for cleaning. */
if (needs_cleaning)
{
do_dtors ();
}
/* do_ctors will reverse the lists for messing up. */
if (needs_messing_up)
{
do_ctors ();
} }
permanent_allocation (1); permanent_allocation (1);
......
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