diff options
author | Nikita Popov <nikic@php.net> | 2012-07-21 21:05:46 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2012-07-22 01:22:22 +0200 |
commit | 80748631aa1c4193cbc68f8854d82e7a57817fe2 (patch) | |
tree | ee081901714fba5399cd0aab9ac7f7ab9c8e79af /Zend/zend_compile.c | |
parent | 1f70a4c5fea97aa577aa5d9ee5f33d91d70e690d (diff) | |
download | php-git-80748631aa1c4193cbc68f8854d82e7a57817fe2.tar.gz |
Require parenthesis around yield expressions
If yield is used in an expression context parenthesis are now required.
This ensures that the code is unambiguos.
Yield statements can still be used without parenthesis (which should be
the most common case).
Also yield expressions without value can be used without parenthesis,
too (this should be the most common case for coroutines).
If the yield expression is used in a context where parenthesis are required
anyway, no additional parenthesis have to be inserted.
Examples:
// Statements don't need parenthesis
yield $foo;
yield $foo => $bar;
// Yield without value doesn't need parenthesis either
$data = yield;
// Parentheses don't have to be duplicated
foo(yield $bar);
if (yield $bar) { ... }
// But we have to use parentheses here
$foo = (yield $bar);
This commit also fixes an issue with by-ref passing of $foo[0] like
variables. They previously weren't properly fetched for write.
Additionally this fixes valgrind warnings which were caused by access to
uninitialized memory in zend_is_function_or_method_call().
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e030f94c78..51fc8c3e5b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2663,7 +2663,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ } /* }}} */ -void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC) /* {{{ */ +void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC) /* {{{ */ { zend_op *opline; @@ -2673,6 +2673,14 @@ void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR; + if (is_variable) { + if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(value)) { + zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); + } else { + zend_do_end_variable_parse(value, BP_VAR_R, 0 TSRMLS_CC); + } + } + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_YIELD; @@ -2680,7 +2688,7 @@ void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC if (value) { SET_NODE(opline->op1, value); - if (zend_is_function_or_method_call(value)) { + if (is_variable && zend_is_function_or_method_call(value)) { opline->extended_value = ZEND_RETURNS_FUNCTION; } } else { |