summaryrefslogtreecommitdiff
path: root/Zend/zend_inheritance.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r--Zend/zend_inheritance.c129
1 files changed, 22 insertions, 107 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 9c8acca865..6d1aef5b30 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -28,8 +28,7 @@
static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *dependency_ce);
static void add_compatibility_obligation(
- zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn,
- zend_bool always_error);
+ zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn);
static void overridden_ptr_dtor(zval *zv) /* {{{ */
{
@@ -680,49 +679,26 @@ static zend_always_inline uint32_t func_lineno(const zend_function *fn) {
}
static void ZEND_COLD emit_incompatible_method_error(
- int error_level, const char *error_verb,
const zend_function *child, const 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),
+ 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(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),
+ "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 ZEND_COLD emit_incompatible_method_error_or_warning(
- const zend_function *child, const zend_function *parent,
- inheritance_status status, zend_string *unresolved_class, zend_bool always_error) {
- int error_level;
- const char *error_verb;
- if (always_error ||
- (child->common.prototype &&
- (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) ||
- ((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);
-}
-
static void perform_delayable_implementation_check(
zend_class_entry *ce, const zend_function *fe,
- const zend_function *proto, zend_bool always_error)
+ const zend_function *proto)
{
zend_string *unresolved_class;
inheritance_status status = zend_do_perform_implementation_check(
@@ -730,16 +706,11 @@ static void perform_delayable_implementation_check(
if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
- add_compatibility_obligation(ce, fe, proto, always_error);
+ add_compatibility_obligation(ce, fe, proto);
} else {
ZEND_ASSERT(status == INHERITANCE_ERROR);
- if (always_error) {
- emit_incompatible_method_error(
- E_COMPILE_ERROR, "must", fe, proto, status, unresolved_class);
- } else {
- emit_incompatible_method_error_or_warning(
- fe, proto, status, unresolved_class, always_error);
- }
+ emit_incompatible_method_error(
+ fe, proto, status, unresolved_class);
}
}
}
@@ -843,8 +814,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(z
return zend_do_perform_implementation_check(
&unresolved_class, child, parent);
}
- perform_delayable_implementation_check(
- ce, child, parent, /*always_error*/0);
+ perform_delayable_implementation_check(ce, child, parent);
}
return INHERITANCE_SUCCESS;
}
@@ -1511,14 +1481,11 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
ce->serialize_func = fe;
} else if (zend_string_equals_literal(mname, "unserialize")) {
ce->unserialize_func = fe;
- } else if (ZSTR_LEN(ce->name) != ZSTR_LEN(mname) && (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_')) {
+ } else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') {
/* pass */
} else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
ce->clone = fe;
} else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
- if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
- zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
- }
ce->constructor = fe;
} else if (zend_string_equals_literal(mname, ZEND_DESTRUCTOR_FUNC_NAME)) {
ce->destructor = fe;
@@ -1542,17 +1509,6 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
ce->__tostring = fe;
} else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) {
ce->__debugInfo = fe;
- } else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
- zend_string *lowercase_name = zend_string_tolower(ce->name);
- lowercase_name = zend_new_interned_string(lowercase_name);
- if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) {
- if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
- zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
- }
- ce->constructor = fe;
- fe->common.fn_flags |= ZEND_ACC_CTOR;
- }
- zend_string_release_ex(lowercase_name, 0);
}
}
/* }}} */
@@ -1578,13 +1534,11 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
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 */
- perform_delayable_implementation_check(
- ce, fn, existing_fn, /*always_error*/ 1);
+ perform_delayable_implementation_check(ce, fn, existing_fn);
}
if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
/* Make sure the abstract declaration is compatible with previous declaration */
- perform_delayable_implementation_check(
- ce, existing_fn, fn, /*always_error*/ 1);
+ perform_delayable_implementation_check(ce, existing_fn, fn);
return;
}
}
@@ -1597,12 +1551,10 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s
} 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 */
- perform_delayable_implementation_check(
- ce, fn, existing_fn, /*always_error*/ 1);
+ perform_delayable_implementation_check(ce, fn, existing_fn);
} else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
/* Make sure the abstract declaration is compatible with previous declaration */
- perform_delayable_implementation_check(
- ce, existing_fn, fn, /*always_error*/ 1);
+ perform_delayable_implementation_check(ce, existing_fn, fn);
return;
} else if (UNEXPECTED(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) {
/* two traits can't define the same non-abstract method */
@@ -2150,32 +2102,6 @@ static void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */
zend_do_traits_property_binding(ce, traits);
efree(traits);
-
- /* Emit E_DEPRECATED for PHP 4 constructors */
- zend_check_deprecated_constructor(ce);
-}
-/* }}} */
-
-
-static zend_bool zend_has_deprecated_constructor(const zend_class_entry *ce) /* {{{ */
-{
- const zend_string *constructor_name;
- if (!ce->constructor) {
- return 0;
- }
- constructor_name = ce->constructor->common.function_name;
- return !zend_binary_strcasecmp(
- ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
- ZSTR_VAL(constructor_name), ZSTR_LEN(constructor_name)
- );
-}
-/* }}} */
-
-void zend_check_deprecated_constructor(const zend_class_entry *ce) /* {{{ */
-{
- if (zend_has_deprecated_constructor(ce)) {
- zend_error(E_DEPRECATED, "Methods with the same name as their class will not be constructors in a future version of PHP; %s has a deprecated constructor", ZSTR_VAL(ce->name));
- }
}
/* }}} */
@@ -2247,7 +2173,6 @@ typedef struct {
struct {
const zend_function *parent_fn;
const zend_function *child_fn;
- zend_bool always_error;
};
};
} variance_obligation;
@@ -2291,14 +2216,12 @@ static void add_dependency_obligation(zend_class_entry *ce, zend_class_entry *de
}
static void add_compatibility_obligation(
- zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn,
- zend_bool always_error) {
+ zend_class_entry *ce, const zend_function *child_fn, const zend_function *parent_fn) {
HashTable *obligations = get_or_init_obligations_for_class(ce);
variance_obligation *obligation = emalloc(sizeof(variance_obligation));
obligation->type = OBLIGATION_COMPATIBILITY;
obligation->child_fn = child_fn;
obligation->parent_fn = parent_fn;
- obligation->always_error = always_error;
zend_hash_next_index_insert_ptr(obligations, obligation);
}
@@ -2318,15 +2241,13 @@ static int check_variance_obligation(zval *zv) {
zend_string *unresolved_class;
inheritance_status status = zend_do_perform_implementation_check(
&unresolved_class, obligation->child_fn, obligation->parent_fn);
-
if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
return ZEND_HASH_APPLY_KEEP;
}
ZEND_ASSERT(status == INHERITANCE_ERROR);
- emit_incompatible_method_error_or_warning(
- obligation->child_fn, obligation->parent_fn, status, unresolved_class,
- obligation->always_error);
+ emit_incompatible_method_error(
+ obligation->child_fn, obligation->parent_fn, status, unresolved_class);
}
/* Either the compatibility check was successful or only threw a warning. */
}
@@ -2388,9 +2309,8 @@ static void report_variance_errors(zend_class_entry *ce) {
status = zend_do_perform_implementation_check(
&unresolved_class, obligation->child_fn, obligation->parent_fn);
ZEND_ASSERT(status == INHERITANCE_UNRESOLVED);
- emit_incompatible_method_error_or_warning(
- obligation->child_fn, obligation->parent_fn,
- status, unresolved_class, obligation->always_error);
+ emit_incompatible_method_error(
+ obligation->child_fn, obligation->parent_fn, status, unresolved_class);
} ZEND_HASH_FOREACH_END();
/* Only warnings were thrown above -- that means that there are incompatibilities, but only
@@ -2440,7 +2360,6 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_na
/* Check whether early binding is prevented due to unresolved types in inheritance checks. */
static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
{
- inheritance_status ret = INHERITANCE_SUCCESS;
zend_string *key;
zend_function *parent_func;
@@ -2452,16 +2371,12 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e
do_inheritance_check_on_method_ex(child_func, parent_func, ce, NULL, 1, 0);
if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
- if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
- return INHERITANCE_UNRESOLVED;
- }
- ZEND_ASSERT(status == INHERITANCE_ERROR);
- ret = INHERITANCE_ERROR;
+ return status;
}
}
} ZEND_HASH_FOREACH_END();
- return ret;
+ return INHERITANCE_SUCCESS;
}
/* }}} */