Index: src/ops/core.ops =================================================================== --- src/ops/core.ops (revision 10945) +++ src/ops/core.ops (working copy) @@ -645,12 +645,16 @@ =item B(labelconst INT) -Create an exception handler for the given catch label and push it onto -the control stack. +Create an exception handler that transfers control to the specified +catch label and push it onto the control stack. Such handlers remain +in effect in the current dynamic context, and are popped automatically +on exit. =item B() -Clear out the most recently placed exception. +Remove the exception on the top of the control stack. A "No exception +to pop" error is signalled if the top of the stack is not an +exception, or the exception does not belong to the current context. =item B(in PMC) Index: src/exceptions.c =================================================================== --- src/exceptions.c (revision 10945) +++ src/exceptions.c (working copy) @@ -327,12 +327,22 @@ { Stack_entry_type type; PMC *handler; + parrot_context_t *current_ctx = CONTEXT(interpreter->ctx); + parrot_context_t *prev_ctx = current_ctx->prev; + Stack_Chunk_t *prev_base = (prev_ctx ? prev_ctx->control_stack : NULL); - handler = stack_peek(interpreter, CONTEXT(interpreter->ctx)->control_stack, &type); + if (prev_base == current_ctx->control_stack) { + real_exception(interpreter, NULL, INVALID_OPERATION, + "No exception to pop."); + } + handler = stack_peek(interpreter, current_ctx->control_stack, &type); if (type != STACK_ENTRY_PMC || - handler->vtable->base_type != enum_class_Exception_Handler) - return; /* no exception on TOS */ - (void)stack_pop(interpreter, &CONTEXT(interpreter->ctx)->control_stack, NULL, + handler->vtable->base_type != enum_class_Exception_Handler) { + /* no exception on TOS */ + real_exception(interpreter, NULL, INVALID_OPERATION, + "No exception to pop."); + } + (void)stack_pop(interpreter, ¤t_ctx->control_stack, NULL, STACK_ENTRY_PMC); } Index: t/pmc/exception.t =================================================================== --- t/pmc/exception.t (revision 10945) +++ t/pmc/exception.t (working copy) @@ -6,7 +6,7 @@ use warnings; use lib qw( . lib ../lib ../../lib ); use Test::More; -use Parrot::Test tests => 26; +use Parrot::Test tests => 28; =head1 NAME @@ -591,3 +591,42 @@ Error: something happened Outer value OUTPUT + +pir_output_like(<<'CODE', <<'OUTPUT', 'clear_eh out of context (1)'); +.sub main :main + pushmark 1 + clear_eh + print "no exceptions.\n" +.end +CODE +/No exception to pop./ +OUTPUT + +pir_output_is(<<'CODE', <<'OUTPUT', 'clear_eh out of context (2)'); +.sub main :main + .local pmc outer, cont + push_eh handler + test1() + print "skipped.\n" + goto done +handler: + .local pmc exception + .get_results (exception) + print "Error: " + print exception + print "\n" +done: + print "done.\n" +.end +.sub test1 + .local pmc exit + print "[in test1]\n" + ## clear_eh is illegal here, and signals an exception. + clear_eh + print "[cleared]\n" +.end +CODE +[in test1] +Error: No exception to pop. +done. +OUTPUT