decl.c (begin_constructor_body, [...]): New fns.

* decl.c (begin_constructor_body, begin_destructor_body): New fns.
        (begin_function_body): Call them and keep_next_level.
        * init.c (emit_base_init): Call keep_next_level.
        * semantics.c (setup_vtbl_ptr): Lose.
        * cp-tree.h (struct cp_language_function): Remove vtbls_set_up_p.
        (vtbls_set_up_p): Lose.
        * pt.c (tsubst_expr, CTOR_INITIALIZER): Call emit_base_init.
        * method.c (do_build_copy_constructor): Likewise.
        (synthesize_method): Call finish_mem_initializers.
        * parse.y (nodecls): Likewise.

From-SVN: r48948
This commit is contained in:
Jason Merrill 2002-01-17 08:07:27 -05:00 committed by Jason Merrill
parent ad6b1795b1
commit cdd2559cec
8 changed files with 106 additions and 96 deletions

View File

@ -1,4 +1,15 @@
2002-01-16 Jason Merrill <jason@redhat.com>
2002-01-17 Jason Merrill <jason@redhat.com>
* decl.c (begin_constructor_body, begin_destructor_body): New fns.
(begin_function_body): Call them and keep_next_level.
* init.c (emit_base_init): Call keep_next_level.
* semantics.c (setup_vtbl_ptr): Lose.
* cp-tree.h (struct cp_language_function): Remove vtbls_set_up_p.
(vtbls_set_up_p): Lose.
* pt.c (tsubst_expr, CTOR_INITIALIZER): Call emit_base_init.
* method.c (do_build_copy_constructor): Likewise.
(synthesize_method): Call finish_mem_initializers.
* parse.y (nodecls): Likewise.
* error.c (dump_type_suffix): Print the exception specs before
recursing.

View File

@ -821,7 +821,6 @@ struct cp_language_function
int returns_null;
int in_function_try_handler;
int x_expanding_p;
int vtbls_set_up_p;
struct named_label_use_list *x_named_label_uses;
struct named_label_list *x_named_labels;
@ -881,11 +880,6 @@ struct cp_language_function
#define current_function_returns_null cp_function_chain->returns_null
/* Nonzero if we have already generated code to initialize virtual
function tables in this function. */
#define vtbls_set_up_p cp_function_chain->vtbls_set_up_p
/* Non-zero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without
interacting with the back end. */

View File

@ -133,7 +133,9 @@ static void mark_lang_function PARAMS ((struct cp_language_function *));
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
static void destroy_local_var PARAMS ((tree));
static void begin_constructor_body PARAMS ((void));
static void finish_constructor_body PARAMS ((void));
static void begin_destructor_body PARAMS ((void));
static void finish_destructor_body PARAMS ((void));
static tree create_array_type_for_decl PARAMS ((tree, tree, tree));
static tree get_atexit_node PARAMS ((void));
@ -13931,6 +13933,18 @@ save_function_data (decl)
}
}
/* Add a note to mark the beginning of the main body of the constructor.
This is used to set up the data structures for the cleanup regions for
fully-constructed bases and members. */
static void
begin_constructor_body ()
{
tree ctor_stmt = build_stmt (CTOR_STMT);
CTOR_BEGIN_P (ctor_stmt) = 1;
add_stmt (ctor_stmt);
}
/* Add a note to mark the end of the main body of the constructor. This is
used to end the cleanup regions for fully-constructed bases and
members. */
@ -13946,6 +13960,54 @@ finish_constructor_body ()
add_stmt (build_stmt (CTOR_STMT));
}
/* Do all the processing for the beginning of a destructor; set up the
vtable pointers and cleanups for bases and members. */
static void
begin_destructor_body ()
{
tree if_stmt;
tree compound_stmt;
/* If the dtor is empty, and we know there is not any possible
way we could use any vtable entries, before they are possibly
set by a base class dtor, we don't have to setup the vtables,
as we know that any base class dtor will set up any vtables
it needs. We avoid MI, because one base class dtor can do a
virtual dispatch to an overridden function that would need to
have a non-related vtable set up, we cannot avoid setting up
vtables in that case. We could change this to see if there
is just one vtable.
??? In the destructor for a class, the vtables are set
appropriately for that class. There will be no non-related
vtables. jason 2001-12-11. */
if_stmt = begin_if_stmt ();
/* If it is not safe to avoid setting up the vtables, then
someone will change the condition to be boolean_true_node.
(Actually, for now, we do not have code to set the condition
appropriately, so we just assume that we always need to
initialize the vtables.) */
finish_if_stmt_cond (boolean_true_node, if_stmt);
current_vcalls_possible_p = &IF_COND (if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
tables. */
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
push_base_cleanups ();
}
/* At the end of every destructor we generate code to delete the object if
necessary. Do that now. */
@ -13990,8 +14052,23 @@ finish_destructor_body ()
tree
begin_function_body ()
{
tree stmt = begin_compound_stmt (0);
tree stmt;
stmt = begin_compound_stmt (0);
COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
if (processing_template_decl)
/* Do nothing now. */;
else if (DECL_CONSTRUCTOR_P (current_function_decl))
begin_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
begin_destructor_body ();
/* Always keep the BLOCK node associated with the outermost pair of
curly braces of a function. These are needed for correct
operation of dwarfout.c. */
keep_next_level (1);
return stmt;
}

View File

@ -668,6 +668,11 @@ emit_base_init (mem_init_list, base_init_list)
int i;
int n_baseclasses = BINFO_N_BASETYPES (t_binfo);
/* We did a keep_next_level (1) in begin_function_body. We don't want
that to apply to any blocks generated for member initializers, so
clear it out. */
keep_next_level (0);
mem_init_list = sort_member_init (t, mem_init_list);
sort_base_init (t, base_init_list, &rbase_init_list, &vbase_init_list);
@ -748,6 +753,9 @@ emit_base_init (mem_init_list, base_init_list)
perform_member_init (member, init, from_init_list);
mem_init_list = TREE_CHAIN (mem_init_list);
}
/* And restore it. */
keep_next_level (1);
}
/* Returns the address of the vtable (i.e., the value that should be

View File

@ -624,7 +624,7 @@ do_build_copy_constructor (fndecl)
}
member_init_list = nreverse (member_init_list);
base_init_list = nreverse (base_init_list);
setup_vtbl_ptr (member_init_list, base_init_list);
emit_base_init (member_init_list, base_init_list);
}
}
@ -770,15 +770,13 @@ synthesize_method (fndecl)
do_build_assign_ref (fndecl);
need_body = 0;
}
else if (DECL_DESTRUCTOR_P (fndecl))
setup_vtbl_ptr (NULL_TREE, NULL_TREE);
else
else if (DECL_CONSTRUCTOR_P (fndecl))
{
tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
setup_vtbl_ptr (NULL_TREE, NULL_TREE);
finish_mem_initializers (NULL_TREE);
}
/* If we haven't yet generated the body of the function, just

View File

@ -1765,7 +1765,8 @@ string:
nodecls:
/* empty */
{
setup_vtbl_ptr (NULL_TREE, NULL_TREE);
if (DECL_CONSTRUCTOR_P (current_function_decl))
finish_mem_initializers (NULL_TREE);
}
;

View File

@ -7274,7 +7274,7 @@ tsubst_expr (t, args, complain, in_decl)
= tsubst_initializer_list (TREE_OPERAND (t, 0), args);
base_init_list
= tsubst_initializer_list (TREE_OPERAND (t, 1), args);
setup_vtbl_ptr (member_init_list, base_init_list);
emit_base_init (member_init_list, base_init_list);
break;
}

View File

@ -1141,90 +1141,11 @@ finish_mem_initializers (init_list)
}
}
setup_vtbl_ptr (member_init_list, base_init_list);
}
/* Do the initialization work necessary at the beginning of a constructor
or destructor. This means processing member initializers and setting
vtable pointers.
??? The call to keep_next_level at the end applies to all functions, but
should probably go somewhere else. */
void
setup_vtbl_ptr (member_init_list, base_init_list)
tree member_init_list;
tree base_init_list;
{
my_friendly_assert (doing_semantic_analysis_p (), 19990919);
my_friendly_assert (!vtbls_set_up_p, 20011220);
if (processing_template_decl)
add_stmt (build_min_nt (CTOR_INITIALIZER,
member_init_list, base_init_list));
else if (DECL_CONSTRUCTOR_P (current_function_decl))
{
tree ctor_stmt;
/* Mark the beginning of the constructor. */
ctor_stmt = build_stmt (CTOR_STMT);
CTOR_BEGIN_P (ctor_stmt) = 1;
add_stmt (ctor_stmt);
/* And actually initialize the base-classes and members. */
emit_base_init (member_init_list, base_init_list);
}
else if (DECL_DESTRUCTOR_P (current_function_decl))
{
tree if_stmt;
tree compound_stmt;
/* If the dtor is empty, and we know there is not any possible
way we could use any vtable entries, before they are possibly
set by a base class dtor, we don't have to setup the vtables,
as we know that any base class dtor will set up any vtables
it needs. We avoid MI, because one base class dtor can do a
virtual dispatch to an overridden function that would need to
have a non-related vtable set up, we cannot avoid setting up
vtables in that case. We could change this to see if there
is just one vtable.
??? In the destructor for a class, the vtables are set
appropriately for that class. There will be no non-related
vtables. jason 2001-12-11. */
if_stmt = begin_if_stmt ();
/* If it is not safe to avoid setting up the vtables, then
someone will change the condition to be boolean_true_node.
(Actually, for now, we do not have code to set the condition
appropriately, so we just assume that we always need to
initialize the vtables.) */
finish_if_stmt_cond (boolean_true_node, if_stmt);
current_vcalls_possible_p = &IF_COND (if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
tables. */
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
push_base_cleanups ();
}
/* Always keep the BLOCK node associated with the outermost pair of
curly braces of a function. These are needed for correct
operation of dwarfout.c. */
keep_next_level (1);
/* The virtual function tables are set up now. */
vtbls_set_up_p = 1;
else
emit_base_init (member_init_list, base_init_list);
}
/* Returns the stack of SCOPE_STMTs for the current function. */