diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 60 | ||||
-rw-r--r-- | gcc/cp/call.c | 39 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 25 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 9 | ||||
-rw-r--r-- | gcc/cp/cp-mudflap.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 52 | ||||
-rw-r--r-- | gcc/cp/decl.c | 68 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 6 | ||||
-rw-r--r-- | gcc/cp/except.c | 79 | ||||
-rw-r--r-- | gcc/cp/init.c | 17 | ||||
-rw-r--r-- | gcc/cp/method.c | 4 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 2 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 4 | ||||
-rw-r--r-- | gcc/cp/parser.c | 90 | ||||
-rw-r--r-- | gcc/cp/pt.c | 91 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 496 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 27 |
17 files changed, 568 insertions, 503 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3889e75b7cf..c8a1a1e5e9c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,63 @@ +2004-06-15 Richard Henderson <rth@redhat.com> + + * call.c (initialize_reference): Don't build CLEANUP_STMT here. + * cp-gimplify.c (cp_gimplify_stmt): Remove next_p argument. + (genericize_try_block): Use gimplify_stmt. + (genericize_catch_block, genericize_eh_spec_block): Likewise. + (cp_gimplify_init_expr): Remove STMT_EXPR special case. + (gimplify_must_not_throw_expr): Update voidify_wrapper_expr call. + * cp-lang.c (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P): Remove. + (cp_tree_chain_matters_p): Remove. + * cp-tree.h (COMPOUND_STMT_TRY_BLOCK): New. + (COMPOUND_STMT_BODY_BLOCK): New. + (STATEMENT_LIST_NO_SCOPE, STATEMENT_LIST_TRY_BLOCK): New. + (EXPR_STMT_STMT_EXPR_RESULT): New. + (building_stmt_tree): Check cur_stmt_list. + (tf_stmt_expr_cmpd, tf_stmt_expr_body): Remove. + (BCS_NO_SCOPE, BCS_TRY_BLOCK, BCS_FN_BODY): New. + * decl.c (poplevel): Use pop_stmt_list for minding cleanups. + (cp_finish_decl): Use push_cleanup. + (start_function, finish_function): Use statement lists. + (finish_stmt): Do nothing. + * except.c (begin_eh_spec_block): Use statement lists. + (check_handlers_1, check_handlers): Likewise. + * init.c (construct_virtual_base): Don't add extra compound stmts. + (build_vec_init): Likewise. + * name-lookup.c (maybe_push_cleanup_level): Use statement lists. + * name-lookup.h (struct cp_binding_level): Add statement_list. + * parser.c (cp_parser_statement): Take the STMT_EXPR node, not a bool. + (cp_parser_labeled_statement, cp_parser_expression_statement, + cp_parser_statement_seq_opt): Likewise. + (cp_parser_compound_statement): Likewise. Take bool for try block. + (cp_parser_selection_statement): Tidy if processing. + (cp_parser_already_scoped_statement): Rewrite to do what it says. + * pt.c (tsubst_copy): Move STMT_EXPR to tsubst_expr. + (tsubst_expr): Rewrite STMT_EXPR processing. Handle STATEMENT_LIST. + Mind COMPOUND_STMT_TRY_BLOCK, EXPR_STMT_STMT_EXPR_RESULT. + * semantics.c (do_poplevel, do_pushlevel): Use statement lists. + (finish_cond): New, rewritten from FINISH_COND. + (simplify_loop_decl_cond): New. + (finish_expr_stmt): Avoid nested EXPR_STMTs. + (begin_if_stmt, finish_if_stmt_cond, finish_then_clause, + begin_else_clause, finish_else_clause, finish_if_stmt, + begin_while_stmt, finish_while_stmt_cond, finish_while_stmt, + begin_do_stmt, finish_do_body, begin_for_stmt, finish_for_init_stmt, + finish_for_cond, finish_for_stmt, begin_switch_stmt, + finish_switch_cond, finish_switch_stmt, begin_try_block, + finish_try_block, finish_cleanup_try_block, finish_function_try_block, + finish_handler_sequence, finish_function_handler_sequence, + begin_handler, finish_handler_parms, finish_handler, + begin_stmt_expr, finish_stmt_expr_expr, finish_stmt_expr): Rewrite + using statement lists. + (begin_compound_stmt): Replace has_no_scope argument with flags. + Update all callers. Use statement lists. + (finish_compound_stmt): Likewise. + (finish_decl_cleanup, finish_eh_cleanup): Use push_cleanup. + (current_scope_stmt_stack): Remove. + (simplify_aggr_init_expr): Don't muck with TREE_CHAIN. + * typeck2.c (split_nonconstant_init_1, split_nonconstant_init): + Rewrite with statement lists. + 2004-06-15 Alexandre Oliva <aoliva@redhat.com> * parser.c: Change all assignments of c_lex_string_translate diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d1e8298164b..616cf812f92 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6362,9 +6362,9 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type) the VAR_DECL being initialized with the EXPR. (In that case, the type of DECL will be TYPE.) If DECL is non-NULL, then CLEANUP must also be non-NULL, and with *CLEANUP initialized to NULL. Upon - return, if *CLEANUP is no longer NULL, it will be a CLEANUP_STMT - that should be inserted after the returned expression is used to - initialize DECL. + return, if *CLEANUP is no longer NULL, it will be an expression + that should be pushed as a cleanup after the returned expression + is used to initialize DECL. Return the converted expression. */ @@ -6485,26 +6485,25 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) { add_decl_stmt (var); *cleanup = cxx_maybe_build_cleanup (var); - if (*cleanup) - /* We must be careful to destroy the temporary only - after its initialization has taken place. If the - initialization throws an exception, then the - destructor should not be run. We cannot simply - transform INIT into something like: + + /* We must be careful to destroy the temporary only + after its initialization has taken place. If the + initialization throws an exception, then the + destructor should not be run. We cannot simply + transform INIT into something like: (INIT, ({ CLEANUP_STMT; })) - because emit_local_var always treats the - initializer as a full-expression. Thus, the - destructor would run too early; it would run at the - end of initializing the reference variable, rather - than at the end of the block enclosing the - reference variable. - - The solution is to pass back a CLEANUP_STMT which - the caller is responsible for attaching to the - statement tree. */ - *cleanup = build_stmt (CLEANUP_STMT, var, *cleanup); + because emit_local_var always treats the + initializer as a full-expression. Thus, the + destructor would run too early; it would run at the + end of initializing the reference variable, rather + than at the end of the block enclosing the + reference variable. + + The solution is to pass back a cleanup expression + which the caller is responsible for attaching to + the statement tree. */ } else { diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index f82ed61eb7a..2884d8b5b2d 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -39,7 +39,7 @@ static void cp_gimplify_init_expr (tree *, tree *, tree *); /* Genericize a C++ _STMT. Called from c_gimplify_stmt. */ int -cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED) +cp_gimplify_stmt (tree *stmt_p) { tree stmt = *stmt_p; switch (TREE_CODE (stmt)) @@ -76,12 +76,12 @@ genericize_try_block (tree *stmt_p) tree body = TRY_STMTS (*stmt_p); tree cleanup = TRY_HANDLERS (*stmt_p); - c_gimplify_stmt (&body); + gimplify_stmt (&body); if (CLEANUP_P (*stmt_p)) /* A cleanup is an expression, so it doesn't need to be genericized. */; else - c_gimplify_stmt (&cleanup); + gimplify_stmt (&cleanup); *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup); } @@ -94,7 +94,7 @@ genericize_catch_block (tree *stmt_p) tree type = HANDLER_TYPE (*stmt_p); tree body = HANDLER_BODY (*stmt_p); - c_gimplify_stmt (&body); + gimplify_stmt (&body); /* FIXME should the caught type go in TREE_TYPE? */ *stmt_p = build (CATCH_EXPR, void_type_node, type, body); @@ -111,7 +111,7 @@ genericize_eh_spec_block (tree *stmt_p) tree failure = build_call (call_unexpected_node, tree_cons (NULL_TREE, build_exc_ptr (), NULL_TREE)); - c_gimplify_stmt (&body); + gimplify_stmt (&body); *stmt_p = gimple_build_eh_filter (body, allowed, failure); } @@ -182,16 +182,8 @@ cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) if (TREE_CODE (from) == TARGET_EXPR) from = TARGET_EXPR_INITIAL (from); - sub = from; - - /* If we are initializing from a STMT_EXPR, extract the returned - expression. */ - if (TREE_CODE (from) == STMT_EXPR) - sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from)); - /* Look through any COMPOUND_EXPRs. */ - while (TREE_CODE (sub) == COMPOUND_EXPR) - sub = TREE_OPERAND (sub, 1); + sub = expr_last (from); /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and replace the slot operand with our target. @@ -205,8 +197,7 @@ cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) *expr_p = from; /* The initialization is now a side-effect, so the container can - become void. This is important for a STMT_EXPR, so we don't try - to voidify it later by creating a temporary. */ + become void. */ if (from != sub) TREE_TYPE (from) = void_type_node; } @@ -218,7 +209,7 @@ static void gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) { tree stmt = *expr_p; - tree temp = voidify_wrapper_expr (stmt); + tree temp = voidify_wrapper_expr (stmt, NULL); tree body = TREE_OPERAND (stmt, 0); gimplify_stmt (&body); diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index 8a82e4e72ce..eb0e2210624 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -138,9 +138,6 @@ static void cxx_initialize_diagnostics (diagnostic_context *); #undef LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS #define LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS \ cp_add_pending_fn_decls -#undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P -#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \ - cp_tree_chain_matters_p #undef LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P #define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \ cp_auto_var_in_fn_p @@ -292,12 +289,6 @@ cp_expr_size (tree exp) return lhd_expr_size (exp); } -int -cp_tree_chain_matters_p (tree t) -{ - return cp_is_overload_p (t) || c_tree_chain_matters_p (t); -} - /* Langhook for tree_size: determine size of our 'x' and 'c' nodes. */ static size_t cp_tree_size (enum tree_code code) diff --git a/gcc/cp/cp-mudflap.c b/gcc/cp/cp-mudflap.c index 878dc8a1c85..faa57e2df5e 100644 --- a/gcc/cp/cp-mudflap.c +++ b/gcc/cp/cp-mudflap.c @@ -82,7 +82,7 @@ mflang_flush_calls (tree enqueued_call_stmt_chain) mf_mark (current_function_decl); /* Generate the body, one statement at a time. */ - body = begin_compound_stmt (/*has_no_scope=*/false); + body = begin_compound_stmt (BCS_FN_BODY); while (enqueued_call_stmt_chain) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 320098b773c..799bbcfe79d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -48,6 +48,9 @@ struct diagnostic_context; PARMLIST_ELLIPSIS_P (in PARMLIST) DECL_PRETTY_FUNCTION_P (in VAR_DECL) KOENIG_LOOKUP_P (in CALL_EXPR) + STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST). + EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT) + COMPOUND_STMT_TRY_BLOCK (in COMPOUND_STMT) 1: IDENTIFIER_VIRTUAL_P. TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -63,6 +66,7 @@ struct diagnostic_context; BINFO_LOST_PRIMARY_P (in BINFO) TREE_PARMLIST (in TREE_LIST) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) + STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST) 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). BINFO_VTABLE_PATH_MARKED. BINFO_PUSHDECLS_MARKED. @@ -70,6 +74,7 @@ struct diagnostic_context; ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE) + COMPOUND_STMT_BODY_BLOCK (in COMPOUND_STMT) 4: BINFO_NEW_VTABLE_MARKED. TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). @@ -266,6 +271,22 @@ typedef struct ptrmem_cst * ptrmem_cst_t; #define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (TRY_BLOCK_CHECK (NODE)) +#define COMPOUND_STMT_TRY_BLOCK(NODE) \ + TREE_LANG_FLAG_0 (COMPOUND_STMT_CHECK (NODE)) + +/* Used to mark the block around the member initializers and cleanups. */ +#define COMPOUND_STMT_BODY_BLOCK(NODE) \ + TREE_LANG_FLAG_3 (COMPOUND_STMT_CHECK (NODE)) + +#define STATEMENT_LIST_NO_SCOPE(NODE) \ + TREE_LANG_FLAG_0 (STATEMENT_LIST_CHECK (NODE)) +#define STATEMENT_LIST_TRY_BLOCK(NODE) \ + TREE_LANG_FLAG_2 (STATEMENT_LIST_CHECK (NODE)) + +/* Marks the result of a statement expression. */ +#define EXPR_STMT_STMT_EXPR_RESULT(NODE) \ + TREE_LANG_FLAG_0 (EXPR_STMT_CHECK (NODE)) + /* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual sense of `same'. */ #define same_type_p(TYPE1, TYPE2) \ @@ -278,7 +299,7 @@ typedef struct ptrmem_cst * ptrmem_cst_t; /* Nonzero if we are presently building a statement tree, rather than expanding each statement as we encounter it. */ -#define building_stmt_tree() (last_tree != NULL_TREE) +#define building_stmt_tree() (cur_stmt_list != NULL_TREE) /* Returns nonzero iff NODE is a declaration for the global function `main'. */ @@ -3031,12 +3052,7 @@ typedef enum tsubst_flags_t { instantiate_type use) */ tf_user = 1 << 5, /* found template must be a user template (lookup_template_class use) */ - tf_stmt_expr_cmpd = 1 << 6, /* tsubsting the compound statement of - a statement expr. */ - tf_stmt_expr_body = 1 << 7, /* tsubsting the statements in the - body of the compound statement of a - statement expr. */ - tf_conv = 1 << 8 /* We are determining what kind of + tf_conv = 1 << 6 /* We are determining what kind of conversion might be permissible, not actually performing the conversion. */ @@ -4004,9 +4020,9 @@ extern tree finish_expr_stmt (tree); extern tree begin_if_stmt (void); extern void finish_if_stmt_cond (tree, tree); extern tree finish_then_clause (tree); -extern void begin_else_clause (void); +extern void begin_else_clause (tree); extern void finish_else_clause (tree); -extern void finish_if_stmt (void); +extern void finish_if_stmt (tree); extern tree begin_while_stmt (void); extern void finish_while_stmt_cond (tree, tree); extern void finish_while_stmt (tree); @@ -4040,8 +4056,15 @@ extern void finish_handler_parms (tree, tree); extern void begin_catch_block (tree); extern void finish_handler (tree); extern void finish_cleanup (tree, tree); -extern tree begin_compound_stmt (bool); -extern tree finish_compound_stmt (tree); + +enum { + BCS_NO_SCOPE = 1, + BCS_TRY_BLOCK = 2, + BCS_FN_BODY = 4 +}; +extern tree begin_compound_stmt (unsigned int); + +extern void finish_compound_stmt (tree); extern tree finish_asm_stmt (int, tree, tree, tree, tree); extern tree finish_label_stmt (tree); extern void finish_label_decl (tree); @@ -4049,7 +4072,7 @@ extern void finish_subobject (tree); extern tree finish_parenthesized_expr (tree); extern tree finish_non_static_data_member (tree, tree, tree); extern tree begin_stmt_expr (void); -extern tree finish_stmt_expr_expr (tree); +extern tree finish_stmt_expr_expr (tree, tree); extern tree finish_stmt_expr (tree, bool); extern tree perform_koenig_lookup (tree, tree); extern tree finish_call_expr (tree, tree, bool, bool); @@ -4082,8 +4105,6 @@ extern void finish_decl_cleanup (tree, tree); extern void finish_eh_cleanup (tree); extern void expand_body (tree); extern void cxx_expand_function_start (void); -extern void do_pushlevel (scope_kind); -extern tree do_poplevel (void); extern void finish_mem_initializers (tree); extern void setup_vtbl_ptr (tree, tree); extern void clear_out_block (void); @@ -4164,7 +4185,6 @@ extern tree find_tree (tree, tree); extern linkage_kind decl_linkage (tree); extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn, void*, void*); -extern int cp_tree_chain_matters_p (tree); extern int cp_cannot_inline_tree_fn (tree*); extern tree cp_add_pending_fn_decls (void*,tree); extern int cp_is_overload_p (tree); @@ -4286,7 +4306,7 @@ extern bool cp_dump_tree (void *, tree); /* in cp-simplify.c */ extern int cp_gimplify_expr (tree *, tree *, tree *); -extern int cp_gimplify_stmt (tree *, tree *); +extern int cp_gimplify_stmt (tree *); /* -- end of C++ */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 92c6cf03976..84ce0d74e94 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -429,12 +429,15 @@ poplevel (int keep, int reverse, int functionbody) int tmp = functionbody; int real_functionbody; tree subblocks; - tree block = NULL_TREE; + tree block; tree decl; int leaving_for_scope; scope_kind kind; timevar_push (TV_NAME_LOOKUP); + restart: + + block = NULL_TREE; my_friendly_assert (current_binding_level->kind != sk_class, 19990916); @@ -657,6 +660,17 @@ poplevel (int keep, int reverse, int functionbody) } kind = current_binding_level->kind; + if (kind == sk_cleanup) + { + tree stmt; + + /* If this is a temporary binding created for a cleanup, then we'll + have pushed a statement list level. Pop that, create a new + BIND_EXPR for the block, and insert it into the stream. */ + stmt = pop_stmt_list (current_binding_level->statement_list); + stmt = c_build_bind_expr (block, stmt); + add_stmt (stmt); + } leave_scope (); if (functionbody) @@ -680,21 +694,9 @@ poplevel (int keep, int reverse, int functionbody) if (block) TREE_USED (block) = 1; - /* Take care of compiler's internal binding structures. */ + /* All temporary bindings created for cleanups are popped silently. */ if (kind == sk_cleanup) - { - tree scope_stmts; - - scope_stmts - = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1); - if (block) - { - SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block; - SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block; - } - - block = poplevel (keep, reverse, functionbody); - } + goto restart; POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block); } @@ -4938,7 +4940,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) /* If a CLEANUP_STMT was created to destroy a temporary bound to a reference, insert it in the statement-tree now. */ if (cleanup) - add_stmt (cleanup); + push_cleanup (decl, cleanup, false); finish_end: @@ -5174,7 +5176,7 @@ register_dtor_fn (tree decl) pop_deferring_access_checks (); /* Create the body of the anonymous function. */ - compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); + compound_stmt = begin_compound_stmt (BCS_FN_BODY); finish_expr_stmt (fcall); finish_compound_stmt (compound_stmt); end_cleanup_fn (); @@ -5252,7 +5254,7 @@ expand_static_init (tree decl, tree init) /* Begin the conditional initialization. */ if_stmt = begin_if_stmt (); finish_if_stmt_cond (get_guard_cond (guard), if_stmt); - then_clause = begin_compound_stmt (/*has_no_scope=*/false); + then_clause = begin_compound_stmt (0); /* Do the initialization itself. */ assignment = init ? init : NULL_TREE; @@ -5278,7 +5280,7 @@ expand_static_init (tree decl, tree init) finish_compound_stmt (then_clause); finish_then_clause (if_stmt); - finish_if_stmt (); + finish_if_stmt (if_stmt); } else static_aggregates = tree_cons (init, decl, static_aggregates); @@ -10225,7 +10227,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags) cfun->x_dont_save_pending_sizes_p = 1; /* Start the statement-tree, start the tree now. */ - begin_stmt_tree (&DECL_SAVED_TREE (decl1)); + DECL_SAVED_TREE (decl1) = push_stmt_list (); /* Let the user know we're compiling this function. */ announce_function (decl1); @@ -10486,8 +10488,7 @@ save_function_data (tree decl) DECL_SAVED_FUNCTION_DATA (decl) = f; /* Clear out the bits we don't need. */ - f->base.x_stmt_tree.x_last_stmt = NULL_TREE; - f->base.x_stmt_tree.x_last_expr_type = NULL_TREE; + f->base.x_stmt_tree.x_cur_stmt_list = NULL_TREE; f->x_named_label_uses = NULL; f->bindings = NULL; f->x_local_names = NULL; @@ -10542,7 +10543,7 @@ begin_destructor_body (void) initialize the vtables.) */ finish_if_stmt_cond (boolean_true_node, if_stmt); - compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); + compound_stmt = begin_compound_stmt (0); /* Make all virtual function table pointers in non-virtual base classes point to CURRENT_CLASS_TYPE's virtual function @@ -10551,7 +10552,7 @@ begin_destructor_body (void) finish_compound_stmt (compound_stmt); finish_then_clause (if_stmt); - finish_if_stmt (); + finish_if_stmt (if_stmt); /* And insert cleanups for our bases and members so that they will be properly destroyed if we throw. */ @@ -10593,7 +10594,7 @@ finish_destructor_body (void) if_stmt); finish_expr_stmt (exprstmt); finish_then_clause (if_stmt); - finish_if_stmt (); + finish_if_stmt (if_stmt); } } @@ -10616,7 +10617,7 @@ begin_function_body (void) operation of dwarfout.c. */ keep_next_level (true); - stmt = begin_compound_stmt (/*has_no_scope=*/false); + stmt = begin_compound_stmt (BCS_FN_BODY); COMPOUND_STMT_BODY_BLOCK (stmt) = 1; if (processing_template_decl) @@ -10716,10 +10717,10 @@ finish_function (int flags) current_eh_spec_block); } - finish_fname_decls (); - /* If we're saving up tree structure, tie off the function now. */ - finish_stmt_tree (&DECL_SAVED_TREE (fndecl)); + DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); + + finish_fname_decls (); /* If this function can't throw any exceptions, remember that. */ if (!processing_template_decl @@ -10773,9 +10774,10 @@ finish_function (int flags) the function so we know that their lifetime always ends with a return; see g++.dg/opt/nrv6.C. We could be more flexible if we were to do this optimization in tree-ssa. */ + && (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))) /* Skip the artificial function body block. */ - && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))), - chain_member (r, BLOCK_VARS (outer)))) + && (outer = BLOCK_SUBBLOCKS (outer)) + && chain_member (r, BLOCK_VARS (outer))) finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl)); current_function_return_value = NULL_TREE; @@ -11094,10 +11096,6 @@ cxx_maybe_build_cleanup (tree decl) void finish_stmt (void) { - /* Always assume this statement was not an expression statement. If - it actually was an expression statement, its our callers - responsibility to fix this up. */ - last_expr_type = NULL_TREE; } /* DECL was originally constructed as a non-static member function, diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 57e3224e91f..8157950371b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1970,7 +1970,7 @@ start_objects (int method_type, int initp) DECL_GLOBAL_DTOR_P (current_function_decl) = 1; DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1; - body = begin_compound_stmt (/*has_no_scope=*/false); + body = begin_compound_stmt (BCS_FN_BODY); /* We cannot allow these functions to be elided, even if they do not have external linkage. And, there's no point in deferring @@ -2127,7 +2127,7 @@ start_static_storage_duration_function (unsigned count) SF_PRE_PARSED); /* Set up the scope of the outermost block in the function. */ - body = begin_compound_stmt (/*has_no_scope=*/false); + body = begin_compound_stmt (BCS_FN_BODY); /* This function must not be deferred because we are depending on its compilation to tell us what is TREE_SYMBOL_REFERENCED. */ @@ -2307,7 +2307,7 @@ static void finish_static_initialization_or_destruction (tree guard_if_stmt) { finish_then_clause (guard_if_stmt); - finish_if_stmt (); + finish_if_stmt (guard_if_stmt); /* Now that we're done with DECL we don't need to pretend to be a member of its class any longer. */ diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 69813d3ac7b..7e6e54e0def 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */ #include "except.h" #include "toplev.h" #include "tree-inline.h" +#include "tree-iterator.h" static void push_eh_cleanup (tree); static tree prepare_eh_type (tree); @@ -51,7 +52,6 @@ static tree wrap_cleanups_r (tree *, int *, void *); static int complete_ptr_ref_or_void_ptr_p (tree, tree); static bool is_admissible_throw_operand (tree); static int can_convert_eh (tree, tree); -static void check_handlers_1 (tree, tree); static tree cp_protect_cleanup_actions (void); /* Sets up all the global eh stuff that needs to be initialized at the @@ -462,6 +462,7 @@ begin_eh_spec_block (void) { tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); + EH_SPEC_STMTS (r) = push_stmt_list (); return r; } @@ -470,7 +471,7 @@ finish_eh_spec_block (tree raw_raises, tree eh_spec_block) { tree raises; - RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block)); + EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block)); /* Strip cv quals, etc, from the specification types. */ for (raises = NULL_TREE; @@ -874,47 +875,57 @@ can_convert_eh (tree to, tree from) return 0; } -/* Check whether any of HANDLERS are shadowed by another handler accepting - TYPE. Note that the shadowing may not be complete; even if an exception - of type B would be caught by a handler for A, there could be a derived - class C for which A is an ambiguous base but B is not, so the handler - for B would catch an exception of type C. */ +/* Check whether any of the handlers in I are shadowed by another handler + accepting TYPE. Note that the shadowing may not be complete; even if + an exception of type B would be caught by a handler for A, there could + be a derived class C for which A is an ambiguous base but B is not, so + the handler for B would catch an exception of type C. */ static void -check_handlers_1 (tree master, tree handlers) +check_handlers_1 (tree master, tree_stmt_iterator i) { tree type = TREE_TYPE (master); - tree handler; - for (handler = handlers; handler; handler = TREE_CHAIN (handler)) - if (TREE_TYPE (handler) - && can_convert_eh (type, TREE_TYPE (handler))) - { - warning ("%Hexception of type `%T' will be caught", - EXPR_LOCUS (handler), TREE_TYPE (handler)); - warning ("%H by earlier handler for `%T'", - EXPR_LOCUS (master), type); - break; - } + for (; !tsi_end_p (i); tsi_next (&i)) + { + tree handler = tsi_stmt (i); + if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler))) + { + warning ("%Hexception of type `%T' will be caught", + EXPR_LOCUS (handler), TREE_TYPE (handler)); + warning ("%H by earlier handler for `%T'", + EXPR_LOCUS (master), type); + break; + } + } } -/* Given a chain of HANDLERs, make sure that they're OK. */ +/* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */ void check_handlers (tree handlers) { - tree handler; - int save_line = input_line; - - for (handler = handlers; handler; handler = TREE_CHAIN (handler)) - { - if (TREE_CHAIN (handler) == NULL_TREE) - /* No more handlers; nothing to shadow. */; - else if (TREE_TYPE (handler) == NULL_TREE) - pedwarn ("%H`...' handler must be the last handler for" - " its try block", EXPR_LOCUS (handler)); - else - check_handlers_1 (handler, TREE_CHAIN (handler)); - } - input_line = save_line; + tree_stmt_iterator i; + + /* If we don't have a STATEMENT_LIST, then we've just got one + handler, and thus nothing to warn about. */ + if (TREE_CODE (handlers) != STATEMENT_LIST) + return; + + i = tsi_start (handlers); + if (!tsi_end_p (i)) + while (1) + { + tree handler = tsi_stmt (i); + tsi_next (&i); + + /* No more handlers; nothing to shadow. */ + if (tsi_end_p (i)) + break; + if (TREE_TYPE (handler) == NULL_TREE) + pedwarn ("%H`...' handler must be the last handler for" + " its try block", EXPR_LOCUS (handler)); + else + check_handlers_1 (handler, i); + } } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 1c003566108..6c886238ea5 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -72,7 +72,7 @@ begin_init_stmts (tree *stmt_expr_p, tree *compound_stmt_p) bool is_global = !building_stmt_tree (); *stmt_expr_p = begin_stmt_expr (); - *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/true); + *compound_stmt_p = begin_compound_stmt (BCS_NO_SCOPE); return is_global; } @@ -826,7 +826,6 @@ static void construct_virtual_base (tree vbase, tree arguments) { tree inner_if_stmt; - tree compound_stmt; tree exp; tree flag; @@ -847,7 +846,6 @@ construct_virtual_base (tree vbase, tree arguments) flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl)); inner_if_stmt = begin_if_stmt (); finish_if_stmt_cond (flag, inner_if_stmt); - compound_stmt = begin_compound_stmt (/*has_no_scope=*/true); /* Compute the location of the virtual base. If we're constructing virtual bases, then we must be the most derived @@ -857,9 +855,8 @@ construct_virtual_base (tree vbase, tree arguments) expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, LOOKUP_COMPLAIN); - finish_compound_stmt (compound_stmt); finish_then_clause (inner_if_stmt); - finish_if_stmt (); + finish_if_stmt (inner_if_stmt); expand_cleanup_for_base (vbase, flag); } @@ -2526,7 +2523,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) tree compound_stmt; int destroy_temps; tree try_block = NULL_TREE; - tree try_body = NULL_TREE; int num_initialized_elts = 0; bool is_global; @@ -2605,7 +2601,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) && from_array != 2) { try_block = begin_try_block (); - try_body = begin_compound_stmt (/*has_no_scope=*/true); } if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) @@ -2674,7 +2669,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) /* If the ITERATOR is equal to -1, then we don't have to loop; we've already initialized all the elements. */ tree for_stmt; - tree for_body; tree elt_init; for_stmt = begin_for_stmt (); @@ -2685,9 +2679,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0), for_stmt); - /* Otherwise, loop through the elements. */ - for_body = begin_compound_stmt (/*has_no_scope=*/true); - if (from_array) { tree to = build1 (INDIRECT_REF, type, base); @@ -2727,7 +2718,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) if (base2) finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0)); - finish_compound_stmt (for_body); finish_for_stmt (for_stmt); } @@ -2747,7 +2737,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) type = strip_array_types (type); } - finish_compound_stmt (try_body); finish_cleanup_try_block (try_block); e = build_vec_delete_1 (rval, m, type, sfk_base_destructor, /*use_global_delete=*/0); @@ -2756,7 +2745,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) /* The value of the array initialization is the array itself, RVAL is a pointer to the first element. */ - finish_stmt_expr_expr (rval); + finish_stmt_expr_expr (rval, stmt_expr); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 01e5313f6de..364cc0688b3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -621,7 +621,7 @@ do_build_assign_ref (tree fndecl) tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree compound_stmt; - compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); + compound_stmt = begin_compound_stmt (0); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) @@ -778,7 +778,7 @@ synthesize_method (tree fndecl) if (need_body) { tree compound_stmt; - compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); + compound_stmt = begin_compound_stmt (BCS_FN_BODY); finish_compound_stmt (compound_stmt); } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 3e42f3b5dce..401f6505d0c 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1433,8 +1433,8 @@ maybe_push_cleanup_level (tree type) && current_binding_level->more_cleanups_ok == 0) { begin_scope (sk_cleanup, NULL); + current_binding_level->statement_list = push_stmt_list (); clear_last_expr (); - add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1); } } diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 044f2895c0c..49046e893fe 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -205,6 +205,10 @@ struct cp_binding_level GTY(()) TREE_LIST; the TREE_VALUE is the actual declaration. */ tree dead_vars_from_for; + /* STATEMENT_LIST for statements in this binding contour. + Only used at present for SK_CLEANUP temporary bindings. */ + tree statement_list; + /* Binding depth at which this level began. */ int binding_depth; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bc736891fef..428762cb437 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1415,15 +1415,15 @@ static tree cp_parser_builtin_offsetof /* Statements [gram.stmt.stmt] */ static void cp_parser_statement - (cp_parser *, bool); + (cp_parser *, tree); static tree cp_parser_labeled_statement - (cp_parser *, bool); + (cp_parser *, tree); static tree cp_parser_expression_statement - (cp_parser *, bool); + (cp_parser *, tree); static tree cp_parser_compound_statement - (cp_parser *, bool); + (cp_parser *, tree, bool); static void cp_parser_statement_seq_opt - (cp_parser *, bool); + (cp_parser *, tree); static tree cp_parser_selection_statement (cp_parser *); static tree cp_parser_condition @@ -2542,7 +2542,7 @@ cp_parser_primary_expression (cp_parser *parser, /* Start the statement-expression. */ expr = begin_stmt_expr (); /* Parse the compound-statement. */ - cp_parser_compound_statement (parser, true); + cp_parser_compound_statement (parser, expr, false); /* Finish up. */ expr = finish_stmt_expr (expr, false); } @@ -5615,7 +5615,7 @@ cp_parser_builtin_offsetof (cp_parser *parser) try-block */ static void -cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) +cp_parser_statement (cp_parser* parser, tree in_statement_expr) { tree statement; cp_token *token; @@ -5638,7 +5638,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) case RID_CASE: case RID_DEFAULT: statement = cp_parser_labeled_statement (parser, - in_statement_expr_p); + in_statement_expr); break; case RID_IF: @@ -5675,11 +5675,11 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) labeled-statement. */ token = cp_lexer_peek_nth_token (parser->lexer, 2); if (token->type == CPP_COLON) - statement = cp_parser_labeled_statement (parser, in_statement_expr_p); + statement = cp_parser_labeled_statement (parser, in_statement_expr); } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) - statement = cp_parser_compound_statement (parser, false); + statement = cp_parser_compound_statement (parser, NULL, false); /* Everything else must be a declaration-statement or an expression-statement. Try for the declaration-statement @@ -5697,7 +5697,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) return; } /* Look for an expression-statement instead. */ - statement = cp_parser_expression_statement (parser, in_statement_expr_p); + statement = cp_parser_expression_statement (parser, in_statement_expr); } /* Set the line number for the statement. */ @@ -5724,7 +5724,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p) an ordinary label, returns a LABEL_STMT. */ static tree -cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p) +cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr) { cp_token *token; tree statement = error_mark_node; @@ -5792,7 +5792,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p) /* Require the `:' token. */ cp_parser_require (parser, CPP_COLON, "`:'"); /* Parse the labeled statement. */ - cp_parser_statement (parser, in_statement_expr_p); + cp_parser_statement (parser, in_statement_expr); /* Return the label, in the case of a `case' or `default' label. */ return statement; @@ -5809,7 +5809,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p) expression statement. */ static tree -cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p) +cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) { tree statement = NULL_TREE; @@ -5821,12 +5821,12 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p) /* Consume the final `;'. */ cp_parser_consume_semicolon_at_end_of_statement (parser); - if (in_statement_expr_p + if (in_statement_expr && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) { /* This is the final expression statement of a statement expression. */ - statement = finish_stmt_expr_expr (statement); + statement = finish_stmt_expr_expr (statement, in_statement_expr); } else if (statement) statement = finish_expr_stmt (statement); @@ -5844,7 +5844,8 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p) Returns a COMPOUND_STMT representing the statement. */ static tree -cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p) +cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, + bool in_try) { tree compound_stmt; @@ -5852,9 +5853,9 @@ cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p) if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) return error_mark_node; /* Begin the compound-statement. */ - compound_stmt = begin_compound_stmt (/*has_no_scope=*/false); + compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0); /* Parse an (optional) statement-seq. */ - cp_parser_statement_seq_opt (parser, in_statement_expr_p); + cp_parser_statement_seq_opt (parser, in_statement_expr); /* Finish the compound-statement. */ finish_compound_stmt (compound_stmt); /* Consume the `}'. */ @@ -5870,7 +5871,7 @@ cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p) statement-seq [opt] statement */ static void -cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p) +cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) { /* Scan statements until there aren't any more. */ while (true) @@ -5881,7 +5882,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p) break; /* Parse the statement. */ - cp_parser_statement (parser, in_statement_expr_p); + cp_parser_statement (parser, in_statement_expr); } } @@ -5935,35 +5936,30 @@ cp_parser_selection_statement (cp_parser* parser) if (keyword == RID_IF) { - tree then_stmt; - /* Add the condition. */ finish_if_stmt_cond (condition, statement); /* Parse the then-clause. */ - then_stmt = cp_parser_implicitly_scoped_statement (parser); + cp_parser_implicitly_scoped_statement (parser); finish_then_clause (statement); /* If the next token is `else', parse the else-clause. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE)) { - tree else_stmt; - /* Consume the `else' keyword. */ cp_lexer_consume_token (parser->lexer); + begin_else_clause (statement); /* Parse the else-clause. */ - else_stmt - = cp_parser_implicitly_scoped_statement (parser); + cp_parser_implicitly_scoped_statement (parser); finish_else_clause (statement); } /* Now we're all done with the if-statement. */ - finish_if_stmt (); + finish_if_stmt (statement); } else { - tree body; bool in_switch_statement_p; /* Add the condition. */ @@ -5972,7 +5968,7 @@ cp_parser_selection_statement (cp_parser* parser) /* Parse the body of the switch-statement. */ in_switch_statement_p = parser->in_switch_statement_p; parser->in_switch_statement_p = true; - body = cp_parser_implicitly_scoped_statement (parser); + cp_parser_implicitly_scoped_statement (parser); parser->in_switch_statement_p = in_switch_statement_p; /* Now we're all done with the switch-statement. */ @@ -6365,7 +6361,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser) if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) { /* Create a compound-statement. */ - statement = begin_compound_stmt (/*has_no_scope=*/false); + statement = begin_compound_stmt (0); /* Parse the dependent-statement. */ cp_parser_statement (parser, false); /* Finish the dummy compound-statement. */ @@ -6373,7 +6369,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser) } /* Otherwise, we simply parse the statement directly. */ else - statement = cp_parser_compound_statement (parser, false); + statement = cp_parser_compound_statement (parser, NULL, false); /* Return the statement. */ return statement; @@ -6387,21 +6383,17 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser) static void cp_parser_already_scoped_statement (cp_parser* parser) { - /* If the token is not a `{', then we must take special action. */ - if (cp_lexer_next_token_is_not(parser->lexer, CPP_OPEN_BRACE)) + /* If the token is a `{', then we must take special action. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + cp_parser_statement (parser, false); + else { - tree statement; - - /* Create a compound-statement. */ - statement = begin_compound_stmt (/*has_no_scope=*/true); - /* Parse the dependent-statement. */ - cp_parser_statement (parser, false); - /* Finish the dummy compound-statement. */ - finish_compound_stmt (statement); + /* Avoid calling cp_parser_compound_statement, so that we + don't create a new scope. Do everything else by hand. */ + cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); + cp_parser_statement_seq_opt (parser, false); + cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); } - /* Otherwise, we simply parse the statement directly. */ - else - cp_parser_statement (parser, false); } /* Declarations [gram.dcl.dcl] */ @@ -11618,7 +11610,7 @@ cp_parser_parameter_declaration (cp_parser *parser, static void cp_parser_function_body (cp_parser *parser) { - cp_parser_compound_statement (parser, false); + cp_parser_compound_statement (parser, NULL, false); } /* Parse a ctor-initializer-opt followed by a function-body. Return @@ -13265,7 +13257,7 @@ cp_parser_try_block (cp_parser* parser) cp_parser_require_keyword (parser, RID_TRY, "`try'"); try_block = begin_try_block (); - cp_parser_compound_statement (parser, false); + cp_parser_compound_statement (parser, NULL, true); finish_try_block (try_block); cp_parser_handler_seq (parser); finish_handler_sequence (try_block); @@ -13341,7 +13333,7 @@ cp_parser_handler (cp_parser* parser) declaration = cp_parser_exception_declaration (parser); finish_handler_parms (declaration, handler); cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); - cp_parser_compound_statement (parser, false); + cp_parser_compound_statement (parser, NULL, false); finish_handler (handler); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ff96eaa83c7..c93184aa0c7 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */ #include "toplev.h" #include "rtl.h" #include "timevar.h" +#include "tree-iterator.h" /* The type of functions taking a tree, and some additional data, and returning an int. */ @@ -7615,22 +7616,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) in_decl), NULL_TREE); - case STMT_EXPR: - /* This processing should really occur in tsubst_expr. However, - tsubst_expr does not recurse into expressions, since it - assumes that there aren't any statements inside them. So, we - need to expand the STMT_EXPR here. */ - if (!processing_template_decl) - { - tree stmt_expr = begin_stmt_expr (); - - tsubst_expr (STMT_EXPR_STMT (t), args, - complain | tf_stmt_expr_cmpd, in_decl); - return finish_stmt_expr (stmt_expr, false); - } - - return t; - case COND_EXPR: case MODOP_EXPR: case PSEUDO_DTOR_EXPR: @@ -7752,20 +7737,26 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) static tree tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) { + /* Live only within one (recursive) call to tsubst_expr. We use + this to pass the statement expression node from the STMT_EXPR + to the EXPR_STMT that is its result. */ + static tree cur_stmt_expr; + tree stmt, tmp; - tsubst_flags_t stmt_expr - = complain & (tf_stmt_expr_cmpd | tf_stmt_expr_body); - complain ^= stmt_expr; if (t == NULL_TREE || t == error_mark_node) return t; - if (!STATEMENT_CODE_P (TREE_CODE (t))) - return tsubst_copy_and_build (t, args, complain, in_decl, - /*function_p=*/false); - switch (TREE_CODE (t)) { + case STATEMENT_LIST: + { + tree_stmt_iterator i; + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) + tsubst_expr (tsi_stmt (i), args, complain, in_decl); + break; + } + case CTOR_INITIALIZER: prep_stmt (t); finish_mem_initializers (tsubst_initializer_list @@ -7778,6 +7769,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) args, complain, in_decl)); break; + case STMT_EXPR: + { + tree old_stmt_expr = cur_stmt_expr; + tree stmt_expr = begin_stmt_expr (); + + cur_stmt_expr = stmt_expr; + tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl); + stmt_expr = finish_stmt_expr (stmt_expr, false); + cur_stmt_expr = old_stmt_expr; + + return stmt_expr; + } + case EXPR_STMT: { tree r; @@ -7785,8 +7789,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) prep_stmt (t); r = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl); - if (stmt_expr & tf_stmt_expr_body && !TREE_CHAIN (t)) - finish_stmt_expr_expr (r); + if (EXPR_STMT_STMT_EXPR_RESULT (t)) + finish_stmt_expr_expr (r, cur_stmt_expr); else finish_expr_stmt (r); break; @@ -7861,12 +7865,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) } /* A DECL_STMT can also be used as an expression, in the condition - clause of an if/for/while construct. If we aren't followed by - another statement, return our decl. */ - if (TREE_CHAIN (t) == NULL_TREE) - return decl; + clause of an if/for/while construct. */ + return decl; } - break; case FOR_STMT: { @@ -7916,21 +7917,17 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) finish_if_stmt_cond (tsubst_expr (IF_COND (t), args, complain, in_decl), stmt); + tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl); + finish_then_clause (stmt); - if (tmp = THEN_CLAUSE (t), tmp) - { - tsubst_expr (tmp, args, complain, in_decl); - finish_then_clause (stmt); - } - - if (tmp = ELSE_CLAUSE (t), tmp) + if (ELSE_CLAUSE (t)) { - begin_else_clause (); - tsubst_expr (tmp, args, complain, in_decl); + begin_else_clause (stmt); + tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl); finish_else_clause (stmt); } - finish_if_stmt (); + finish_if_stmt (stmt); } break; @@ -7940,11 +7937,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (COMPOUND_STMT_BODY_BLOCK (t)) stmt = begin_function_body (); else - stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)); + stmt = begin_compound_stmt (COMPOUND_STMT_TRY_BLOCK (t) + ? BCS_TRY_BLOCK : 0); - tsubst_expr (COMPOUND_BODY (t), args, - complain | ((stmt_expr & tf_stmt_expr_cmpd) << 1), - in_decl); + tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl); if (COMPOUND_STMT_BODY_BLOCK (t)) finish_function_body (stmt); @@ -8053,7 +8049,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) stmt = begin_handler (); if (HANDLER_PARMS (t)) { - decl = DECL_STMT_DECL (HANDLER_PARMS (t)); + decl = HANDLER_PARMS (t); decl = tsubst (decl, args, complain, in_decl); /* Prevent instantiate_decl from trying to instantiate this variable. We've already done all that needs to be @@ -8074,10 +8070,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) break; default: + if (!STATEMENT_CODE_P (TREE_CODE (t))) + return tsubst_copy_and_build (t, args, complain, in_decl, + /*function_p=*/false); abort (); } - return tsubst_expr (TREE_CHAIN (t), args, complain | stmt_expr, in_decl); + return NULL_TREE; } /* T is a postfix-expression that is not being used in a function diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2fea1c8b86c..eeb66c59559 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -44,6 +44,7 @@ #include "debug.h" #include "diagnostic.h" #include "cgraph.h" +#include "tree-iterator.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -60,23 +61,6 @@ static void emit_associated_thunks (tree); static tree finalize_nrv_r (tree *, int *, void *); -/* Finish processing the COND, the SUBSTMT condition for STMT. */ - -#define FINISH_COND(COND, STMT, SUBSTMT) \ - do { \ - if (last_tree != (STMT)) \ - { \ - RECHAIN_STMTS (STMT, SUBSTMT); \ - if (!processing_template_decl) \ - { \ - (COND) = build_tree_list (SUBSTMT, COND); \ - (SUBSTMT) = (COND); \ - } \ - } \ - else \ - (SUBSTMT) = (COND); \ - } while (0) - /* Deferred Access Checking Overview --------------------------------- @@ -332,45 +316,99 @@ anon_aggr_type_p (tree node) /* Finish a scope. */ -tree -do_poplevel (void) +static tree +do_poplevel (tree stmt_list) { - tree block = NULL_TREE; + tree block = NULL; if (stmts_are_full_exprs_p ()) - { - tree scope_stmts = NULL_TREE; + block = poplevel (kept_level_p (), 1, 0); - block = poplevel (kept_level_p (), 1, 0); - if (!processing_template_decl) - { - /* This needs to come after the poplevel so that partial scopes - are properly nested. */ - scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); - if (block) - { - SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block; - SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block; - } - } + stmt_list = pop_stmt_list (stmt_list); + + if (!processing_template_decl) + { + stmt_list = c_build_bind_expr (block, stmt_list); + /* ??? See c_end_compound_stmt re statement expressions. */ } - return block; + return stmt_list; } /* Begin a new scope. */ -void +static tree do_pushlevel (scope_kind sk) { + tree ret = push_stmt_list (); if (stmts_are_full_exprs_p ()) + begin_scope (sk, NULL); + return ret; +} + +/* Finish processing a conditional. COND contains the raw expression; + STMT_P is a stacked statement list that will contain any other stmts + emitting during the processing of this conditional. Place the + resulting conditional back in STMT_P. */ + +static void +finish_cond (tree cond, tree *stmt_p) +{ + tree stmt = *stmt_p; + stmt = pop_stmt_list (stmt); + if (TREE_SIDE_EFFECTS (stmt)) + { + /* If stmt is set, it will be a DECL_STMT. When processing a template, + using this is enough, because tsubst_expr considers the result of a + DECL_STMT to be the DECL. When generating real code, we build a + funny little TREE_LIST thingy that's handled by the gimplifier. */ + /* ??? The object of this thingy is to get the DECL declared in the + proper scope. Seems like this oughtn't be terribly hard with the + new explicit uses of BIND_EXPR and such. */ + if (processing_template_decl) + { + stmt = expr_only (stmt); + if (!stmt) + abort (); + } + else + stmt = build_tree_list (stmt, cond); + } + else + stmt = cond; + *stmt_p = stmt; +} + +/* If *COND_P specifies a conditional with a declaration, transform the + loop such that + while (A x = 42) { } + for (; A x = 42;) { } + becomes + while (true) { A x = 42; if (!x) break; } + for (;;) { A x = 42; if (!x) break; } + The statement list for the loop body should have been pushed. */ + +static void +simplify_loop_decl_cond (tree *cond_p) +{ + tree cond = *cond_p; + if (TREE_CODE (cond) == TREE_LIST) { - if (!processing_template_decl) - add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); - begin_scope (sk, NULL); + tree if_stmt; + + *cond_p = boolean_true_node; + + if_stmt = begin_if_stmt (); + add_stmt (TREE_PURPOSE (cond)); + cond = build_unary_op (TRUTH_NOT_EXPR, TREE_VALUE (cond), 0); + finish_if_stmt_cond (cond, if_stmt); + finish_break_stmt (); + finish_then_clause (if_stmt); + finish_if_stmt (if_stmt); } } + /* Finish a goto-statement. */ tree @@ -432,8 +470,12 @@ finish_expr_stmt (tree expr) expr = convert_to_void (expr, "statement"); else if (!type_dependent_expression_p (expr)) convert_to_void (build_non_dependent_expr (expr), "statement"); - - r = add_stmt (build_stmt (EXPR_STMT, expr)); + + /* Simplification of inner statement expressions, compound exprs, + etc can result in the us already having an EXPR_STMT. */ + if (TREE_CODE (expr) != EXPR_STMT) + expr = build_stmt (EXPR_STMT, expr); + r = add_stmt (expr); } finish_stmt (); @@ -448,10 +490,12 @@ finish_expr_stmt (tree expr) tree begin_if_stmt (void) { - tree r; - do_pushlevel (sk_block); + tree r, scope; + scope = do_pushlevel (sk_block); r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE); + TREE_CHAIN (r) = scope; add_stmt (r); + IF_COND (r) = push_stmt_list (); return r; } @@ -462,7 +506,8 @@ void finish_if_stmt_cond (tree cond, tree if_stmt) { cond = maybe_convert_cond (cond); - FINISH_COND (cond, if_stmt, IF_COND (if_stmt)); + finish_cond (cond, &IF_COND (if_stmt)); + THEN_CLAUSE (if_stmt) = push_stmt_list (); } /* Finish the then-clause of an if-statement, which may be given by @@ -471,15 +516,16 @@ finish_if_stmt_cond (tree cond, tree if_stmt) tree finish_then_clause (tree if_stmt) { - RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt)); + THEN_CLAUSE (if_stmt) = pop_stmt_list (THEN_CLAUSE (if_stmt)); return if_stmt; } /* Begin the else-clause of an if-statement. */ -void -begin_else_clause (void) +void +begin_else_clause (tree if_stmt) { + ELSE_CLAUSE (if_stmt) = push_stmt_list (); } /* Finish the else-clause of an if-statement, which may be given by @@ -488,16 +534,18 @@ begin_else_clause (void) void finish_else_clause (tree if_stmt) { - RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt)); + ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt)); } /* Finish an if-statement. */ void -finish_if_stmt (void) +finish_if_stmt (tree if_stmt) { + tree scope = TREE_CHAIN (if_stmt); + TREE_CHAIN (if_stmt) = NULL; + add_stmt (do_poplevel (scope)); finish_stmt (); - do_poplevel (); } /* Begin a while-statement. Returns a newly created WHILE_STMT if @@ -509,7 +557,8 @@ begin_while_stmt (void) tree r; r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE); add_stmt (r); - do_pushlevel (sk_block); + WHILE_BODY (r) = do_pushlevel (sk_block); + WHILE_COND (r) = push_stmt_list (); return r; } @@ -520,29 +569,8 @@ void finish_while_stmt_cond (tree cond, tree while_stmt) { cond = maybe_convert_cond (cond); - if (processing_template_decl) - /* Don't mess with condition decls in a template. */ - FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt)); - else if (getdecls () == NULL_TREE) - /* It was a simple condition; install it. */ - WHILE_COND (while_stmt) = cond; - else - { - /* If there was a declaration in the condition, we can't leave it - there; transform - while (A x = 42) { } - to - while (true) { A x = 42; if (!x) break; } */ - tree if_stmt; - WHILE_COND (while_stmt) = boolean_true_node; - - if_stmt = begin_if_stmt (); - cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0); - finish_if_stmt_cond (cond, if_stmt); - finish_break_stmt (); - finish_then_clause (if_stmt); - finish_if_stmt (); - } + finish_cond (cond, &WHILE_COND (while_stmt)); + simplify_loop_decl_cond (&WHILE_COND (while_stmt)); } /* Finish a while-statement, which may be given by WHILE_STMT. */ @@ -550,8 +578,7 @@ finish_while_stmt_cond (tree cond, tree while_stmt) void finish_while_stmt (tree while_stmt) { - do_poplevel (); - RECHAIN_STMTS (while_stmt, WHILE_BODY (while_stmt)); + WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt)); finish_stmt (); } @@ -563,6 +590,7 @@ begin_do_stmt (void) { tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE); add_stmt (r); + DO_BODY (r) = push_stmt_list (); return r; } @@ -571,7 +599,7 @@ begin_do_stmt (void) void finish_do_body (tree do_stmt) { - RECHAIN_STMTS (do_stmt, DO_BODY (do_stmt)); + DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt)); } /* Finish a do-statement, which may be given by DO_STMT, and whose @@ -620,10 +648,9 @@ begin_for_stmt (void) r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); - NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0; - if (NEW_FOR_SCOPE_P (r)) - do_pushlevel (sk_for); - add_stmt (r); + + if (flag_new_for_scope > 0) + TREE_CHAIN (r) = do_pushlevel (sk_for); return r; } @@ -634,9 +661,9 @@ begin_for_stmt (void) void finish_for_init_stmt (tree for_stmt) { - if (last_tree != for_stmt) - RECHAIN_STMTS (for_stmt, FOR_INIT_STMT (for_stmt)); - do_pushlevel (sk_block); + add_stmt (for_stmt); + FOR_BODY (for_stmt) = do_pushlevel (sk_block); + FOR_COND (for_stmt) = push_stmt_list (); } /* Finish the COND of a for-statement, which may be given by @@ -646,29 +673,9 @@ void finish_for_cond (tree cond, tree for_stmt) { cond = maybe_convert_cond (cond); - if (processing_template_decl) - /* Don't mess with condition decls in a template. */ - FINISH_COND (cond, for_stmt, FOR_COND (for_stmt)); - else if (getdecls () == NULL_TREE) - /* It was a simple condition; install it. */ - FOR_COND (for_stmt) = cond; - else - { - /* If there was a declaration in the condition, we can't leave it - there; transform - for (; A x = 42;) { } - to - for (;;) { A x = 42; if (!x) break; } */ - tree if_stmt; - FOR_COND (for_stmt) = NULL_TREE; - - if_stmt = begin_if_stmt (); - cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0); - finish_if_stmt_cond (cond, if_stmt); - finish_break_stmt (); - finish_then_clause (if_stmt); - finish_if_stmt (); - } + finish_cond (cond, &FOR_COND (for_stmt)); + if (FOR_COND (for_stmt)) + simplify_loop_decl_cond (&FOR_COND (for_stmt)); } /* Finish the increment-EXPRESSION in a for-statement, which may be @@ -694,11 +701,16 @@ finish_for_expr (tree expr, tree for_stmt) void finish_for_stmt (tree for_stmt) { + FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt)); + /* Pop the scope for the body of the loop. */ - do_poplevel (); - RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt)); - if (NEW_FOR_SCOPE_P (for_stmt)) - do_poplevel (); + if (flag_new_for_scope > 0) + { + tree scope = TREE_CHAIN (for_stmt); + TREE_CHAIN (for_stmt) = NULL; + add_stmt (do_poplevel (scope)); + } + finish_stmt (); } @@ -724,10 +736,16 @@ finish_continue_stmt (void) tree begin_switch_stmt (void) { - tree r; - do_pushlevel (sk_block); + tree r, scope; + r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE); + + scope = do_pushlevel (sk_block); + TREE_CHAIN (r) = scope; + add_stmt (r); + SWITCH_COND (r) = push_stmt_list (); + return r; } @@ -770,9 +788,10 @@ finish_switch_cond (tree cond, tree switch_stmt) cond = index; } } - FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt)); + finish_cond (cond, &SWITCH_COND (switch_stmt)); SWITCH_TYPE (switch_stmt) = orig_type; push_switch (switch_stmt); + SWITCH_BODY (switch_stmt) = push_stmt_list (); } /* Finish the body of a switch-statement, which may be given by @@ -781,10 +800,15 @@ finish_switch_cond (tree cond, tree switch_stmt) void finish_switch_stmt (tree switch_stmt) { - RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt)); + tree scope; + + SWITCH_BODY (switch_stmt) = pop_stmt_list (SWITCH_BODY (switch_stmt)); pop_switch (); finish_stmt (); - do_poplevel (); + + scope = TREE_CHAIN (switch_stmt); + TREE_CHAIN (switch_stmt) = NULL; + add_stmt (do_poplevel (scope)); } /* Begin a try-block. Returns a newly-created TRY_BLOCK if @@ -795,6 +819,7 @@ begin_try_block (void) { tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE); add_stmt (r); + TRY_STMTS (r) = push_stmt_list (); return r; } @@ -803,9 +828,8 @@ begin_try_block (void) tree begin_function_try_block (void) { - tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE); + tree r = begin_try_block (); FN_TRY_BLOCK_P (r) = 1; - add_stmt (r); return r; } @@ -814,7 +838,8 @@ begin_function_try_block (void) void finish_try_block (tree try_block) { - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block)); + TRY_HANDLERS (try_block) = push_stmt_list (); } /* Finish the body of a cleanup try-block, which may be given by @@ -823,7 +848,7 @@ finish_try_block (tree try_block) void finish_cleanup_try_block (tree try_block) { - RECHAIN_STMTS (try_block, TRY_STMTS (try_block)); + TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block)); } /* Finish an implicitly generated try-block, with a cleanup is given @@ -841,16 +866,9 @@ finish_cleanup (tree cleanup, tree try_block) void finish_function_try_block (tree 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)); + finish_try_block (try_block); + /* FIXME : something queer about CTOR_INITIALIZER somehow following + the try block, but moving it inside. */ in_function_try_handler = 1; } @@ -860,7 +878,7 @@ finish_function_try_block (tree try_block) void finish_handler_sequence (tree try_block) { - RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); + TRY_HANDLERS (try_block) = pop_stmt_list (TRY_HANDLERS (try_block)); check_handlers (TRY_HANDLERS (try_block)); } @@ -870,8 +888,7 @@ void finish_function_handler_sequence (tree try_block) { in_function_try_handler = 0; - RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block)); - check_handlers (TRY_HANDLERS (try_block)); + finish_handler_sequence (try_block); } /* Begin a handler. Returns a HANDLER if appropriate. */ @@ -880,11 +897,14 @@ tree begin_handler (void) { tree r; + r = build_stmt (HANDLER, NULL_TREE, NULL_TREE); add_stmt (r); + /* Create a binding level for the eh_info and the exception object cleanup. */ - do_pushlevel (sk_catch); + HANDLER_BODY (r) = do_pushlevel (sk_catch); + return r; } @@ -902,8 +922,7 @@ finish_handler_parms (tree decl, tree handler) { decl = pushdecl (decl); decl = push_template_decl (decl); - add_decl_stmt (decl); - RECHAIN_STMTS (handler, HANDLER_PARMS (handler)); + HANDLER_PARMS (handler) = decl; type = TREE_TYPE (decl); } } @@ -923,8 +942,7 @@ finish_handler (tree handler) { if (!processing_template_decl) expand_end_catch_block (); - do_poplevel (); - RECHAIN_STMTS (handler, HANDLER_BODY (handler)); + HANDLER_BODY (handler) = do_poplevel (HANDLER_BODY (handler)); } /* Begin a compound-statement. If HAS_NO_SCOPE is true, the @@ -932,58 +950,50 @@ finish_handler (tree handler) COMPOUND_STMT. */ tree -begin_compound_stmt (bool has_no_scope) +begin_compound_stmt (unsigned int flags) { - tree r; - int is_try = 0; - - r = build_stmt (COMPOUND_STMT, NULL_TREE); - - if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK) - is_try = 1; - - add_stmt (r); - if (has_no_scope) - COMPOUND_STMT_NO_SCOPE (r) = 1; + tree r; - last_expr_type = NULL_TREE; + if (flags & BCS_NO_SCOPE) + { + r = push_stmt_list (); + STATEMENT_LIST_NO_SCOPE (r) = 1; - if (!has_no_scope) - do_pushlevel (is_try ? sk_try : sk_block); + /* Normally, we try hard to keep the BLOCK for a statement-expression. + But, if it's a statement-expression with a scopeless block, there's + nothing to keep, and we don't want to accidentally keep a block + *inside* the scopeless block. */ + keep_next_level (false); + } else - /* Normally, we try hard to keep the BLOCK for a - statement-expression. But, if it's a statement-expression with - a scopeless block, there's nothing to keep, and we don't want - to accidentally keep a block *inside* the scopeless block. */ - keep_next_level (false); + r = do_pushlevel (flags & BCS_TRY_BLOCK ? sk_try : sk_block); + + if (flags & BCS_FN_BODY || processing_template_decl) + { + r = build (COMPOUND_STMT, NULL_TREE, r); + COMPOUND_STMT_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0; + COMPOUND_STMT_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0; + TREE_SIDE_EFFECTS (r) = 1; + } return r; } /* Finish a compound-statement, which is given by COMPOUND_STMT. */ -tree -finish_compound_stmt (tree compound_stmt) +void +finish_compound_stmt (tree stmt) { - tree r; - tree t; - - if (COMPOUND_STMT_NO_SCOPE (compound_stmt)) - r = NULL_TREE; + if (TREE_CODE (stmt) == COMPOUND_STMT) + COMPOUND_BODY (stmt) = do_poplevel (COMPOUND_BODY (stmt)); + else if (STATEMENT_LIST_NO_SCOPE (stmt)) + stmt = pop_stmt_list (stmt); else - r = do_poplevel (); - - RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt)); + stmt = do_poplevel (stmt); - /* When we call finish_stmt we will lose LAST_EXPR_TYPE. But, since - the precise purpose of that variable is store the type of the - last expression statement within the last compound statement, we - preserve the value. */ - t = last_expr_type; + /* ??? See c_end_compound_stmt wrt statement expressions. */ + add_stmt (stmt); finish_stmt (); - last_expr_type = t; - - return r; } /* Finish an asm-statement, whose components are a STRING, some @@ -1090,7 +1100,7 @@ finish_label_decl (tree name) void finish_decl_cleanup (tree decl, tree cleanup) { - add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup)); + push_cleanup (decl, cleanup, false); } /* If the current scope exits with an exception, run CLEANUP. */ @@ -1098,9 +1108,7 @@ finish_decl_cleanup (tree decl, tree cleanup) void finish_eh_cleanup (tree cleanup) { - tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup); - CLEANUP_EH_ONLY (r) = 1; - add_stmt (r); + push_cleanup (NULL, cleanup, true); } /* The MEM_INITS is a list of mem-initializers, in reverse of the @@ -1120,14 +1128,6 @@ finish_mem_initializers (tree mem_inits) emit_mem_initializers (mem_inits); } -/* Returns the stack of SCOPE_STMTs for the current function. */ - -tree * -current_scope_stmt_stack (void) -{ - return &cfun->language->base.x_scope_stmt_stack; -} - /* Finish a parenthesized expression EXPR. */ tree @@ -1348,17 +1348,7 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done, tree begin_stmt_expr (void) { - /* If we're outside a function, we won't have a statement-tree to - work with. But, if we see a statement-expression we need to - create one. */ - if (! cfun && !last_tree) - begin_stmt_tree (&scope_chain->x_saved_tree); - - last_expr_type = NULL_TREE; - - keep_next_level (true); - - return last_tree; + return push_stmt_list (); } /* Process the final expression of a statement expression. EXPR can be @@ -1367,7 +1357,7 @@ begin_stmt_expr (void) expression. */ tree -finish_stmt_expr_expr (tree expr) +finish_stmt_expr_expr (tree expr, tree stmt_expr) { tree result = NULL_TREE; tree type = void_type_node; @@ -1408,15 +1398,16 @@ finish_stmt_expr_expr (tree expr) if (expr != error_mark_node) { result = build_stmt (EXPR_STMT, expr); + EXPR_STMT_STMT_EXPR_RESULT (result) = 1; add_stmt (result); } } finish_stmt (); - /* Remember the last expression so that finish_stmt_expr can pull it - apart. */ - last_expr_type = result ? result : void_type_node; + /* Remember the last expression so that finish_stmt_expr + can pull it apart. */ + TREE_TYPE (stmt_expr) = result; return result; } @@ -1426,46 +1417,62 @@ finish_stmt_expr_expr (tree expr) representing the statement-expression. */ tree -finish_stmt_expr (tree rtl_expr, bool has_no_scope) +finish_stmt_expr (tree stmt_expr, bool has_no_scope) { - tree result; - tree result_stmt = last_expr_type; - tree type; - - if (!last_expr_type) + tree result, result_stmt, type; + tree *result_stmt_p = NULL; + + result_stmt = TREE_TYPE (stmt_expr); + TREE_TYPE (stmt_expr) = void_type_node; + result = pop_stmt_list (stmt_expr); + + if (!result_stmt || VOID_TYPE_P (result_stmt)) type = void_type_node; else { - if (result_stmt == void_type_node) + /* We need to search the statement expression for the result_stmt, + since we'll need to replace it entirely. */ + tree t; + result_stmt_p = &result; + while (1) { - type = void_type_node; - result_stmt = NULL_TREE; + t = *result_stmt_p; + if (t == result_stmt) + break; + + switch (TREE_CODE (t)) + { + case STATEMENT_LIST: + { + tree_stmt_iterator i = tsi_last (t); + result_stmt_p = tsi_stmt_ptr (i); + break; + } + case BIND_EXPR: + result_stmt_p = &BIND_EXPR_BODY (t); + break; + case COMPOUND_STMT: + result_stmt_p = &COMPOUND_BODY (t); + break; + case TRY_FINALLY_EXPR: + case TRY_CATCH_EXPR: + case CLEANUP_STMT: + result_stmt_p = &TREE_OPERAND (t, 0); + break; + default: + abort (); + } } - else - type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); + type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); } - - result = build_min (STMT_EXPR, type, last_tree); - TREE_SIDE_EFFECTS (result) = 1; - STMT_EXPR_NO_SCOPE (result) = has_no_scope; - - last_expr_type = NULL_TREE; - - /* Remove the compound statement from the tree structure; it is - now saved in the STMT_EXPR. */ - last_tree = rtl_expr; - TREE_CHAIN (last_tree) = NULL_TREE; - - /* If we created a statement-tree for this statement-expression, - remove it now. */ - if (! cfun - && TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE) - finish_stmt_tree (&scope_chain->x_saved_tree); if (processing_template_decl) - return result; - - if (!VOID_TYPE_P (type)) + { + result = build_min (STMT_EXPR, type, result); + TREE_SIDE_EFFECTS (result) = 1; + STMT_EXPR_NO_SCOPE (result) = has_no_scope; + } + else if (!VOID_TYPE_P (type)) { /* Pull out the TARGET_EXPR that is the final expression. Put the target's init_expr as the final expression and then put @@ -1474,10 +1481,24 @@ finish_stmt_expr (tree rtl_expr, bool has_no_scope) tree last_expr = EXPR_STMT_EXPR (result_stmt); my_friendly_assert (TREE_CODE (last_expr) == TARGET_EXPR, 20030729); - EXPR_STMT_EXPR (result_stmt) = TREE_OPERAND (last_expr, 1); + *result_stmt_p = TREE_OPERAND (last_expr, 1); + + if (TREE_CODE (result) == BIND_EXPR) + { + if (VOID_TYPE_P (TREE_TYPE (result))) + TREE_TYPE (result) = TREE_TYPE (last_expr); + else if (same_type_p (TREE_TYPE (result), TREE_TYPE (last_expr))) + ; + else + abort (); + } + else if (TREE_CODE (result) == STATEMENT_LIST) + result = build (BIND_EXPR, TREE_TYPE (last_expr), NULL, result, NULL); + TREE_OPERAND (last_expr, 1) = result; result = last_expr; } + return result; } @@ -2755,11 +2776,8 @@ simplify_aggr_init_expr (tree *tp) /* We want to use the value of the initialized location as the result. */ - call_expr = build (COMPOUND_EXPR, type, - call_expr, slot); + call_expr = build (COMPOUND_EXPR, type, call_expr, slot); - /* Replace the AGGR_INIT_EXPR with the CALL_EXPR. */ - TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr); *tp = call_expr; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 5bf6d144cf1..9b998ea47b0 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -293,13 +293,10 @@ cxx_incomplete_type_error (tree value, tree type) /* The recursive part of split_nonconstant_init. DEST is an lvalue - expression to which INIT should be assigned. INIT is a CONSTRUCTOR. - PCODE is a pointer to the tail of a chain of statements being emitted. - The return value is the new tail of that chain after new statements - are generated. */ + expression to which INIT should be assigned. INIT is a CONSTRUCTOR. */ -static tree * -split_nonconstant_init_1 (tree dest, tree init, tree *pcode) +static void +split_nonconstant_init_1 (tree dest, tree init) { tree *pelt, elt, type = TREE_TYPE (dest); tree sub, code, inner_type = NULL; @@ -331,7 +328,7 @@ split_nonconstant_init_1 (tree dest, tree init, tree *pcode) else sub = build (COMPONENT_REF, inner_type, dest, field_index); - pcode = split_nonconstant_init_1 (sub, value, pcode); + split_nonconstant_init_1 (sub, value); } else if (!initializer_constant_valid_p (value, inner_type)) { @@ -344,11 +341,10 @@ split_nonconstant_init_1 (tree dest, tree init, tree *pcode) code = build (MODIFY_EXPR, inner_type, sub, value); code = build_stmt (EXPR_STMT, code); - - *pcode = code; - pcode = &TREE_CHAIN (code); + add_stmt (code); continue; } + pelt = &TREE_CHAIN (elt); } break; @@ -359,15 +355,13 @@ split_nonconstant_init_1 (tree dest, tree init, tree *pcode) CONSTRUCTOR_ELTS (init) = NULL; code = build (MODIFY_EXPR, type, dest, init); code = build_stmt (EXPR_STMT, code); - pcode = &TREE_CHAIN (code); + add_stmt (code); } break; default: abort (); } - - return pcode; } /* A subroutine of store_init_value. Splits non-constant static @@ -382,10 +376,9 @@ split_nonconstant_init (tree dest, tree init) if (TREE_CODE (init) == CONSTRUCTOR) { - code = build_stmt (COMPOUND_STMT, NULL_TREE); - split_nonconstant_init_1 (dest, init, &COMPOUND_BODY (code)); - code = build1 (STMT_EXPR, void_type_node, code); - TREE_SIDE_EFFECTS (code) = 1; + code = push_stmt_list (); + split_nonconstant_init_1 (dest, init); + code = pop_stmt_list (code); DECL_INITIAL (dest) = init; TREE_READONLY (dest) = 0; } |