mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-31 12:44:53 +08:00
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:
parent
ad6b1795b1
commit
cdd2559cec
@ -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.
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user