aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-09-10 09:21:37 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-09-10 09:21:37 +0000
commit62409b397b129d3e5b40c406c1bd91b252003353 (patch)
treef37256f751716adcc44c2b70bf519b5fe2388f0a /gcc
parentca5b5533e1a80628f6afca632fcece5395305665 (diff)
downloadgcc-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/ChangeLog18
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/init.c25
-rw-r--r--gcc/cp/method.c42
-rw-r--r--gcc/cp/pt.c30
-rw-r--r--gcc/cp/semantics.c435
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;
}