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

Reply via email to