diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-09-10 09:21:37 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-09-10 09:21:37 +0000 |
commit | 62409b397b129d3e5b40c406c1bd91b252003353 (patch) | |
tree | f37256f751716adcc44c2b70bf519b5fe2388f0a /gcc | |
parent | ca5b5533e1a80628f6afca632fcece5395305665 (diff) | |
download | gcc-62409b397b129d3e5b40c406c1bd91b252003353.zip gcc-62409b397b129d3e5b40c406c1bd91b252003353.tar.gz gcc-62409b397b129d3e5b40c406c1bd91b252003353.tar.bz2 |
cp-tree.h (FN_TRY_BLOCK_P): New macro.
* cp-tree.h (FN_TRY_BLOCK_P): New macro.
* init.c (perform_member_init): Remove obstack machinations.
(expand_cleanup_for_base): Likewise.
(finish_init_stmts): Mark the statement-expression as used.
* method.c (emit_thunk): Use tree-generating functions, not
RTL.
(do_build_copy_constructor): Likewise.
(do_build_assign_ref): Likewise.
(synthesize_method): Likewise. Keep track of line numbers.
* pt.c (tsubst_expr): Handle various kinds of try blocks.
* semantics.c (expand_stmts): Remove.
(begin_function_try_block): Set FN_TRY_BLOCK_P.
(finish_function_try_block): Be careful rechaining
function try blocks.
(expand_stmt): Loop through all the statements at a given level.
(exapnd_body): Be careful with line-numbers here too. Prepare for
being called directly from the parser.
From-SVN: r29263
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 3 | ||||
-rw-r--r-- | gcc/cp/init.c | 25 | ||||
-rw-r--r-- | gcc/cp/method.c | 42 | ||||
-rw-r--r-- | gcc/cp/pt.c | 30 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 435 |
6 files changed, 327 insertions, 226 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b9737ec..8996c44 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,23 @@ 1999-09-10 Mark Mitchell <mark@codesourcery.com> + * cp-tree.h (FN_TRY_BLOCK_P): New macro. + * init.c (perform_member_init): Remove obstack machinations. + (expand_cleanup_for_base): Likewise. + (finish_init_stmts): Mark the statement-expression as used. + * method.c (emit_thunk): Use tree-generating functions, not + RTL. + (do_build_copy_constructor): Likewise. + (do_build_assign_ref): Likewise. + (synthesize_method): Likewise. Keep track of line numbers. + * pt.c (tsubst_expr): Handle various kinds of try blocks. + * semantics.c (expand_stmts): Remove. + (begin_function_try_block): Set FN_TRY_BLOCK_P. + (finish_function_try_block): Be careful rechaining + function try blocks. + (expand_stmt): Loop through all the statements at a given level. + (exapnd_body): Be careful with line-numbers here too. Prepare for + being called directly from the parser. + * cp-tree.h (finish_function): Adjust prototype. * decl.c (finish_function): Return the function compiled. * pt.c (instantiate_decl): Don't play games with obstacks. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index dd88d1a..9be527e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -63,6 +63,7 @@ Boston, MA 02111-1307, USA. */ BINFO_PUSHDECLS_MARKED. (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) + FN_TRY_BLOCK_P (in TRY_BLOCK) 4: BINFO_NEW_VTABLE_MARKED. TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). @@ -2429,6 +2430,8 @@ extern int flag_new_for_scope; #define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0) #define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1) #define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (NODE) +/* Nonzero if this try block is a function try block. */ +#define FN_TRY_BLOCK_P(NODE) TREE_LANG_FLAG_3 (NODE) #define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0) #define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1) #define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index fd48f19..0d9af2c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -225,10 +225,6 @@ perform_member_init (member, name, init, explicit) { tree expr; - /* All cleanups must be on the function_obstack. */ - push_obstacks_nochange (); - resume_temporary_allocation (); - expr = build_component_ref (current_class_ref, name, NULL_TREE, explicit); expr = build_delete (type, expr, integer_zero_node, @@ -236,8 +232,6 @@ perform_member_init (member, name, init, explicit) if (expr != error_mark_node) finish_subobject (expr); - - pop_obstacks (); } } @@ -699,10 +693,6 @@ expand_cleanup_for_base (binfo, flag) if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo))) return; - /* All cleanups must be on the function_obstack. */ - push_obstacks_nochange (); - resume_temporary_allocation (); - /* Call the destructor. */ expr = (build_scoped_method_call (current_class_ref, binfo, dtor_identifier, @@ -712,7 +702,6 @@ expand_cleanup_for_base (binfo, flag) truthvalue_conversion (flag), expr, integer_zero_node)); - pop_obstacks (); finish_subobject (expr); } @@ -1009,9 +998,17 @@ finish_init_stmts (stmt_expr, compound_stmt) tree compound_stmt; { pop_momentary (); - return finish_stmt_expr (stmt_expr, - finish_compound_stmt (/*has_no_scope=*/1, - compound_stmt)); + stmt_expr + = finish_stmt_expr (stmt_expr, + finish_compound_stmt (/*has_no_scope=*/1, + compound_stmt)); + + /* To avoid spurious warnings about unused values, we set + TREE_USED. */ + if (stmt_expr) + TREE_USED (stmt_expr) = 1; + + return stmt_expr; } /* This is like `expand_member_init', only it stores one aggregate diff --git a/gcc/cp/method.c b/gcc/cp/method.c index e91eefa..5e9c578 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2147,7 +2147,7 @@ emit_thunk (thunk_fndecl) t = tree_cons (NULL_TREE, a, t); t = nreverse (t); t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t); - c_expand_return (t); + finish_return_stmt (t); finish_function (lineno, 0); @@ -2172,7 +2172,6 @@ do_build_copy_constructor (fndecl) tree fndecl; { tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); - tree compound_stmt; tree t; if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) @@ -2249,9 +2248,6 @@ do_build_copy_constructor (fndecl) current_base_init_list = nreverse (current_base_init_list); setup_vtbl_ptr (); } - - compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); - finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); } static void @@ -2290,7 +2286,7 @@ do_build_assign_ref (fndecl) p = convert_from_reference (p); p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], build_expr_list (NULL_TREE, p)); - expand_expr_stmt (p); + finish_expr_stmt (p); } for (; fields; fields = TREE_CHAIN (fields)) { @@ -2342,10 +2338,10 @@ do_build_assign_ref (fndecl) comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); init = build (COMPONENT_REF, TREE_TYPE (field), init, field); - expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); + finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); } } - c_expand_return (current_class_ref); + finish_return_stmt (current_class_ref); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); } @@ -2355,6 +2351,7 @@ synthesize_method (fndecl) { int nested = (current_function_decl != NULL_TREE); tree context = hack_decl_function_context (fndecl); + int need_body = 1; if (at_eof) import_export_decl (fndecl); @@ -2364,13 +2361,25 @@ synthesize_method (fndecl) else if (nested) push_function_context_to (context); + /* Put the function definition at the position where it is needed, + rather than within the body of the class. That way, an error + during the generation of the implicit body points at the place + where the attempt to generate the function occurs, giving the + user a hint as to why we are attempting to generate the + function. */ + DECL_SOURCE_LINE (fndecl) = lineno; + DECL_SOURCE_FILE (fndecl) = input_filename; + interface_unknown = 1; start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); store_parm_decls (); clear_last_expr (); if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) - do_build_assign_ref (fndecl); + { + do_build_assign_ref (fndecl); + need_body = 0; + } else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) ; else @@ -2381,13 +2390,16 @@ synthesize_method (fndecl) if (arg_chain != void_list_node) do_build_copy_constructor (fndecl); else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) - { - tree compound_stmt; + setup_vtbl_ptr (); + } - setup_vtbl_ptr (); - compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); - finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); - } + /* If we haven't yet generated the body of the function, just + generate an empty compound statement. */ + if (need_body) + { + tree compound_stmt; + compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); + finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); } finish_function (lineno, 0); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8af26e5..a214317 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7443,16 +7443,32 @@ tsubst_expr (t, args, complain, in_decl) case TRY_BLOCK: prep_stmt (t); - stmt = begin_try_block (); - tsubst_expr (TRY_STMTS (t), args, complain, in_decl); - finish_try_block (stmt); if (CLEANUP_P (t)) - finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args, - complain, in_decl), - stmt); + { + begin_try_block (); + tsubst_expr (TRY_STMTS (t), args, complain, in_decl); + finish_cleanup_try_block (stmt); + finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args, + complain, in_decl), + stmt); + } else { - tree handler = TRY_HANDLERS (t); + tree handler; + + if (FN_TRY_BLOCK_P (t)) + stmt = begin_function_try_block (); + else + stmt = begin_try_block (); + + tsubst_expr (TRY_STMTS (t), args, complain, in_decl); + + if (FN_TRY_BLOCK_P (t)) + finish_function_try_block (stmt); + else + finish_try_block (stmt); + + handler = TRY_HANDLERS (t); for (; handler; handler = TREE_CHAIN (handler)) tsubst_expr (handler, args, complain, in_decl); finish_handler_sequence (stmt); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 771f7c8..d2f6969 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -41,7 +41,6 @@ parsing into this file; that will make implementing the new parser much easier since it will be able to make use of these routines. */ -static void expand_stmts PROTO((tree)); static void do_pushlevel PROTO((void)); static tree do_poplevel PROTO((void)); static void finish_expr_stmt_real PROTO((tree, int)); @@ -650,6 +649,7 @@ begin_function_try_block () { tree r = build_min_nt (TRY_BLOCK, NULL_TREE, NULL_TREE); + FN_TRY_BLOCK_P (r) = 1; add_tree (r); return r; } @@ -674,6 +674,14 @@ finish_try_block (try_block) expand_start_all_catch (); } +void +finish_cleanup_try_block (try_block) + tree try_block; +{ + if (building_stmt_tree ()) + RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); +} + /* Finish an implicitly generated try-block, with a cleanup is given by CLEANUP. */ @@ -698,7 +706,18 @@ finish_function_try_block (try_block) tree try_block; { if (building_stmt_tree ()) - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + { + if (TREE_CHAIN (try_block) + && TREE_CODE (TREE_CHAIN (try_block)) == CTOR_INITIALIZER) + { + /* Chain the compound statement after the CTOR_INITIALIZER. */ + TREE_CHAIN (TREE_CHAIN (try_block)) = last_tree; + /* And make the CTOR_INITIALIZER the body of the try-block. */ + RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + } + else + RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + } else { end_protect_partials (); @@ -2025,219 +2044,225 @@ expand_cond (t) return t; } -/* Generate RTL for the chain of statements T. */ - -static void -expand_stmts (t) - tree t; -{ - while (t) - { - expand_stmt (t); - t = TREE_CHAIN (t); - } -} - -/* Generate RTL for the statement T, and its substatements. */ +/* Generate RTL for the statement T, and its substatements, and any + other statements at its nesting level. */ tree expand_stmt (t) tree t; { - int saved_stmts_are_full_exprs_p; tree rval; - if (t == NULL_TREE || t == error_mark_node) - return NULL_TREE; + while (t && t != error_mark_node) + { + int saved_stmts_are_full_exprs_p; - /* Assume we'll have nothing to return. */ - rval = NULL_TREE; + /* Assume we'll have nothing to return. */ + rval = NULL_TREE; - /* Set up context appropriately for handling this statement. */ - saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p; - prep_stmt (t); + /* Set up context appropriately for handling this statement. */ + saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p; + prep_stmt (t); - switch (TREE_CODE (t)) - { - case RETURN_STMT: - finish_return_stmt (RETURN_EXPR (t)); - break; + switch (TREE_CODE (t)) + { + case RETURN_STMT: + finish_return_stmt (RETURN_EXPR (t)); + break; - case EXPR_STMT: - finish_expr_stmt_real (EXPR_STMT_EXPR (t), - EXPR_STMT_ASSIGNS_THIS (t)); - break; + case EXPR_STMT: + finish_expr_stmt_real (EXPR_STMT_EXPR (t), + EXPR_STMT_ASSIGNS_THIS (t)); + break; - case DECL_STMT: - { - tree decl; - int i = suspend_momentary (); - - lineno = STMT_LINENO (t); - emit_line_note (input_filename, lineno); - decl = DECL_STMT_DECL (t); - if (TREE_CODE (decl) == LABEL_DECL) - finish_label_decl (DECL_NAME (decl)); - else + case DECL_STMT: { - /* We need to clear DECL_CONTEXT so that maybe_push_decl - will push it into the current scope. */ - if (DECL_CONTEXT (decl) == current_function_decl) - DECL_CONTEXT (decl) = NULL_TREE; - /* If we marked this variable as dead when we processed it - before, we must undo that now. The variable has been - resuscitated. */ - if (TREE_CODE (decl) == VAR_DECL) - DECL_DEAD_FOR_LOCAL (decl) = 0; - maybe_push_decl (decl); - if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl)) + tree decl; + int i = suspend_momentary (); + + emit_line_note (input_filename, lineno); + decl = DECL_STMT_DECL (t); + if (TREE_CODE (decl) == LABEL_DECL) + finish_label_decl (DECL_NAME (decl)); + else { - maybe_inject_for_scope_var (decl); - initialize_local_var (decl, DECL_INITIAL (decl), 0); + /* If we marked this variable as dead when we processed it + before, we must undo that now. The variable has been + resuscitated. */ + if (TREE_CODE (decl) == VAR_DECL) + DECL_DEAD_FOR_LOCAL (decl) = 0; + /* We need to clear DECL_CONTEXT so that maybe_push_decl + will push it into the current scope. */ + if (DECL_CONTEXT (decl) == current_function_decl) + { + DECL_CONTEXT (decl) = NULL_TREE; + maybe_push_decl (decl); + } + /* If this is a declaration for an automatic local + variable, initialize it. Note that we might also see a + declaration for a namespace-scope object (declared with + `extern') or an object with static storage duration + (declared with `static'). We don't have to handle the + initialization of those objects here; the former can + never be a definition (only a declaration), and the + latter is handled in finish_file. */ + if (TREE_CODE (decl) == VAR_DECL + && !TREE_STATIC (decl) + && !DECL_EXTERNAL (decl)) + { + /* Support the old for-scope rules for backwards + compatibility. */ + maybe_inject_for_scope_var (decl); + /* Let the back-end know about this variable. */ + initialize_local_var (decl, DECL_INITIAL (decl), 0); + } } + resume_momentary (i); } - resume_momentary (i); - } - break; - - case FOR_STMT: - { - tree tmp; - - begin_for_stmt (); - for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp)) - expand_stmt (tmp); - finish_for_init_stmt (NULL_TREE); - finish_for_cond (expand_cond (FOR_COND (t)), NULL_TREE); - tmp = FOR_EXPR (t); - finish_for_expr (tmp, NULL_TREE); - expand_stmt (FOR_BODY (t)); - finish_for_stmt (tmp, NULL_TREE); - } - break; - - case WHILE_STMT: - { - begin_while_stmt (); - finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE); - expand_stmt (WHILE_BODY (t)); - finish_while_stmt (NULL_TREE); - } - break; + break; - case DO_STMT: - { - begin_do_stmt (); - expand_stmt (DO_BODY (t)); - finish_do_body (NULL_TREE); - finish_do_stmt (DO_COND (t), NULL_TREE); - } - break; - - case IF_STMT: - begin_if_stmt (); - finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE); - if (THEN_CLAUSE (t)) - { - expand_stmt (THEN_CLAUSE (t)); - finish_then_clause (NULL_TREE); - } - if (ELSE_CLAUSE (t)) - { - begin_else_clause (); - expand_stmt (ELSE_CLAUSE (t)); - finish_else_clause (NULL_TREE); - } - finish_if_stmt (); - break; - - case COMPOUND_STMT: - begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)); - expand_stmts (COMPOUND_BODY (t)); - rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), - NULL_TREE); - break; - - case BREAK_STMT: - finish_break_stmt (); - break; + case FOR_STMT: + { + tree tmp; + + begin_for_stmt (); + expand_stmt (FOR_INIT_STMT (t)); + finish_for_init_stmt (NULL_TREE); + finish_for_cond (expand_cond (FOR_COND (t)), NULL_TREE); + tmp = FOR_EXPR (t); + finish_for_expr (tmp, NULL_TREE); + expand_stmt (FOR_BODY (t)); + finish_for_stmt (tmp, NULL_TREE); + } + break; - case CONTINUE_STMT: - finish_continue_stmt (); - break; + case WHILE_STMT: + { + begin_while_stmt (); + finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE); + expand_stmt (WHILE_BODY (t)); + finish_while_stmt (NULL_TREE); + } + break; - case SWITCH_STMT: - { - tree cond; + case DO_STMT: + { + begin_do_stmt (); + expand_stmt (DO_BODY (t)); + finish_do_body (NULL_TREE); + finish_do_stmt (DO_COND (t), NULL_TREE); + } + break; - begin_switch_stmt (); - cond = expand_cond (SWITCH_COND (t)); - finish_switch_cond (cond, NULL_TREE); - expand_stmt (SWITCH_BODY (t)); - finish_switch_stmt (cond, NULL_TREE); - } - break; + case IF_STMT: + begin_if_stmt (); + finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE); + if (THEN_CLAUSE (t)) + { + expand_stmt (THEN_CLAUSE (t)); + finish_then_clause (NULL_TREE); + } + if (ELSE_CLAUSE (t)) + { + begin_else_clause (); + expand_stmt (ELSE_CLAUSE (t)); + finish_else_clause (NULL_TREE); + } + finish_if_stmt (); + break; - case CASE_LABEL: - finish_case_label (CASE_LOW (t), CASE_HIGH (t)); - break; + case COMPOUND_STMT: + begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)); + expand_stmt (COMPOUND_BODY (t)); + rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), + NULL_TREE); + break; - case LABEL_STMT: - finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t))); - break; + case BREAK_STMT: + finish_break_stmt (); + break; - case GOTO_STMT: - if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL) - finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t))); - else - finish_goto_stmt (GOTO_DESTINATION (t)); - break; + case CONTINUE_STMT: + finish_continue_stmt (); + break; - case ASM_STMT: - finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS - (t), ASM_INPUTS (t), ASM_CLOBBERS (t)); - break; + case SWITCH_STMT: + { + tree cond; - case TRY_BLOCK: - if (CLEANUP_P (t)) - { - expand_eh_region_start (); - expand_stmt (TRY_STMTS (t)); - finish_cleanup (TRY_HANDLERS (t), NULL_TREE); - } - else - { - begin_try_block (); - expand_stmt (TRY_STMTS (t)); - finish_try_block (NULL_TREE); - expand_stmts (TRY_HANDLERS (t)); - finish_handler_sequence (NULL_TREE); + begin_switch_stmt (); + cond = expand_cond (SWITCH_COND (t)); + finish_switch_cond (cond, NULL_TREE); + expand_stmt (SWITCH_BODY (t)); + finish_switch_stmt (cond, NULL_TREE); + } + break; + + case CASE_LABEL: + finish_case_label (CASE_LOW (t), CASE_HIGH (t)); + break; + + case LABEL_STMT: + finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t))); + break; + + case GOTO_STMT: + if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL) + finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t))); + else + finish_goto_stmt (GOTO_DESTINATION (t)); + break; + + case ASM_STMT: + finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS + (t), ASM_INPUTS (t), ASM_CLOBBERS (t)); + break; + + case TRY_BLOCK: + if (CLEANUP_P (t)) + { + expand_eh_region_start (); + expand_stmt (TRY_STMTS (t)); + finish_cleanup_try_block (NULL_TREE); + finish_cleanup (TRY_HANDLERS (t), NULL_TREE); + } + else + { + begin_try_block (); + expand_stmt (TRY_STMTS (t)); + finish_try_block (NULL_TREE); + expand_stmt (TRY_HANDLERS (t)); + finish_handler_sequence (NULL_TREE); + } + break; + + case HANDLER: + begin_handler (); + if (HANDLER_PARMS (t)) + expand_start_catch_block (DECL_STMT_DECL (HANDLER_PARMS (t))); + else + expand_start_catch_block (NULL_TREE); + finish_handler_parms (NULL_TREE); + expand_stmt (HANDLER_BODY (t)); + finish_handler (NULL_TREE); + break; + + case SUBOBJECT: + finish_subobject (SUBOBJECT_CLEANUP (t)); + break; + + default: + my_friendly_abort (19990810); + break; } - break; - case HANDLER: - begin_handler (); - if (HANDLER_PARMS (t)) - expand_start_catch_block (DECL_STMT_DECL (HANDLER_PARMS (t))); - else - expand_start_catch_block (NULL_TREE); - finish_handler_parms (NULL_TREE); - expand_stmt (HANDLER_BODY (t)); - finish_handler (NULL_TREE); - break; + /* Restore saved state. */ + stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; - case SUBOBJECT: - finish_subobject (SUBOBJECT_CLEANUP (t)); - break; - - default: - my_friendly_abort (19990810); - break; + /* Go on to the next statement in this scope. */ + t = TREE_CHAIN (t); } - /* Restore saved state. */ - stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; - return rval; } @@ -2247,9 +2272,30 @@ void expand_body (fn) tree fn; { + int saved_lineno; + char *saved_input_filename; tree t; tree try_block; + /* When the parser calls us after finishing the body of a template + function, we don't really want to expand the body. When we're + processing an in-class definition of an inline function, + PROCESSING_TEMPLATE_DECL will no longer be set here, so we have + to look at the function itself. */ + if (processing_template_decl + || (DECL_LANG_SPECIFIC (fn) + && DECL_TEMPLATE_INFO (fn) + && uses_template_parms (DECL_TI_ARGS (fn)))) + return; + + /* Save the current file name and line number. When we expand the + body of the funciton, we'll set LINENO and INPUT_FILENAME so that + error-mesages come out in the right places. */ + saved_lineno = lineno; + saved_input_filename = input_filename; + lineno = DECL_SOURCE_LINE (fn); + input_filename = DECL_SOURCE_FILE (fn); + start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND); store_parm_decls (); @@ -2292,13 +2338,22 @@ expand_body (fn) if (try_block) { finish_function_try_block (NULL_TREE); - { - tree handler = TRY_HANDLERS (try_block); - for (; handler; handler = TREE_CHAIN (handler)) - expand_stmt (handler); - } + expand_stmt (TRY_HANDLERS (try_block)); finish_function_handler_sequence (NULL_TREE); } + /* Statements should always be full-expressions at the outermost set + of curly braces for a function. */ + my_friendly_assert (stmts_are_full_exprs_p, 19990831); + + /* The outermost statement for a function contains the line number + recorded when we finished processing the function. */ + lineno = STMT_LINENO (DECL_SAVED_TREE (fn)); + + /* Generate code for the function. */ finish_function (lineno, 0); + + /* And restore the current source position. */ + lineno = saved_lineno; + input_filename = saved_input_filename; } |