return fn->common.type == ZEND_USER_FUNCTION ? fn->op_array.line_start : 0;
}
- int error_level, const char *error_verb, zend_function *child, zend_function *parent,
+ static void ZEND_COLD emit_incompatible_method_error(
- zend_error_at(error_level, NULL, func_lineno(child),
++ zend_function *child, zend_function *parent,
+ inheritance_status status, zend_string *unresolved_class) {
+ zend_string *parent_prototype = zend_get_function_declaration(parent);
+ zend_string *child_prototype = zend_get_function_declaration(child);
+ if (status == INHERITANCE_UNRESOLVED) {
- zend_error_at(error_level, NULL, func_lineno(child),
- "Declaration of %s %s be compatible with %s",
- ZSTR_VAL(child_prototype), error_verb, ZSTR_VAL(parent_prototype));
++ zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
+ "Could not check compatibility between %s and %s, because class %s is not available",
+ ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype), ZSTR_VAL(unresolved_class));
+ } else {
++ zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
++ "Declaration of %s must be compatible with %s",
++ ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype));
+ }
+ zend_string_efree(child_prototype);
+ zend_string_efree(parent_prototype);
+ }
+
static void do_inheritance_check_on_method(zend_function *child, zend_function *parent, zend_class_entry *ce, zval *child_zv) /* {{{ */
{
uint32_t child_flags;
ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
}
- if (UNEXPECTED(!zend_do_perform_implementation_check(child, parent))) {
- zend_string *method_prototype = zend_get_function_declaration(parent);
- zend_string *child_prototype = zend_get_function_declaration(child);
- zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child),
- "Declaration of %s must be compatible with %s",
- ZSTR_VAL(child_prototype), ZSTR_VAL(method_prototype));
- zend_string_efree(child_prototype);
- zend_string_efree(method_prototype);
+ status = zend_do_perform_implementation_check(&unresolved_class, child, parent);
- if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
- int error_level;
- const char *error_verb;
- 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_perform_covariant_type_check(&unresolved_class, child, child->common.arg_info - 1, parent, parent->common.arg_info - 1) != INHERITANCE_SUCCESS)) {
- error_level = E_COMPILE_ERROR;
- error_verb = "must";
- } else {
- error_level = E_WARNING;
- error_verb = "should";
- }
- emit_incompatible_method_error(
- error_level, error_verb, child, parent, status, unresolved_class);
++ if (status != INHERITANCE_SUCCESS) {
++ emit_incompatible_method_error(child, parent, status, unresolved_class);
}
}
} while (0);
if ((existing_fn = zend_hash_find_ptr(*overridden, key)) != NULL) {
if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
/* Make sure the trait method is compatible with previosly declared abstract method */
- if (UNEXPECTED(!zend_do_perform_implementation_check(fn, existing_fn))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
- ZSTR_VAL(zend_get_function_declaration(fn)),
- ZSTR_VAL(zend_get_function_declaration(existing_fn)));
+ status = zend_do_perform_implementation_check(
+ &unresolved_class, fn, existing_fn);
+ if (status != INHERITANCE_SUCCESS) {
+ emit_incompatible_method_error(
- E_COMPILE_ERROR, "must", fn, existing_fn, status, unresolved_class);
++ fn, existing_fn, status, unresolved_class);
}
}
if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
/* Make sure the abstract declaration is compatible with previous declaration */
- if (UNEXPECTED(!zend_do_perform_implementation_check(existing_fn, fn))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
- ZSTR_VAL(zend_get_function_declaration(existing_fn)),
- ZSTR_VAL(zend_get_function_declaration(fn)));
+ status = zend_do_perform_implementation_check(
+ &unresolved_class, existing_fn, fn);
+ if (status != INHERITANCE_SUCCESS) {
+ emit_incompatible_method_error(
- E_COMPILE_ERROR, "must", existing_fn, fn, status, unresolved_class);
++ existing_fn, fn, status, unresolved_class);
}
return;
}
} else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT &&
(existing_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
/* Make sure the trait method is compatible with previosly declared abstract method */
- if (UNEXPECTED(!zend_do_perform_implementation_check(fn, existing_fn))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
- ZSTR_VAL(zend_get_function_declaration(fn)),
- ZSTR_VAL(zend_get_function_declaration(existing_fn)));
+ status = zend_do_perform_implementation_check(&unresolved_class, fn, existing_fn);
+ if (status != INHERITANCE_SUCCESS) {
- emit_incompatible_method_error(
- E_COMPILE_ERROR, "must", fn, existing_fn, status, unresolved_class);
++ emit_incompatible_method_error(fn, existing_fn, status, unresolved_class);
}
} else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
/* Make sure the abstract declaration is compatible with previous declaration */
- if (UNEXPECTED(!zend_do_perform_implementation_check(existing_fn, fn))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
- ZSTR_VAL(zend_get_function_declaration(existing_fn)),
- ZSTR_VAL(zend_get_function_declaration(fn)));
+ status = zend_do_perform_implementation_check(&unresolved_class, existing_fn, fn);
+ if (status != INHERITANCE_SUCCESS) {
- emit_incompatible_method_error(
- E_COMPILE_ERROR, "must", existing_fn, fn, status, unresolved_class);
++ emit_incompatible_method_error(existing_fn, fn, status, unresolved_class);
}
return;
} else if (UNEXPECTED(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) {