emit_op(NULL, ZEND_THROW, &expr_node, NULL TSRMLS_CC);
}
+void zend_compile_break_continue(zend_ast *ast TSRMLS_DC) {
+ zend_ast *depth_ast = ast->child[0];
+ zend_uint opcode = ast->kind;
+
+ znode depth_node;
+ zend_op *opline;
+
+ ZEND_ASSERT(opcode == ZEND_BRK || opcode == ZEND_CONT);
+
+ if (depth_ast) {
+ if (depth_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
+ "is no longer supported", opcode == ZEND_BRK ? "break" : "continue");
+ }
+
+ zend_compile_expr(&depth_node, depth_ast TSRMLS_CC);
+
+ if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
+ zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
+ opcode == ZEND_BRK ? "break" : "continue");
+ }
+ } else {
+ depth_node.op_type = IS_CONST;
+ ZVAL_LONG(&depth_node.u.constant, 1);
+ }
+
+ opline = emit_op(NULL, opcode, NULL, &depth_node TSRMLS_CC);
+ opline->op1.opline_num = CG(context).current_brk_cont;
+}
+
void zend_compile_binary_op(znode *result, zend_ast *ast TSRMLS_DC) {
zend_ast *left_ast = ast->child[0];
zend_ast *right_ast = ast->child[1];
case ZEND_THROW:
zend_compile_throw(ast TSRMLS_CC);
return;
+ case ZEND_BRK:
+ case ZEND_CONT:
+ zend_compile_break_continue(ast TSRMLS_CC);
+ return;
EMPTY_SWITCH_DEFAULT_CASE()
}
}
')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); }
for_statement { zend_do_for_end(&$7 TSRMLS_CC); }
| T_SWITCH parenthesis_expr { AC($2); zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); }
- | T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); }
- | T_BREAK expr ';' { AC($2); zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); }
- | T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
- | T_CONTINUE expr ';' { AC($2); zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
+ | T_BREAK ';' { $$.u.ast = zend_ast_create_unary(ZEND_BRK, NULL); AS($$); }
+ | T_BREAK expr ';' { $$.u.ast = zend_ast_create_unary(ZEND_BRK, $2.u.ast); AS($$); }
+ | T_CONTINUE ';' { $$.u.ast = zend_ast_create_unary(ZEND_CONT, NULL); AS($$); }
+ | T_CONTINUE expr ';' { $$.u.ast = zend_ast_create_unary(ZEND_CONT, $2.u.ast); AS($$); }
| T_RETURN ';'
{ $$.u.ast = zend_ast_create_unary(ZEND_AST_RETURN, NULL); AS($$); }
| T_RETURN expr ';'