From: Nikita Popov Date: Thu, 14 Jul 2016 13:44:04 +0000 (+0200) Subject: Fix return from by-ref generators X-Git-Tag: php-7.1.0beta1~64 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e3e400c983d91af84e57c5c8402260ac84ec5459;p=php Fix return from by-ref generators --- diff --git a/Zend/tests/generators/return_from_by_ref_generator.phpt b/Zend/tests/generators/return_from_by_ref_generator.phpt new file mode 100644 index 0000000000..32bebfbbde --- /dev/null +++ b/Zend/tests/generators/return_from_by_ref_generator.phpt @@ -0,0 +1,20 @@ +--TEST-- +Return from by-ref generator +--FILE-- +next(); + +?> +--EXPECT-- +int(42) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9a4ff33950..ec95fd0d9c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4120,11 +4120,17 @@ static int zend_has_finally(void) /* {{{ */ void zend_compile_return(zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; + zend_bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0; zend_bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; znode expr_node; zend_op *opline; + if (is_generator) { + /* For generators the by-ref flag refers to yields, not returns */ + by_ref = 0; + } + if (!expr_ast) { expr_node.op_type = IS_CONST; ZVAL_NULL(&expr_node.u.constant); @@ -4146,7 +4152,7 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ } /* Generator return types are handled separately */ - if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + 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); } @@ -4156,10 +4162,10 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, &expr_node, NULL); - if (expr_ast) { + if (by_ref && expr_ast) { if (zend_is_call(expr_ast)) { opline->extended_value = ZEND_RETURNS_FUNCTION; - } else if (by_ref && !zend_is_variable(expr_ast)) { + } else if (!zend_is_variable(expr_ast)) { opline->extended_value = ZEND_RETURNS_VALUE; } }