}
for (i = block->start; i < block->start + block->len; i++) {
zend_op *opline = &op_array->opcodes[i];
- if (opline->opcode == ZEND_FE_FREE ||
- (opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH)) {
+ if (zend_optimizer_is_loop_var_free(opline)) {
int ssa_var = scdf->ssa->ops[i].op1_use;
if (ssa_var >= 0) {
int op_num = scdf->ssa->vars[ssa_var].definition;
for (j = b->start; j < b->start + b->len; j++) {
zend_op *opline = &op_array->opcodes[j];
- if (opline->opcode == ZEND_FE_FREE ||
- (opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH)
- ) {
+ if (zend_optimizer_is_loop_var_free(opline)) {
zend_op *def_opline = zend_optimizer_get_loop_var_def(op_array, opline);
if (def_opline) {
uint32_t def_block = block_map[def_opline - op_array->opcodes];
zend_op *zend_optimizer_get_loop_var_def(const zend_op_array *op_array, zend_op *free_opline) {
uint32_t var = free_opline->op1.var;
- ZEND_ASSERT(free_opline->opcode == ZEND_FE_FREE ||
- (free_opline->opcode == ZEND_FREE && free_opline->extended_value == ZEND_FREE_SWITCH));
+ ZEND_ASSERT(zend_optimizer_is_loop_var_free(free_opline));
while (--free_opline >= op_array->opcodes) {
if ((free_opline->result_type & (IS_TMP_VAR|IS_VAR)) && free_opline->result.var == var) {
target = src; \
} while (0)
+static inline zend_bool zend_optimizer_is_loop_var_free(const zend_op *opline) {
+ return (opline->opcode == ZEND_FE_FREE && opline->extended_value != ZEND_FREE_ON_RETURN)
+ || (opline->opcode == ZEND_FREE && opline->extended_value == ZEND_FREE_SWITCH);
+}
+
int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv);
int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy);
void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value);
--- /dev/null
+--TEST--
+Check that SCCP correctly handles non-terminating frees of loop variables
+--FILE--
+<?php
+function test() {
+ $arr = [];
+ foreach ($arr as $item) {
+ if (!empty($result)) {
+ return $result;
+ }
+ }
+ return 2;
+}
+
+var_dump(test());
+?>
+--EXPECT--
+int(2)