From a12f43ee2c3d27a7eb9a3c873901643df5f7197e Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 17 Dec 2016 20:06:18 +0800 Subject: [PATCH] Reorder the oplines 1. we should only do the return type checking when it is really about to return 2. for 029.php, actually, the exception threw should be discard while it jmp into finally(it could be observed by change the return to return an array) 3. after this fix, the test 029.phpt behavior consistently with 7.0 4. good for optimizer too --- Zend/tests/return_types/029.phpt | 11 +++-------- Zend/zend_compile.c | 4 ++-- ext/opcache/Optimizer/zend_optimizer.c | 9 ++------- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/Zend/tests/return_types/029.phpt b/Zend/tests/return_types/029.phpt index adc07cde7f4dd..af13e6a69918c 100644 --- a/Zend/tests/return_types/029.phpt +++ b/Zend/tests/return_types/029.phpt @@ -16,13 +16,8 @@ function foo() : array { foo(); ?> --EXPECTF-- -Fatal error: Uncaught Exception: xxxx in %s:%d +Fatal error: Uncaught TypeError: Return value of foo() must be of the type array, null returned in %s029.php:%d Stack trace: -#0 %s(%d): foo() +#0 %s: foo() #1 {main} - -Next TypeError: Return value of foo() must be of the type array, null returned in %s29.php:%d -Stack trace: -#0 %s(%d): foo() -#1 {main} - thrown in %s029.php on line %d + thrown in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c8f2eefa7d2ec..71599e0e089c5 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4209,14 +4209,14 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ } } + zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL); + /* Generator return types are handled separately */ if (!is_generator && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { zend_emit_return_type_check( expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); } - zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL); - opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, &expr_node, NULL); diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index fa86b99b690a7..5c6b690c0c2c0 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -506,6 +506,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, } case ZEND_VERIFY_RETURN_TYPE: { zend_arg_info *ret_info = op_array->arg_info - 1; + ZEND_ASSERT((opline + 1)->opcode == ZEND_RETURN || (opline + 1)->opcode == ZEND_RETURN_BY_REF); if (ret_info->class_name || ret_info->type_hint == IS_CALLABLE || !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(val)) @@ -514,13 +515,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, return 0; } MAKE_NOP(opline); - - /* zend_handle_loops_and_finally may inserts other oplines */ - do { - ++opline; - } while (opline->opcode != ZEND_RETURN && opline->opcode != ZEND_RETURN_BY_REF); - ZEND_ASSERT(ZEND_OP1(opline).var == var); - + ++opline; break; } default: