Commit: 134089372b94de2e3e8c2a1aba4cbc415c803d67 Author: Nikita Popov <ni...@php.net> Sun, 22 Jul 2012 20:11:09 +0200 Parents: 94b2ccae9ce95c4c71bb8db8ce75dcdf26df7d7a Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=134089372b94de2e3e8c2a1aba4cbc415c803d67 Log: 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. Changed paths: A Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt M Zend/tests/generators/errors/generator_cannot_return_error.phpt M Zend/zend_compile.c M Zend/zend_opcode.c Diff: diff --git a/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt new file mode 100644 index 0000000..ad618d2 --- /dev/null +++ b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt @@ -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 diff --git a/Zend/tests/generators/errors/generator_cannot_return_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_error.phpt index 9a46bff..5114906 100644 --- a/Zend/tests/generators/errors/generator_cannot_return_error.phpt +++ b/Zend/tests/generators/errors/generator_cannot_return_error.phpt @@ -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 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f0648a2..483ff30 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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)) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 65fa851..0042c37 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -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++; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php