Commit 0dde4175 by Jason Merrill Committed by Jason Merrill

semantics.c (begin_function_try_block, [...]): New fns.

	* semantics.c (begin_function_try_block, finish_function_try_block,
	finish_function_handler_sequence): New fns.
	* parse.y (function_try_block): Use them.
	* pt.c (instantiate_decl): Likewise.

	* cp-tree.h: Declare in_function_try_handler.
	* decl.c: Define it.
	(start_function): Clear it.
	(struct cp_function, push_cp_function_context): Save it.
	(pop_cp_function_context): Restore it.
	* parse.y (function_try_block): Set and clear it.
	* except.c (expand_end_catch_block): Rethrow if we reach the end
	of a function-try-block handler in a ctor or dtor.
	* typeck.c (c_expand_return): Complain about returning from a
	function-try-block handler of a ctor.

	* parse.y (function_try_block): Call end_protect_partials
	before expand_start_all_catch.

From-SVN: r28624
parent fb20fc45
1999-08-09 Jason Merrill <jason@yorick.cygnus.com>
* semantics.c (begin_function_try_block, finish_function_try_block,
finish_function_handler_sequence): New fns.
* parse.y (function_try_block): Use them.
* pt.c (instantiate_decl): Likewise.
* cp-tree.h: Declare in_function_try_handler.
* decl.c: Define it.
(start_function): Clear it.
(struct cp_function, push_cp_function_context): Save it.
(pop_cp_function_context): Restore it.
* parse.y (function_try_block): Set and clear it.
* except.c (expand_end_catch_block): Rethrow if we reach the end
of a function-try-block handler in a ctor or dtor.
* typeck.c (c_expand_return): Complain about returning from a
function-try-block handler of a ctor.
* parse.y (function_try_block): Call end_protect_partials
before expand_start_all_catch.
1999-08-08 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (struct binding_level): Add eh_region field.
......
......@@ -2290,6 +2290,8 @@ extern tree tag_identifier;
extern tree vt_off_identifier;
extern tree empty_except_spec;
extern int in_function_try_handler;
/* A node that is a list (length 1) of error_mark_nodes. */
extern tree error_mark_list;
......@@ -3381,6 +3383,9 @@ extern void finish_goto_stmt PROTO((tree));
extern tree begin_try_block PROTO((void));
extern void finish_try_block PROTO((tree));
extern void finish_handler_sequence PROTO((tree));
extern tree begin_function_try_block PROTO((void));
extern void finish_function_try_block PROTO((tree));
extern void finish_function_handler_sequence PROTO((tree));
extern tree begin_handler PROTO((void));
extern void finish_handler_parms PROTO((tree));
extern void finish_handler PROTO((tree));
......
......@@ -288,7 +288,7 @@ tree va_list_type_node;
static tree global_type_node;
/* Namespace std. */
int in_std = 0;
int in_std;
/* Expect only namespace names now. */
static int only_namespace_names;
......@@ -339,6 +339,9 @@ tree vt_off_identifier;
/* Exception specifier used for throw(). */
tree empty_except_spec;
/* Nonzero if we're in a handler for a function-try-block. */
int in_function_try_handler;
struct named_label_list
{
struct binding_level *binding_level;
......@@ -12982,6 +12985,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
current_member_init_list = NULL_TREE;
ctor_label = dtor_label = NULL_TREE;
static_labelno = 0;
in_function_try_handler = 0;
clear_temp_name ();
......@@ -14622,6 +14626,7 @@ struct cp_function
struct cp_function *next;
struct binding_level *binding_level;
int static_labelno;
int in_function_try_handler;
};
static struct cp_function *cp_function_chain;
......@@ -14664,6 +14669,7 @@ push_cp_function_context (context)
p->current_class_ptr = current_class_ptr;
p->current_class_ref = current_class_ref;
p->static_labelno = static_labelno;
p->in_function_try_handler = in_function_try_handler;
}
/* Restore the variables used during compilation of a C++ function. */
......@@ -14706,6 +14712,7 @@ pop_cp_function_context (context)
current_class_ptr = p->current_class_ptr;
current_class_ref = p->current_class_ref;
static_labelno = p->static_labelno;
in_function_try_handler = p->in_function_try_handler;
free (p);
}
......
......@@ -698,6 +698,13 @@ expand_end_catch_block ()
if (! doing_eh (1))
return;
/* The exception being handled is rethrown if control reaches the end of
a handler of the function-try-block of a constructor or destructor. */
if (in_function_try_handler
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl)))
expand_throw (NULL_TREE);
/* Cleanup the EH parameter. */
expand_end_bindings (getdecls (), kept_level_p (), 0);
poplevel (kept_level_p (), 1, 0);
......
......@@ -3384,18 +3384,12 @@ simple_stmt:
function_try_block:
TRY
{
if (! current_function_parms_stored)
store_parm_decls ();
expand_start_early_try_stmts ();
}
{ $<ttype>$ = begin_function_try_block (); }
ctor_initializer_opt compstmt
{
expand_start_all_catch ();
}
{ finish_function_try_block ($<ttype>2); }
handler_seq
{
expand_end_all_catch ();
finish_function_handler_sequence ($<ttype>2);
$$ = $3;
}
;
......
......@@ -9503,10 +9503,18 @@ instantiate_decl (d)
else if (TREE_CODE (d) == FUNCTION_DECL)
{
tree t = DECL_SAVED_TREE (code_pattern);
tree try_block = NULL_TREE;
start_function (NULL_TREE, d, NULL_TREE, 1);
store_parm_decls ();
if (t && TREE_CODE (t) == TRY_BLOCK)
{
try_block = t;
begin_function_try_block ();
t = TRY_STMTS (try_block);
}
if (t && TREE_CODE (t) == RETURN_INIT)
{
store_return_init
......@@ -9533,6 +9541,17 @@ instantiate_decl (d)
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
tsubst_expr (t, args, /*complain=*/1, tmpl);
if (try_block)
{
finish_function_try_block (NULL_TREE);
{
tree handler = TRY_HANDLERS (try_block);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, /*complain=*/1, tmpl);
}
finish_function_handler_sequence (NULL_TREE);
}
finish_function (lineno, 0, nested);
}
......
......@@ -586,6 +586,27 @@ begin_try_block ()
}
}
/* Likewise, for a function-try-block. */
tree
begin_function_try_block ()
{
if (processing_template_decl)
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
add_tree (r);
return r;
}
else
{
if (! current_function_parms_stored)
store_parm_decls ();
expand_start_early_try_stmts ();
return NULL_TREE;
}
}
/* Finish a try-block, which may be given by TRY_BLOCK. */
void
......@@ -600,6 +621,22 @@ finish_try_block (try_block)
}
}
/* Likewise, for a function-try-block. */
void
finish_function_try_block (try_block)
tree try_block;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
{
end_protect_partials ();
expand_start_all_catch ();
in_function_try_handler = 1;
}
}
/* Finish a handler-sequence for a try-block, which may be given by
TRY_BLOCK. */
......@@ -615,6 +652,21 @@ finish_handler_sequence (try_block)
}
}
/* Likewise, for a function-try-block. */
void
finish_function_handler_sequence (try_block)
tree try_block;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
in_function_try_handler = 0;
expand_end_all_catch ();
}
}
/* Begin a handler. Returns a HANDLER if appropriate. */
tree
......
......@@ -6858,6 +6858,14 @@ c_expand_return (retval)
expand_goto (dtor_label);
return;
}
else if (in_function_try_handler
&& DECL_CONSTRUCTOR_P (current_function_decl))
{
/* If a return statement appears in a handler of the
function-try-block of a constructor, the program is ill-formed. */
error ("cannot return from a handler of a function-try-block of a constructor");
return;
}
/* Only operator new(...) throw(), can return NULL [expr.new/13]. */
if ((DECL_NAME (current_function_decl) == ansi_opname[(int) NEW_EXPR]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment