Commit: 6b0b4bf8ebec7fa7172d2d2617fa7c80ecf4b528
Author: Dmitry Stogov <dmi...@zend.com> Thu, 13 Dec 2012 02:48:51
+0400
Parents: 9c96fe52d95a6674f90dc8efd4e2c054818c96ad
Branches: PHP-5.5 master
Link:
http://git.php.net/?p=php-src.git;a=commitdiff;h=6b0b4bf8ebec7fa7172d2d2617fa7c80ecf4b528
Log:
An exception thrown in try or catch block is disacarded by return statement in
finally block.
Changed paths:
M Zend/tests/catch_finally_006.phpt
M Zend/tests/try_catch_finally_003.phpt
A Zend/tests/try_finally_010.phpt
M Zend/zend_compile.c
M Zend/zend_compile.h
M Zend/zend_extensions.h
M Zend/zend_modules.h
M Zend/zend_vm_def.h
M Zend/zend_vm_execute.h
M Zend/zend_vm_opcodes.h
diff --git a/Zend/tests/catch_finally_006.phpt
b/Zend/tests/catch_finally_006.phpt
index 9759eab..216219b 100644
--- a/Zend/tests/catch_finally_006.phpt
+++ b/Zend/tests/catch_finally_006.phpt
@@ -25,4 +25,4 @@ try {
--EXPECT--
string(4) "para"
string(7) "finally"
-string(2) "ex"
+string(6) "return"
diff --git a/Zend/tests/try_catch_finally_003.phpt
b/Zend/tests/try_catch_finally_003.phpt
index 784063b..7ec8ec8 100644
--- a/Zend/tests/try_catch_finally_003.phpt
+++ b/Zend/tests/try_catch_finally_003.phpt
@@ -15,11 +15,9 @@ function foo () {
die("error");
} finally {
echo "1";
- return 1;
}
} finally {
echo "2";
- return 2;
}
} catch (BE $e) {
die("error");
diff --git a/Zend/tests/try_finally_010.phpt b/Zend/tests/try_finally_010.phpt
new file mode 100644
index 0000000..bbac8dd
--- /dev/null
+++ b/Zend/tests/try_finally_010.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Try finally (function call in the finaly block after exception)
+--FILE--
+<?php
+function foo() {
+ echo "4";
+}
+function bar() {
+ try {
+ echo "2";
+ throw new Exception();
+ echo "x";
+ } catch (MyEx $ex) {
+ echo "x";
+ } finally {
+ echo "3";
+ foo();
+ echo "5";
+ }
+}
+try {
+ echo "1";
+ bar();
+ echo "x";
+} catch (Exception $ex) {
+ echo "6";
+}
+echo "\n";
+--EXPECT--
+123456
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 3c7db27..ac3e633 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -181,6 +181,7 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
CG(context).backpatch_count = 0;
CG(context).nested_calls = 0;
CG(context).used_stack = 0;
+ CG(context).in_finally = 0;
CG(context).labels = NULL;
}
/* }}} */
@@ -287,7 +288,7 @@ ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
{
- return EX_TMP_VAR_NUM(0, (op_array->T)++);
+ return (zend_uint)EX_TMP_VAR_NUM(0, (op_array->T)++);
}
/* }}} */
@@ -2671,6 +2672,13 @@ void zend_do_return(znode *expr, int do_end_vparse
TSRMLS_DC) /* {{{ */
start_op_number++;
}
+ if (CG(context).in_finally) {
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_DISCARD_EXCEPTION;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);
+ }
+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN;
@@ -2819,6 +2827,8 @@ void zend_do_finally(znode *finally_token TSRMLS_DC) /*
{{{ */
opline->opcode = ZEND_JMP;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
+
+ CG(context).in_finally++;
}
/* }}} */
@@ -2897,6 +2907,8 @@ void zend_do_end_finally(znode *try_token, znode*
catch_token, znode *finally_to
SET_UNUSED(opline->op2);
CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num =
get_next_op_number(CG(active_op_array));
+
+ CG(context).in_finally--;
}
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index da0a49b..c921c2a 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -61,6 +61,7 @@ typedef struct _zend_compiler_context {
int backpatch_count;
int nested_calls;
int used_stack;
+ int in_finally;
HashTable *labels;
} zend_compiler_context;
diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h
index 5be6be6..3c60916 100644
--- a/Zend/zend_extensions.h
+++ b/Zend/zend_extensions.h
@@ -28,7 +28,7 @@
/* The first number is the engine version and the rest is the date.
* This way engine 2/3 API no. is always greater than engine 1 API no..
*/
-#define ZEND_EXTENSION_API_NO 220121204
+#define ZEND_EXTENSION_API_NO 220121212
typedef struct _zend_extension_version_info {
int zend_extension_api_no;
diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h
index b4ad648..a4ed106 100644
--- a/Zend/zend_modules.h
+++ b/Zend/zend_modules.h
@@ -33,7 +33,7 @@
#define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC
#define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC
-#define ZEND_MODULE_API_NO 20121204
+#define ZEND_MODULE_API_NO 20121212
#ifdef ZTS
#define USING_ZTS 1
#else
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 939dc1d..ef3f80e 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1845,12 +1845,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
zend_bool nested;
zend_op_array *op_array = EX(op_array);
- if (EXPECTED(EG(exception) == NULL) &&
- UNEXPECTED(EG(prev_exception) != NULL)) {
- /* return from finally block called because of unhandled
exception */
- zend_exception_restore(TSRMLS_C);
- }
-
EG(current_execute_data) = EX(prev_execute_data);
EG(opline_ptr) = NULL;
if (!EG(active_symbol_table)) {
@@ -2960,12 +2954,6 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY)
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
- if (EXPECTED(EG(exception) == NULL) &&
- UNEXPECTED(EG(prev_exception) != NULL)) {
- /* return from finally block called because of unhandled
exception */
- zend_exception_restore(TSRMLS_C);
- }
-
/* Close the generator to free up resources */
zend_generator_close(generator, 1 TSRMLS_CC);
@@ -5409,6 +5397,17 @@ ZEND_VM_HANDLER(160, ZEND_YIELD,
CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
ZEND_VM_RETURN();
}
+ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
+{
+ if (EG(prev_exception) != NULL) {
+ /* discard the previously thrown exception */
+ zval_ptr_dtor(&EG(prev_exception));
+ EG(prev_exception) = NULL;
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
{
USE_OPLINE
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index dd77aa5..4e4dedf 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -386,12 +386,6 @@ static int ZEND_FASTCALL
zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_bool nested;
zend_op_array *op_array = EX(op_array);
- if (EXPECTED(EG(exception) == NULL) &&
- UNEXPECTED(EG(prev_exception) != NULL)) {
- /* return from finally block called because of unhandled
exception */
- zend_exception_restore(TSRMLS_C);
- }
-
EG(current_execute_data) = EX(prev_execute_data);
EG(opline_ptr) = NULL;
if (!EG(active_symbol_table)) {
@@ -696,12 +690,6 @@ static int ZEND_FASTCALL
ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER
/* The generator object is stored in return_value_ptr_ptr */
zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
- if (EXPECTED(EG(exception) == NULL) &&
- UNEXPECTED(EG(prev_exception) != NULL)) {
- /* return from finally block called because of unhandled
exception */
- zend_exception_restore(TSRMLS_C);
- }
-
/* Close the generator to free up resources */
zend_generator_close(generator, 1 TSRMLS_CC);
@@ -1134,6 +1122,17 @@ static int ZEND_FASTCALL
ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
}
+static int ZEND_FASTCALL
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ if (EG(prev_exception) != NULL) {
+ /* discard the previously thrown exception */
+ zval_ptr_dtor(&EG(prev_exception));
+ EG(prev_exception) = NULL;
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -44827,31 +44826,31 @@ void zend_init_opcodes_handlers(void)
ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+ ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
ZEND_YIELD_SPEC_CONST_CONST_HANDLER,
ZEND_YIELD_SPEC_CONST_TMP_HANDLER,
ZEND_YIELD_SPEC_CONST_VAR_HANDLER,
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 52f6cde..061d7e4 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -159,6 +159,7 @@
#define ZEND_SEPARATE 156
#define ZEND_QM_ASSIGN_VAR 157
#define ZEND_JMP_SET_VAR 158
+#define ZEND_DISCARD_EXCEPTION 159
#define ZEND_YIELD 160
#define ZEND_GENERATOR_RETURN 161
#define ZEND_FAST_CALL 162
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php