extern void finish_eh_spec_block (tree, tree);
extern tree build_eh_type_type (tree);
extern tree cp_protect_cleanup_actions (void);
-extern void maybe_splice_retval_cleanup (tree);
+extern void maybe_splice_retval_cleanup (tree, bool);
extern tree maybe_set_retval_sentinel (void);
extern tree template_parms_to_args (tree);
on throw. */
void
-maybe_splice_retval_cleanup (tree compound_stmt)
+maybe_splice_retval_cleanup (tree compound_stmt, bool is_try)
{
- /* If we need a cleanup for the return value, add it in at the same level as
+ if (!current_function_decl || !cfun
+ || DECL_CONSTRUCTOR_P (current_function_decl)
+ || DECL_DESTRUCTOR_P (current_function_decl)
+ || !current_retval_sentinel)
+ return;
+
+ /* if we need a cleanup for the return value, add it in at the same level as
pushdecl_outermost_localscope. And also in try blocks. */
- const bool function_body
- = (current_binding_level->level_chain
- && current_binding_level->level_chain->kind == sk_function_parms
- /* When we're processing a default argument, c_f_d may not have been
- set. */
- && current_function_decl);
-
- if ((function_body || current_binding_level->kind == sk_try)
- && !DECL_CONSTRUCTOR_P (current_function_decl)
- && !DECL_DESTRUCTOR_P (current_function_decl)
- && current_retval_sentinel)
+ cp_binding_level *b = current_binding_level;
+ const bool function_body = b->kind == sk_function_parms;
+
+ if (function_body || is_try)
{
location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
tree_stmt_iterator iter = tsi_start (compound_stmt);
set_cleanup_locs (stmt, loc);
}
+/* True iff the innermost block scope is a try block. */
+
+static bool
+at_try_scope ()
+{
+ cp_binding_level *b = current_binding_level;
+ while (b && b->kind == sk_cleanup)
+ b = b->level_chain;
+ return b && b->kind == sk_try;
+}
+
/* Finish a scope. */
tree
{
tree block = NULL;
- maybe_splice_retval_cleanup (stmt_list);
+ bool was_try = at_try_scope ();
if (stmts_are_full_exprs_p ())
block = poplevel (kept_level_p (), 1, 0);
+ /* This needs to come after poplevel merges sk_cleanup statement_lists. */
+ maybe_splice_retval_cleanup (stmt_list, was_try);
+
stmt_list = pop_stmt_list (stmt_list);
/* input_location is the last token of the scope, usually a }. */