Skip to content

Commit 35951d4

Browse files
committed
1 parent e888d48 commit 35951d4

File tree

7 files changed

+61
-9
lines changed

7 files changed

+61
-9
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ PHP NEWS
33
?? ??? 201?, PHP 5.5.0
44

55
- General improvements:
6+
. Support list in foreach (https://wiki.php.net/rfc/foreachlist). (Laruence)
67
. Implemented 'finally' keyword (https://wiki.php.net/rfc/finally). (Laruence)
78
. Drop Windows XP and 2003 support. (Pierre)
89
. Improve set_exception_handler while doing reset.(Laruence)

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ PHP X.Y UPGRADE NOTES
3131
2. New Features
3232
========================================
3333

34+
- Support list in foreach. (Laruence)
35+
(wiki.php.net/rfc/foreachlist)
3436
- Support finally keyword. (Laruence)
3537
(wiki.php.net/rfc/finally)
3638
- Support constant array/string dereferencing. (Laruence)

Zend/tests/foreach_list.phpt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
foreach with list syntax
3+
--FILE--
4+
<?php
5+
6+
foreach(array(array(1,2), array(3,4)) as list($a, $b)) {
7+
var_dump($a . $b);
8+
}
9+
10+
$array = array(
11+
array('a', 'b'),
12+
array('c', 'd'),
13+
);
14+
15+
foreach ($array as list($a, $b)) {
16+
var_dump($a . $b);
17+
}
18+
19+
20+
$multi = array(
21+
array(array(1,2), array(3,4)),
22+
array(array(5,6), array(7,8)),
23+
);
24+
25+
foreach ($multi as list(list($a, $b), list($c, $d))) {
26+
var_dump($a . $b . $c . $d);
27+
}
28+
29+
foreach ($multi as $key => list(list($a, $b), list($c, $d))) {
30+
var_dump($key . $a . $b . $c . $d);
31+
}
32+
33+
34+
?>
35+
--EXPECT--
36+
string(2) "12"
37+
string(2) "34"
38+
string(2) "ab"
39+
string(2) "cd"
40+
string(4) "1234"
41+
string(4) "5678"
42+
string(5) "01234"
43+
string(5) "15678"

Zend/zend_compile.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6320,13 +6320,18 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token
63206320

63216321
GET_NODE(&value_node, opline->result);
63226322

6323-
if (assign_by_ref) {
6324-
zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
6325-
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
6326-
zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
6327-
} else {
6328-
zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
6323+
if (value->EA & ZEND_PARSED_LIST_EXPR) {
6324+
zend_do_list_end(&dummy, &value_node TSRMLS_CC);
63296325
zend_do_free(&dummy TSRMLS_CC);
6326+
} else {
6327+
if (assign_by_ref) {
6328+
zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
6329+
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
6330+
zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
6331+
} else {
6332+
zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
6333+
zend_do_free(&dummy TSRMLS_CC);
6334+
}
63306335
}
63316336

63326337
if (key->op_type != IS_UNUSED) {

Zend/zend_compile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
725725
#define ZEND_PARSED_VARIABLE (1<<4)
726726
#define ZEND_PARSED_REFERENCE_VARIABLE (1<<5)
727727
#define ZEND_PARSED_NEW (1<<6)
728+
#define ZEND_PARSED_LIST_EXPR (1<<7)
728729

729730

730731
/* unset types */

Zend/zend_language_parser.y

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ unticked_statement:
310310
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
311311
| T_FOREACH '(' expr_without_variable T_AS
312312
{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
313-
variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
313+
foreach_variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
314314
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
315315
| T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); }
316316
| ';' /* empty statement */
@@ -429,10 +429,10 @@ foreach_optional_arg:
429429
| T_DOUBLE_ARROW foreach_variable { $$ = $2; }
430430
;
431431

432-
433432
foreach_variable:
434433
variable { zend_check_writable_variable(&$1); $$ = $1; }
435434
| '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; }
435+
| T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; }
436436
;
437437

438438
for_statement:

tests/lang/foreachLoop.007.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ foreach (array(1,2) as &$v) {
88
}
99
?>
1010
--EXPECTF--
11-
Parse error: %s on line 3
11+
Fatal error: Cannot create references to elements of a temporary array expression in %sforeachLoop.007.php on line %d

0 commit comments

Comments
 (0)