if (first) first = 0; else fprintf(stderr, ", ");
fprintf(stderr, "null");
}
- if (info & MAY_BE_FALSE) {
+ if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) {
+ if (first) first = 0; else fprintf(stderr, ", ");
+ fprintf(stderr, "bool");
+ } else if (info & MAY_BE_FALSE) {
if (first) first = 0; else fprintf(stderr, ", ");
fprintf(stderr, "false");
- }
- if (info & MAY_BE_TRUE) {
+ } else if (info & MAY_BE_TRUE) {
if (first) first = 0; else fprintf(stderr, ", ");
fprintf(stderr, "true");
}
}
fprintf(stderr, ")\n");
} else {
- fprintf(stderr, " = Pi(");
+ fprintf(stderr, " = Pi<BB%d>(", p->pi);
zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var, dump_flags);
fprintf(stderr, " &");
zend_dump_pi_constraint(op_array, ssa, &p->constraint, dump_flags);
op2_max = OP2_MAX_RANGE();
tmp->min = (op1_min == op1_max &&
- op2_min == op2_min &&
+ op2_min == op2_max &&
op1_min == op2_max);
tmp->max = (op1_min <= op2_max && op1_max >= op2_min);
return 1;
tmp->min = (op1_min > op2_max || op1_max < op2_min);
tmp->max = (op1_min != op1_max ||
- op2_min != op2_min ||
+ op2_min != op2_max ||
op1_min != op2_max);
return 1;
} else {
if (opline->op1_type & (IS_CV|IS_VAR)) {
tmp |= MAY_BE_RCN;
}
+ if (opline->opcode != ZEND_QM_ASSIGN) {
+ /* COALESCE and JMP_SET result can't be null */
+ tmp &= ~MAY_BE_NULL;
+ if (opline->opcode == ZEND_JMP_SET) {
+ /* JMP_SET result can't be false either */
+ tmp &= ~MAY_BE_FALSE;
+ }
+ }
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
if ((t1 & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) {
UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def);
case ZEND_FETCH_DIM_W:
case ZEND_FETCH_DIM_UNSET:
case ZEND_FETCH_DIM_FUNC_ARG:
+ case ZEND_FETCH_LIST:
if (ssa_ops[i].op1_def >= 0) {
tmp = t1;
if (opline->opcode == ZEND_FETCH_DIM_W ||
UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def);
}
}
+ /* FETCH_LIST on a string behaves like FETCH_R on null */
tmp = zend_array_element_type(
- t1,
- (opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS),
+ opline->opcode != ZEND_FETCH_LIST ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
+ opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS
+ && opline->opcode != ZEND_FETCH_LIST,
opline->op2_type == IS_UNUSED);
if (opline->opcode == ZEND_FETCH_DIM_W ||
opline->opcode == ZEND_FETCH_DIM_RW ||
END_EXTERN_C()
-static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, int use)
+static zend_always_inline int zend_ssa_next_use(const zend_ssa_op *ssa_op, int var, int use)
{
ssa_op += use;
if (ssa_op->result_use == var) {
return (ssa_op->op1_use == var) ? ssa_op->op1_use_chain : ssa_op->op2_use_chain;
}
-static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(zend_ssa *ssa, int var, zend_ssa_phi *p)
+static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(const zend_ssa *ssa, int var, const zend_ssa_phi *p)
{
if (p->pi >= 0) {
return p->use_chains[0];