summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2012-07-22 20:11:09 +0200
committerNikita Popov <nikic@php.net>2012-07-22 20:11:09 +0200
commit134089372b94de2e3e8c2a1aba4cbc415c803d67 (patch)
tree90fca0bc751801e6a63ab571e85097890882f137
parent94b2ccae9ce95c4c71bb8db8ce75dcdf26df7d7a (diff)
downloadphp-git-134089372b94de2e3e8c2a1aba4cbc415c803d67.tar.gz
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.
-rw-r--r--Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt13
-rw-r--r--Zend/tests/generators/errors/generator_cannot_return_error.phpt2
-rw-r--r--Zend/zend_compile.c9
-rw-r--r--Zend/zend_opcode.c12
4 files changed, 28 insertions, 8 deletions
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 0000000000..ad618d20ba
--- /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 9a46bff5e6..51149062a7 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 f0648a2d97..483ff30ddc 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 65fa85185e..0042c37299 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++;