c-common.h (COMPOUND_STMT_BODY_BLOCK): New macro.

* c-common.h (COMPOUND_STMT_BODY_BLOCK): New macro.

        * 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.

From-SVN: r47987
This commit is contained in:
Jason Merrill 2001-12-13 22:01:59 -05:00
parent 466eb3e085
commit ade3dc07d5
12 changed files with 234 additions and 204 deletions

View File

@ -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.

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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)

View File

@ -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));

View File

@ -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

View File

@ -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
}
/* At the beginning of a destructor, push cleanups that will call the
destructors for our base classes and members.
Called from setup_vtbl_ptr. */
void
push_base_cleanups ()
{
tree binfos;
int i, n_baseclasses;
tree member;
tree expr;
/* Run destructors for all virtual baseclasses. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
{
/* 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);
tree vbases;
tree cond = (condition_conversion
(build (BIT_AND_EXPR, integer_type_node,
current_in_charge_parm,
integer_two_node)));
/* Set this again before we call anything, as we might get called
recursively. */
TYPE_HAS_DESTRUCTOR (type) = 1;
/* If we have member delete or vbases, we call delete in
finish_function. */
my_friendly_assert (auto_delete == sfk_base_destructor, 20000411);
/* Take care of the remaining baseclasses. */
for (i = 0; i < n_baseclasses; i++)
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))
{
base_binfo = TREE_VEC_ELT (binfos, i);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
|| TREE_VIA_VIRTUAL (base_binfo))
continue;
tree vbase = TREE_VALUE (vbases);
tree base_type = BINFO_TYPE (vbase);
expr = build_scoped_method_call (ref, base_binfo,
base_dtor_identifier,
NULL_TREE);
exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
}
for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
{
if (TREE_CODE (member) != FIELD_DECL)
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
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);
}
}
}
if (exprstmt)
return build_compound_expr (exprstmt);
/* Virtual base classes make this function do nothing. */
return void_zero_node;
binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
/* 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);
}
}
}

View File

@ -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 ();

View File

@ -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:

View File

@ -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 ();
}

View File

@ -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. */