diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c-common.h | 5 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 5 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/decl.c | 170 | ||||
-rw-r--r-- | gcc/cp/init.c | 135 | ||||
-rw-r--r-- | gcc/cp/method.c | 3 | ||||
-rw-r--r-- | gcc/cp/parse.y | 55 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 7 |
12 files changed, 231 insertions, 201 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53e29eb..7dc7c8a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2001-12-13 Jason Merrill <jason@redhat.com> + + * c-common.h (COMPOUND_STMT_BODY_BLOCK): New macro. + 2001-12-13 Aldy Hernandez <aldyh@redhat.com> * config/rs6000/rs6000.md (eh_set_lr_di): Change scratch @@ -20,10 +24,10 @@ Thu Dec 13 20:30:08 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> 2001-12-12 Aldy Hernandez <aldyh@redhat.com> - * config/rs6000/rs6000.c (rs6000_override_options): Add - SUBSUBTARGET_OVERRIDE_OPTIONS. + * config/rs6000/rs6000.c (rs6000_override_options): Add + SUBSUBTARGET_OVERRIDE_OPTIONS. - * config/rs6000/eabialtivec.h: New file. + * config/rs6000/eabialtivec.h: New file. * config/rs6000/linuxaltivec.h: New file. diff --git a/gcc/c-common.h b/gcc/c-common.h index 5ce8923..f6e6290 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA STMT_IS_FULL_EXPR_P (in _STMT) 2: STMT_LINENO_FOR_FN_P (in _STMT) 3: SCOPE_NO_CLEANUPS_P (in SCOPE_STMT) + COMPOUND_STMT_BODY_BLOCK (in COMPOUND_STMT) 4: SCOPE_PARTIAL_P (in SCOPE_STMT) */ @@ -762,6 +763,10 @@ extern tree build_return_stmt PARAMS ((tree)); #define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE) +/* Used by the C++ frontend to mark the block around the member + initializers and cleanups. */ +#define COMPOUND_STMT_BODY_BLOCK(NODE) TREE_LANG_FLAG_3 (NODE) + extern void c_expand_asm_operands PARAMS ((tree, tree, tree, tree, int, const char *, int)); /* These functions must be defined by each front-end which implements diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1e70a56..d033251 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,28 @@ 2001-12-13 Jason Merrill <jason@redhat.com> + * Make-lang.in (parse.h): Separate rule, just depend on parse.c. + + Use cleanups to run base and member destructors. + * init.c (push_base_cleanups): New function, split out from... + (build_delete): ...here. Lose !TYPE_HAS_DESTRUCTOR code. + * decl.c (finish_destructor_body): Move vbase destruction code to + push_base_cleanups. + (begin_function_body, finish_function_body): New fns. + (finish_function): Move [cd]tor handling and call_poplevel to + finish_function_body. + (pushdecl): Skip the new level. + * semantics.c (genrtl_try_block): Don't call end_protect_partials. + (setup_vtbl_ptr): Call push_base_cleanups. + * method.c (synthesize_method): Call {begin,end}_function_body. + * pt.c (tsubst_expr): Handle COMPOUND_STMT_BODY_BLOCK. + * cp-tree.h: Declare new fns. + * parse.y (function_body, .begin_function_body): New nonterminals. + (fndef, pending_inline, function_try_block): Use function_body. + (ctor_initializer_opt, function_try_block): No longer has a value. + (base_init): Remove .set_base_init token. + (.set_base_init, compstmt_or_error): Remove. + * Make-lang.in (parse.c): Expect two fewer s/r conflicts. + * optimize.c (maybe_clone_body): Fix parameter updating. 2001-12-12 Jason Merrill <jason@redhat.com> diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index eb42dec..d848e3a 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -118,8 +118,9 @@ $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' \ $(srcdir)/cp/cfns.gperf > $(srcdir)/cp/cfns.h -$(srcdir)/cp/parse.h $(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y - @echo "Expect 36 shift/reduce conflicts and 58 reduce/reduce conflicts." +$(srcdir)/cp/parse.h: $(srcdir)/cp/parse.c +$(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y + @echo "Expect 34 shift/reduce conflicts and 58 reduce/reduce conflicts." cd $(srcdir)/cp; $(BISON) $(BISONFLAGS) -d -o p$$$$.c parse.y ; \ grep '^#define[ ]*YYEMPTY' p$$$$.c >> p$$$$.h ; \ mv -f p$$$$.c parse.c ; mv -f p$$$$.h parse.h diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 1395301..dbe990a 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -234,6 +234,8 @@ DEFTREECODE (CTOR_STMT, "ctor_stmt", 'e', 0) constructed. If, after this point, the CLEANUP_DECL goes out of scope, the CLEANUP_EXPR must be run. */ DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 2) +/* CTOR_INITIALIZER is a placeholder in template code for a call to + setup_vtbl_pointer (and appears in all functions, not just ctors). */ DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2) DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b68e0ba..70b5110 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3677,6 +3677,8 @@ extern tree start_enum PARAMS ((tree)); extern void finish_enum PARAMS ((tree)); extern void build_enumerator PARAMS ((tree, tree, tree)); extern int start_function PARAMS ((tree, tree, tree, int)); +extern tree begin_function_body PARAMS ((void)); +extern void finish_function_body PARAMS ((tree)); extern tree finish_function PARAMS ((int)); extern tree start_method PARAMS ((tree, tree, tree)); extern tree finish_method PARAMS ((tree)); @@ -3849,6 +3851,7 @@ extern tree build_new PARAMS ((tree, tree, tree, int)); extern tree build_vec_init PARAMS ((tree, tree, int)); extern tree build_x_delete PARAMS ((tree, int, tree)); extern tree build_delete PARAMS ((tree, tree, special_function_kind, int, int)); +extern void push_base_cleanups PARAMS ((void)); extern tree build_vbase_delete PARAMS ((tree, tree)); extern tree build_vec_delete PARAMS ((tree, tree, special_function_kind, int)); extern tree create_temporary_var PARAMS ((tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7e9692d..c997535 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4188,8 +4188,8 @@ pushdecl (x) them there. */ struct binding_level *b = current_binding_level->level_chain; - if (cleanup_label) - b = b->level_chain; + /* Skip the ctor/dtor cleanup level. */ + b = b->level_chain; /* ARM $8.3 */ if (b->parm_flag == 1) @@ -13920,106 +13920,29 @@ save_function_data (decl) } } -/* At the end of every constructor we generate to code to return - `this'. Do that now. */ +/* 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. */ static void finish_constructor_body () { - /* Mark the end of the constructor. */ + /* Mark the end of the cleanups for a partially constructed object. + + ??? These should really be handled automatically by closing the block, + as with the destructor cleanups; the only difference is that these are + only run if an exception is thrown. */ add_stmt (build_stmt (CTOR_STMT)); } -/* At the end of every destructor we generate code to restore virtual - function tables to the values desired by base classes and to call - to base class destructors. Do that now. */ +/* At the end of every destructor we generate code to delete the object if + necessary. Do that now. */ static void finish_destructor_body () { - tree compound_stmt; tree exprstmt; - /* Create a block to contain all the extra code. */ - compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); - - /* Any return from a destructor will end up here. */ - add_stmt (build_stmt (LABEL_STMT, dtor_label)); - - /* Generate the code to call destructor on base class. If this - destructor belongs to a class with virtual functions, then set - the virtual function table pointer to represent the type of our - base class. */ - - /* This side-effect makes call to `build_delete' generate the code - we have to have at the end of this destructor. `build_delete' - will set the flag again. */ - TYPE_HAS_DESTRUCTOR (current_class_type) = 0; - - exprstmt = build_delete (current_class_type, - current_class_ref, - sfk_base_destructor, - LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, - 0); - - if (exprstmt != error_mark_node - && (TREE_CODE (exprstmt) != NOP_EXPR - || TREE_OPERAND (exprstmt, 0) != integer_zero_node - || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))) - { - if (exprstmt != void_zero_node) - /* Don't call `expand_expr_stmt' if we're not going to do - anything, since -Wall will give a diagnostic. */ - finish_expr_stmt (exprstmt); - - /* Run destructors for all virtual baseclasses. */ - if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) - { - tree vbases; - tree if_stmt; - - if_stmt = begin_if_stmt (); - finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node, - current_in_charge_parm, - integer_two_node), - if_stmt); - - vbases = CLASSTYPE_VBASECLASSES (current_class_type); - /* The CLASSTYPE_VBASECLASSES list is in initialization - order, so we have to march through it in reverse order. */ - for (vbases = nreverse (copy_list (vbases)); - vbases; - vbases = TREE_CHAIN (vbases)) - { - tree vbase = TREE_VALUE (vbases); - tree base_type = BINFO_TYPE (vbase); - - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type)) - { - tree base_ptr_type = build_pointer_type (base_type); - tree expr = current_class_ptr; - - /* Convert to the basetype here, as we know the layout is - fixed. What is more, if we let build_method_call do it, - it will use the vtable, which may have been clobbered - by the deletion of our primary base. */ - - expr = build1 (NOP_EXPR, base_ptr_type, expr); - expr = build (PLUS_EXPR, base_ptr_type, expr, - BINFO_OFFSET (vbase)); - expr = build_indirect_ref (expr, NULL); - expr = build_method_call (expr, base_dtor_identifier, - NULL_TREE, vbase, - LOOKUP_NORMAL); - finish_expr_stmt (expr); - } - } - - finish_then_clause (if_stmt); - finish_if_stmt (); - } - } - /* In a virtual destructor, we must call delete. */ if (DECL_VIRTUAL_P (current_function_decl)) { @@ -14028,10 +13951,10 @@ finish_destructor_body () /* [class.dtor] - At the point of definition of a virtual destructor (including - an implicit definition), non-placement operator delete shall - be looked up in the scope of the destructor's class and if - found shall be accessible and unambiguous. */ + At the point of definition of a virtual destructor (including + an implicit definition), non-placement operator delete shall + be looked up in the scope of the destructor's class and if + found shall be accessible and unambiguous. */ exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, virtual_size, LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); @@ -14045,20 +13968,58 @@ finish_destructor_body () finish_then_clause (if_stmt); finish_if_stmt (); } +} - /* Close the block we started above. */ - finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); +/* Do the necessary processing for the beginning of a function body, which + in this case includes member-initializers, but not the catch clauses of + a function-try-block. Currently, this means opening a binding level + for the member-initializers (in a ctor) and member cleanups (in a dtor). + In other functions, this isn't necessary, but it doesn't hurt. */ + +tree +begin_function_body () +{ + tree stmt = begin_compound_stmt (0); + COMPOUND_STMT_BODY_BLOCK (stmt) = 1; + return stmt; } +/* Do the processing for the end of a function body. Currently, this means + closing out the cleanups for fully-constructed bases and members, and in + the case of the destructor, deleting the object if desired. Again, this + is only meaningful for [cd]tors, since they are the only functions where + there is a significant distinction between the main body and any + function catch clauses. Handling, say, main() return semantics here + would be wrong, as flowing off the end of a function catch clause for + main() would also need to return 0. */ + +void +finish_function_body (compstmt) + tree compstmt; +{ + if (processing_template_decl) + /* Do nothing now. */; + else if (DECL_DESTRUCTOR_P (current_function_decl)) + /* Any return from a destructor will end up here. Put it before the + cleanups so that an explicit return doesn't duplicate them. */ + add_stmt (build_stmt (LABEL_STMT, dtor_label)); + + /* Close the block; in a destructor, run the member cleanups. */ + finish_compound_stmt (0, compstmt); + + if (processing_template_decl) + /* Do nothing now. */; + else if (DECL_CONSTRUCTOR_P (current_function_decl)) + finish_constructor_body (); + else if (DECL_DESTRUCTOR_P (current_function_decl)) + finish_destructor_body (); +} + /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage for the function definition. FLAGS is a bitwise or of the following values: - 1 - CALL_POPLEVEL - An extra call to poplevel (and expand_end_bindings) must be - made to take care of the binding contour for the base - initializers. This is only relevant for constructors. 2 - INCLASS_INLINE We just finished processing the body of an in-class inline function definition. (This processing will have taken place @@ -14070,7 +14031,6 @@ finish_function (flags) { register tree fndecl = current_function_decl; tree fntype, ctype = NULL_TREE; - int call_poplevel = (flags & 1) != 0; int inclass_inline = (flags & 2) != 0; int nested; @@ -14094,15 +14054,7 @@ finish_function (flags) there's no need to add any extra bits. */ if (!DECL_CLONED_FUNCTION_P (fndecl)) { - if (DECL_CONSTRUCTOR_P (fndecl)) - { - finish_constructor_body (); - if (call_poplevel) - do_poplevel (); - } - else if (DECL_DESTRUCTOR_P (fndecl) && !processing_template_decl) - finish_destructor_body (); - else if (DECL_MAIN_P (fndecl)) + if (DECL_MAIN_P (current_function_decl)) { /* Make it so that `main' always returns 0 by default. */ #ifdef VMS_TARGET diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 098697f..c0cc3f3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3078,9 +3078,7 @@ build_dtor_call (exp, dtor_kind, flags) sfk_deleting_destructor. FLAGS is the logical disjunction of zero or more LOOKUP_ - flags. See cp-tree.h for more info. - - This function does not delete an object's virtual base classes. */ + flags. See cp-tree.h for more info. */ tree build_delete (type, addr, auto_delete, flags, use_global_delete) @@ -3089,7 +3087,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) int flags; int use_global_delete; { - tree member; tree expr; if (addr == error_mark_node) @@ -3157,15 +3154,13 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL), NULL_TREE); } - - /* Below, we will reverse the order in which these calls are made. - If we have a destructor, then that destructor will take care - of the base classes; otherwise, we must do that here. */ - if (TYPE_HAS_DESTRUCTOR (type)) + else { tree do_delete = NULL_TREE; tree ifexp; + my_friendly_assert (TYPE_HAS_DESTRUCTOR (type), 20011213); + /* For `::delete x', we must not use the deleting destructor since then we would not be sure to get the global `operator delete'. */ @@ -3215,56 +3210,98 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) return expr; } - else - { - /* We only get here from finish_function for a destructor. */ - tree binfos = BINFO_BASETYPES (TYPE_BINFO (type)); - int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type); - tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE; - tree exprstmt = NULL_TREE; - tree ref = build_indirect_ref (addr, NULL); +} - /* Set this again before we call anything, as we might get called - recursively. */ - TYPE_HAS_DESTRUCTOR (type) = 1; +/* At the beginning of a destructor, push cleanups that will call the + destructors for our base classes and members. - /* If we have member delete or vbases, we call delete in - finish_function. */ - my_friendly_assert (auto_delete == sfk_base_destructor, 20000411); + Called from setup_vtbl_ptr. */ - /* Take care of the remaining baseclasses. */ - for (i = 0; i < n_baseclasses; i++) - { - base_binfo = TREE_VEC_ELT (binfos, i); - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)) - || TREE_VIA_VIRTUAL (base_binfo)) - continue; - - expr = build_scoped_method_call (ref, base_binfo, - base_dtor_identifier, - NULL_TREE); +void +push_base_cleanups () +{ + tree binfos; + int i, n_baseclasses; + tree member; + tree expr; - exprstmt = tree_cons (NULL_TREE, expr, exprstmt); - } + /* Run destructors for all virtual baseclasses. */ + if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) + { + tree vbases; + tree cond = (condition_conversion + (build (BIT_AND_EXPR, integer_type_node, + current_in_charge_parm, + integer_two_node))); - for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) + vbases = CLASSTYPE_VBASECLASSES (current_class_type); + /* The CLASSTYPE_VBASECLASSES list is in initialization + order, which is also the right order for pushing cleanups. */ + for (; vbases; + vbases = TREE_CHAIN (vbases)) { - if (TREE_CODE (member) != FIELD_DECL) - continue; - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member))) + tree vbase = TREE_VALUE (vbases); + tree base_type = BINFO_TYPE (vbase); + + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type)) { - tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0); - tree this_type = TREE_TYPE (member); - expr = build_delete (this_type, this_member, - sfk_complete_destructor, flags, 0); - exprstmt = tree_cons (NULL_TREE, expr, exprstmt); + tree base_ptr_type = build_pointer_type (base_type); + expr = current_class_ptr; + + /* Convert to the basetype here, as we know the layout is + fixed. What is more, if we let build_method_call do it, + it will use the vtable, which may have been clobbered + by the deletion of our primary base. */ + + expr = build1 (NOP_EXPR, base_ptr_type, expr); + expr = build (PLUS_EXPR, base_ptr_type, expr, + BINFO_OFFSET (vbase)); + expr = build_indirect_ref (expr, NULL); + expr = build_method_call (expr, base_dtor_identifier, + NULL_TREE, vbase, + LOOKUP_NORMAL); + expr = build (COND_EXPR, void_type_node, cond, + expr, void_zero_node); + finish_decl_cleanup (NULL_TREE, expr); } } + } + + binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type)); + n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type); - if (exprstmt) - return build_compound_expr (exprstmt); - /* Virtual base classes make this function do nothing. */ - return void_zero_node; + /* Take care of the remaining baseclasses. */ + for (i = 0; i < n_baseclasses; i++) + { + tree base_binfo = TREE_VEC_ELT (binfos, i); + if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)) + || TREE_VIA_VIRTUAL (base_binfo)) + continue; + + expr = build_scoped_method_call (current_class_ref, base_binfo, + base_dtor_identifier, + NULL_TREE); + + finish_decl_cleanup (NULL_TREE, expr); + } + + for (member = TYPE_FIELDS (current_class_type); member; + member = TREE_CHAIN (member)) + { + if (TREE_CODE (member) != FIELD_DECL) + continue; + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member))) + { + tree this_member = (build_component_ref + (current_class_ref, DECL_NAME (member), + NULL_TREE, 0)); + tree this_type = TREE_TYPE (member); + expr = build_delete (this_type, this_member, + sfk_complete_destructor, + LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, + 0); + finish_decl_cleanup (NULL_TREE, expr); + } } } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 0cef1e3..9dbf1e3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -727,6 +727,7 @@ synthesize_method (fndecl) int nested = (current_function_decl != NULL_TREE); tree context = decl_function_context (fndecl); int need_body = 1; + tree stmt; if (at_eof) import_export_decl (fndecl); @@ -757,6 +758,7 @@ synthesize_method (fndecl) interface_unknown = 1; start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); clear_last_expr (); + stmt = begin_function_body (); if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) { @@ -783,6 +785,7 @@ synthesize_method (fndecl) finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); } + finish_function_body (stmt); expand_body (finish_function (0)); extract_interface_info (); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 28a1456..b49f6eb 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -385,7 +385,7 @@ cp_parse_init () %token <pi> PRE_PARSED_FUNCTION_DECL %type <ttype> component_constructor_declarator %type <ttype> fn.def2 return_id constructor_declarator -%type <itype> ctor_initializer_opt function_try_block +%type <ttype> .begin_function_body %type <ttype> named_class_head_sans_basetype %type <ftype> class_head named_class_head %type <ftype> named_complex_class_head_sans_basetype @@ -747,9 +747,7 @@ datadef: ctor_initializer_opt: nodecls - { $$ = 0; } | base_init - { $$ = 1; } ; maybe_return_init: @@ -763,11 +761,18 @@ eat_saved_input: | END_OF_SAVED_INPUT ; +function_body: + .begin_function_body ctor_initializer_opt compstmt + { + finish_function_body ($1); + } + ; + fndef: - fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error - { expand_body (finish_function ((int)$3)); } + fn.def1 maybe_return_init function_body + { expand_body (finish_function (0)); } | fn.def1 maybe_return_init function_try_block - { expand_body (finish_function ((int)$3)); } + { expand_body (finish_function (0)); } | fn.def1 maybe_return_init error { } ; @@ -890,25 +895,21 @@ return_init: ; base_init: - ':' .set_base_init member_init_list + ':' member_init_list { - if ($3.new_type_flag == 0) + if (! DECL_CONSTRUCTOR_P (current_function_decl)) + error ("only constructors take base initializers"); + else if ($2.new_type_flag == 0) error ("no base or member initializers given following ':'"); - finish_mem_initializers ($3.t); + finish_mem_initializers ($2.t); } ; -.set_base_init: +.begin_function_body: /* empty */ { - if (DECL_CONSTRUCTOR_P (current_function_decl)) - /* Make a contour for the initializer list. */ - do_pushlevel (); - else if (current_class_type == NULL_TREE) - error ("base initializers not allowed for non-member functions"); - else if (! DECL_CONSTRUCTOR_P (current_function_decl)) - error ("only constructors take base initializers"); + $$ = begin_function_body (); } ; @@ -2208,14 +2209,14 @@ initlist: ; pending_inline: - PRE_PARSED_FUNCTION_DECL maybe_return_init ctor_initializer_opt compstmt_or_error + PRE_PARSED_FUNCTION_DECL maybe_return_init function_body { - expand_body (finish_function ((int)$3 | 2)); + expand_body (finish_function (2)); process_next_inline ($1); } | PRE_PARSED_FUNCTION_DECL maybe_return_init function_try_block { - expand_body (finish_function ((int)$3 | 2)); + expand_body (finish_function (2)); process_next_inline ($1); } | PRE_PARSED_FUNCTION_DECL maybe_return_init error @@ -3328,13 +3329,6 @@ label_decl: } ; -/* This is the body of a function definition. - It causes syntax errors to ignore to the next openbrace. */ -compstmt_or_error: - compstmt - | error compstmt - ; - compstmt: save_lineno '{' { $<ttype>$ = begin_compound_stmt (0); } @@ -3499,13 +3493,10 @@ simple_stmt: function_try_block: TRY { $<ttype>$ = begin_function_try_block (); } - ctor_initializer_opt compstmt + function_body { finish_function_try_block ($<ttype>2); } handler_seq - { - finish_function_handler_sequence ($<ttype>2); - $$ = $3; - } + { finish_function_handler_sequence ($<ttype>2); } ; try_block: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 48f3951..79a413b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7389,9 +7389,17 @@ tsubst_expr (t, args, complain, in_decl) case COMPOUND_STMT: { prep_stmt (t); - stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)); + if (COMPOUND_STMT_BODY_BLOCK (t)) + stmt = begin_function_body (); + else + stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)); + tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl); - finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt); + + if (COMPOUND_STMT_BODY_BLOCK (t)) + finish_function_body (stmt); + else + finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt); } break; @@ -7517,7 +7525,7 @@ tsubst_expr (t, args, complain, in_decl) case CTOR_STMT: add_stmt (copy_node (t)); break; - + default: abort (); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8dc792a..bbd43e9 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -580,7 +580,6 @@ genrtl_try_block (t) if (FN_TRY_BLOCK_P (t)) { - end_protect_partials (); expand_start_all_catch (); in_function_try_handler = 1; expand_stmt (TRY_HANDLERS (t)); @@ -1216,6 +1215,10 @@ setup_vtbl_ptr (member_init_list, base_init_list) 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 @@ -2559,8 +2562,6 @@ static void genrtl_start_function (fn) tree fn; { - tree parm; - /* Tell everybody what function we're processing. */ current_function_decl = fn; /* Get the RTL machinery going for this function. */ |