From: Jason Merrill Date: Thu, 17 Jan 2002 13:07:27 +0000 (-0500) Subject: decl.c (begin_constructor_body, [...]): New fns. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cdd2559cec98c587afc243a2850a329861487013;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 793af6d5367..abb6417663c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,4 +1,15 @@ -2002-01-16 Jason Merrill +2002-01-17 Jason Merrill + + * 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 88b4cdbfd50..99f7bf71b74 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ed163fdece7..2a4eaeacb43 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index f159f446e36..3aaedafdd93 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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 diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 288b897c4b7..8cb30a81de7 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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 diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 64f3dc1a31e..31fc850d601 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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); } ; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e75b153e0a7..0f0d93bbdfc 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b8a09fd899a..eade7004f2f 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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. */