This commit is contained in:
Xinchen Hui 2015-01-19 09:12:44 -05:00
commit 137a251a52
5 changed files with 193 additions and 158 deletions

View File

@ -16,4 +16,5 @@ $b->bar();
?>
--EXPECTF--
Fatal error: Non-static method A::foo() cannot be called statically, assuming $this from incompatible context in %s on line %d
Deprecated: Non-static method A::foo() should not be called statically, assuming $this from incompatible context in %s on line %d
string(1) "B"

View File

@ -3527,13 +3527,21 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
zend_compile_expr(&cond_node, cond_ast);
opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node);
SET_NODE(opline->result, &case_node);
if (opline->op1_type == IS_CONST) {
zval_copy_ctor(CT_CONSTANT(opline->op1));
}
if (expr_node.op_type == IS_CONST
&& Z_TYPE(expr_node.u.constant) == IS_FALSE) {
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
} else if (expr_node.op_type == IS_CONST
&& Z_TYPE(expr_node.u.constant) == IS_TRUE) {
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
} else {
opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node);
SET_NODE(opline->result, &case_node);
if (opline->op1_type == IS_CONST) {
zval_copy_ctor(CT_CONSTANT(opline->op1));
}
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
}
}
opnum_default_jmp = zend_emit_jump(0);
@ -5124,7 +5132,32 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
return;
}
zend_emit_op_tmp(result, opcode, &left_node, &right_node);
do {
if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
if (left_node.op_type == IS_CONST) {
if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
zend_emit_op_tmp(result, opcode, &right_node, NULL);
break;
} else if (Z_TYPE(left_node.u.constant) == IS_TRUE) {
opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
zend_emit_op_tmp(result, opcode, &right_node, NULL);
break;
}
} else if (right_node.op_type == IS_CONST) {
if (Z_TYPE(right_node.u.constant) == IS_FALSE) {
opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
zend_emit_op_tmp(result, opcode, &left_node, NULL);
break;
} else if (Z_TYPE(right_node.u.constant) == IS_TRUE) {
opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
zend_emit_op_tmp(result, opcode, &left_node, NULL);
break;
}
}
}
zend_emit_op_tmp(result, opcode, &left_node, &right_node);
} while (0);
}
/* }}} */

View File

@ -2471,24 +2471,24 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}

View File

@ -4257,24 +4257,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -6052,24 +6052,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -7127,24 +7127,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -8265,24 +8265,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -13393,24 +13393,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -14882,24 +14882,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -16329,24 +16329,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}
@ -17766,24 +17766,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z
object = Z_OBJ(EX(This));
GC_REFCOUNT(object)++;
}
if (!object) {
if (!object ||
!instanceof_function(object->ce, ce)) {
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* We allow calling userland non-static methods without $this */
zend_error(E_STRICT,
"Non-static method %s::%s() should not be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
zend_error(
object ? E_DEPRECATED : E_STRICT,
"Non-static method %s::%s() should not be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
} else {
/* An internal function assumes $this is present and won't check that.
* So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically",
fbc->common.scope->name->val, fbc->common.function_name->val);
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(
E_ERROR,
"Non-static method %s::%s() cannot be called statically%s",
fbc->common.scope->name->val, fbc->common.function_name->val,
object ? ", assuming $this from incompatible context" : "");
}
} else if (!instanceof_function(object->ce, ce)) {
zend_error_noreturn(E_ERROR,
"Non-static method %s::%s() cannot be called statically, "
"assuming $this from incompatible context",
fbc->common.scope->name->val, fbc->common.function_name->val);
}
}

View File

@ -901,22 +901,31 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
ZVAL_NULL(&ZEND_OP1_LITERAL(last_op));
MAKE_NOP(last_op);
} else if (opline->opcode == ZEND_CONCAT &&
} else if ((opline->opcode == ZEND_CONCAT ||
opline->opcode == ZEND_ADD_STRING ||
opline->opcode == ZEND_ADD_CHAR) &&
ZEND_OP2_TYPE(opline) == IS_CONST &&
ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
VAR_SOURCE(opline->op1) &&
(VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT ||
VAR_SOURCE(opline->op1)->opcode == ZEND_ADD_STRING) &&
VAR_SOURCE(opline->op1)->opcode == ZEND_ADD_STRING ||
VAR_SOURCE(opline->op1)->opcode == ZEND_ADD_CHAR) &&
ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST &&
ZEND_RESULT(VAR_SOURCE(opline->op1)).var == ZEND_OP1(opline).var) {
/* compress consecutive CONCATs */
/* compress consecutive CONCAT/ADD_STRING/ADD_CHARs */
zend_op *src = VAR_SOURCE(opline->op1);
int l, old_len;
if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
if (opline->opcode == ZEND_ADD_CHAR) {
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
} else if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
convert_to_string_safe(&ZEND_OP2_LITERAL(opline));
}
if (Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) {
if (src->opcode == ZEND_ADD_CHAR) {
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(src));
ZVAL_STRINGL(&ZEND_OP2_LITERAL(src), &c, 1);
} else if (Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) {
convert_to_string_safe(&ZEND_OP2_LITERAL(src));
}
@ -924,6 +933,8 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
if (ZEND_OP1_TYPE(src) == IS_UNUSED) {
/* 5.3 may use IS_UNUSED as first argument to ZEND_ADD_... */
opline->opcode = ZEND_ADD_STRING;
} else {
opline->opcode = ZEND_CONCAT;
}
COPY_NODE(opline->op1, src->op1);
old_len = Z_STRLEN(ZEND_OP2_LITERAL(src));
@ -945,16 +956,6 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
ZVAL_NULL(&ZEND_OP2_LITERAL(src));
MAKE_NOP(src);
} else if ((opline->opcode == ZEND_ADD_STRING || opline->opcode == ZEND_ADD_VAR) && ZEND_OP1_TYPE(opline) == IS_CONST) {
/* convert ADD_STRING(C1, C2) to CONCAT(C1, C2) */
opline->opcode = ZEND_CONCAT;
continue;
} else if (opline->opcode == ZEND_ADD_CHAR && ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP2_TYPE(opline) == IS_CONST) {
/* convert ADD_CHAR(C1, C2) to CONCAT(C1, C2) */
char c = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
ZVAL_STRINGL(&ZEND_OP2_LITERAL(opline), &c, 1);
opline->opcode = ZEND_CONCAT;
continue;
} else if ((opline->opcode == ZEND_ADD ||
opline->opcode == ZEND_SUB ||
opline->opcode == ZEND_MUL ||