Index: Zend/zend_compile.c =================================================================== --- Zend/zend_compile.c (revision 313636) +++ Zend/zend_compile.c (working copy) @@ -5824,7 +5824,7 @@ znode dummy, value_node; zend_bool assign_by_ref=0; - opline = &CG(active_op_array)->opcodes[as_token->u.op. opline_num]; + opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num]; if (key->op_type != IS_UNUSED) { znode *tmp; @@ -5837,8 +5837,13 @@ opline->extended_value |= ZEND_FE_FETCH_WITH_KEY; } - if ((key->op_type != IS_UNUSED) && (key->EA & ZEND_PARSED_REFERENCE_VARIABLE)) { - zend_error(E_COMPILE_ERROR, "Key element cannot be a reference"); + if ((key->op_type != IS_UNUSED)) { + if (key->EA & ZEND_PARSED_REFERENCE_VARIABLE) { + zend_error(E_COMPILE_ERROR, "Key element cannot be a reference"); + } + if (key->EA & ZEND_PARSED_LIST_EXPR) { + zend_error(E_COMPILE_ERROR, "Key element cannot be a list expression"); + } } if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) { @@ -5873,14 +5878,21 @@ } GET_NODE(&value_node, opline->result); - - if (assign_by_ref) { - zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); - /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ - zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); + if (value->EA & ZEND_PARSED_LIST_EXPR) { + zend_do_list_end(&dummy, &value_node TSRMLS_CC); + zend_do_free(&dummy TSRMLS_CC); + if (value->op_type == IS_TMP_VAR) { + zend_do_end_silence(value TSRMLS_CC); + } } else { - zend_do_assign(&dummy, value, &value_node TSRMLS_CC); - zend_do_free(&dummy TSRMLS_CC); + if (assign_by_ref) { + zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); + /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ + zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); + } else { + zend_do_assign(&dummy, value, &value_node TSRMLS_CC); + zend_do_free(&dummy TSRMLS_CC); + } } if (key->op_type != IS_UNUSED) { Index: Zend/zend_compile.h =================================================================== --- Zend/zend_compile.h (revision 313636) +++ Zend/zend_compile.h (working copy) @@ -719,6 +719,7 @@ #define ZEND_PARSED_VARIABLE (1<<4) #define ZEND_PARSED_REFERENCE_VARIABLE (1<<5) #define ZEND_PARSED_NEW (1<<6) +#define ZEND_PARSED_LIST_EXPR (1<<7) /* unset types */ Index: Zend/zend_language_parser.y =================================================================== --- Zend/zend_language_parser.y (revision 313636) +++ Zend/zend_language_parser.y (working copy) @@ -308,7 +308,7 @@ foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); } - variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } + foreach_variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } | 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); } | ';' /* empty statement */ @@ -420,10 +420,15 @@ | T_DOUBLE_ARROW foreach_variable { $$ = $2; } ; +foreach_list_expr: + | T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; } + | '@' foreach_list_expr { zend_do_begin_silence(&$1 TSRMLS_CC); $$ = $1; } + foreach_variable: variable { zend_check_writable_variable(&$1); $$ = $1; } | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; } + | foreach_list_expr { $$ = $1; } ; for_statement: