* 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
-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.
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;
#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. */
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));
}
}
+/* 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. */
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. */
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;
}
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);
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
}
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);
}
}
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
nodecls:
/* empty */
{
- setup_vtbl_ptr (NULL_TREE, NULL_TREE);
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
+ finish_mem_initializers (NULL_TREE);
}
;
= 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;
}
}
}
- 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. */