mirror of
https://github.com/php/php-src.git
synced 2026-03-24 08:12:21 +01:00
Throw error also for return occuring before yield
Previously only an error was thrown when return occured after yield. Also returns before the first yield would fail for by-ref generators. Now the error message is handled in pass_two, so all returns are checked.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Generators cannot return values (even before yield)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function gen() {
|
||||
return $foo;
|
||||
yield;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Generators cannot return values using "return" in %s on line 4
|
||||
@@ -10,4 +10,4 @@ function gen() {
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Generators cannot return values using "return" in %s on line %d
|
||||
Fatal error: Generators cannot return values using "return" in %s on line 5
|
||||
|
||||
@@ -2611,14 +2611,9 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_op *opline;
|
||||
int start_op_number, end_op_number;
|
||||
zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
|
||||
|
||||
/* For generators the & modifier applies to the yielded values, not the
|
||||
* return value. */
|
||||
zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR);
|
||||
|
||||
if ((CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && expr != NULL) {
|
||||
zend_error(E_COMPILE_ERROR, "Generators cannot return values using \"return\"");
|
||||
}
|
||||
/* The error for use of return inside a generator is thrown in pass_two. */
|
||||
|
||||
if (do_end_vparse) {
|
||||
if (returns_reference && !zend_is_function_or_method_call(expr)) {
|
||||
|
||||
@@ -532,6 +532,18 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
|
||||
case ZEND_JMP_SET_VAR:
|
||||
opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
|
||||
break;
|
||||
case ZEND_RETURN:
|
||||
case ZEND_RETURN_BY_REF:
|
||||
if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
|
||||
if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) {
|
||||
CG(zend_lineno) = opline->lineno;
|
||||
zend_error(E_COMPILE_ERROR, "Generators cannot return values using \"return\"");
|
||||
}
|
||||
if (opline->opcode == ZEND_RETURN_BY_REF) {
|
||||
opline->opcode = ZEND_RETURN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
ZEND_VM_SET_OPCODE_HANDLER(opline);
|
||||
opline++;
|
||||
|
||||
Reference in New Issue
Block a user