diff options
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r-- | Zend/zend_inheritance.c | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 9eb7a0b9c9..845500c041 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -319,6 +319,14 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c return 0; } +#if 0 + // This introduces BC break described at https://bugs.php.net/bug.php?id=72119 + if (proto_arg_info->type_hint && proto_arg_info->allow_null && !fe_arg_info->allow_null) { + /* incompatible nullability */ + return 0; + } +#endif + /* by-ref constraints on arguments are invariant */ if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) { return 0; @@ -483,6 +491,8 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function } else { smart_str_appends(&str, "NULL"); } + } else if (arg_info->type_hint && arg_info->allow_null) { + smart_str_appends(&str, " = NULL"); } if (++i < num_args) { @@ -563,17 +573,31 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * } if (child->common.prototype && ( - child->common.prototype->common.fn_flags & (ZEND_ACC_ABSTRACT | ZEND_ACC_HAS_RETURN_TYPE) + child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT )) { - if (UNEXPECTED(!zend_do_perform_implementation_check(child, child->common.prototype))) { - zend_string *method_prototype = zend_get_function_declaration(child->common.prototype); - zend_string *child_prototype = zend_get_function_declaration(child); - zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype)); - } - } else if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) { + parent = child->common.prototype; + } + if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) { + int error_level; + const char *error_verb; zend_string *method_prototype = zend_get_function_declaration(parent); zend_string *child_prototype = zend_get_function_declaration(child); - zend_error(E_WARNING, "Declaration of %s should be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype)); + + if (child->common.prototype && ( + child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT + )) { + error_level = E_COMPILE_ERROR; + error_verb = "must"; + } else if ((parent->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) && + (!(child->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + !zend_do_perform_type_hint_check(child, child->common.arg_info - 1, parent, parent->common.arg_info - 1))) { + error_level = E_COMPILE_ERROR; + error_verb = "must"; + } else { + error_level = E_WARNING; + error_verb = "should"; + } + zend_error(error_level, "Declaration of %s %s be compatible with %s", ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(method_prototype)); zend_string_free(child_prototype); zend_string_free(method_prototype); } @@ -636,7 +660,8 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke int parent_num = OBJ_PROP_TO_NUM(parent_info->offset); int child_num = OBJ_PROP_TO_NUM(child_info->offset); - zval_ptr_dtor(&(ce->default_properties_table[parent_num])); + /* Don't keep default properties in GC (thry may be freed by opcache) */ + zval_ptr_dtor_nogc(&(ce->default_properties_table[parent_num])); ce->default_properties_table[parent_num] = ce->default_properties_table[child_num]; ZVAL_UNDEF(&ce->default_properties_table[child_num]); child_info->offset = parent_info->offset; |