From: Dmitry Stogov Date: Wed, 26 Jun 2019 23:25:57 +0000 (+0300) Subject: Merge branch 'PHP-7.4' X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e2effc96b4ab02ec1674d9db2126c8bf02182557;p=php Merge branch 'PHP-7.4' * PHP-7.4: Avoid double checks on early binding --- e2effc96b4ab02ec1674d9db2126c8bf02182557 diff --cc Zend/zend_compile.c index c69735ebc1,fc6dcf5bb7..3d32a087f1 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@@ -6349,12 -6444,15 +6330,13 @@@ zend_op *zend_compile_class_decl(zend_a zend_string_release(lcname); return NULL; } + CG(zend_lineno) = ast->lineno; } - } else { - if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { - zend_string_release(lcname); - zend_build_properties_info_table(ce); - ce->ce_flags |= ZEND_ACC_LINKED; - return NULL; - } + } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { + zend_string_release(lcname); + zend_build_properties_info_table(ce); + ce->ce_flags |= ZEND_ACC_LINKED; + return NULL; } } diff --cc Zend/zend_inheritance.c index 9e3707ad6d,0877f7a70b..f79096edfb --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@@ -771,7 -812,23 +783,22 @@@ static zend_always_inline inheritance_s 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"); } - perform_delayable_implementation_check(ce, child, parent); + if (!checked) { + if (check_only) { + zend_string *unresolved_class; + + 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; + } + /* }}} */ + + static void do_inheritance_check_on_method(zend_function *child, zend_function *parent, zend_class_entry *ce, zval *child_zv) /* {{{ */ + { + do_inheritance_check_on_method_ex(child, parent, ce, child_zv, 0, 0); } /* }}} */ @@@ -2305,39 -2440,48 +2360,43 @@@ ZEND_API void zend_do_link_class(zend_c } } } + /* }}} */ /* Check whether early binding is prevented due to unresolved types in inheritance checks. */ - zend_bool zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) { + 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; - ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) { - uint32_t parent_flags = parent_func->common.fn_flags; - zval *zv; - zend_string *unresolved_class; - if (parent_flags & ZEND_ACC_PRIVATE) { - continue; - } else if (parent_flags & ZEND_ACC_CTOR) { - zend_function *proto = parent_func->common.prototype ? - parent_func->common.prototype : parent_func; + ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) { + zval *zv = zend_hash_find_ex(&ce->function_table, key, 1); + if (zv) { + zend_function *child_func = Z_FUNC_P(zv); + inheritance_status status = + do_inheritance_check_on_method_ex(child_func, parent_func, ce, NULL, 1, 0); - /* ctors only have a prototype if is abstract (or comes from an interface) */ - /* and if that is the case, we want to check inheritance against it */ - if (!(proto->common.fn_flags & ZEND_ACC_ABSTRACT)) { - continue; + if (UNEXPECTED(status != INHERITANCE_SUCCESS)) { - if (EXPECTED(status == INHERITANCE_UNRESOLVED)) { - return INHERITANCE_UNRESOLVED; - } - ZEND_ASSERT(status == INHERITANCE_ERROR); - ret = INHERITANCE_ERROR; ++ return status; } - parent_func = proto; } + } ZEND_HASH_FOREACH_END(); - zv = zend_hash_find_ex(&ce->function_table, key, 1); - if (zv) { - zend_function *child_func = Z_FUNC_P(zv); - inheritance_status status; - return ret; ++ return INHERITANCE_SUCCESS; + } + /* }}} */ - status = zend_do_perform_implementation_check( - &unresolved_class, child_func, parent_func); + zend_bool zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding) /* {{{ */ + { + inheritance_status status = zend_can_early_bind(ce, parent_ce); - if (UNEXPECTED(status == INHERITANCE_UNRESOLVED)) { + if (EXPECTED(status != INHERITANCE_UNRESOLVED)) { + if (delayed_early_binding) { + if (UNEXPECTED(zend_hash_set_bucket_key(EG(class_table), (Bucket*)delayed_early_binding, lcname) == NULL)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); + return 0; + } + } else { + if (UNEXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) == NULL)) { return 0; } } diff --cc Zend/zend_inheritance.h index d5d624cf20,120a56a1ef..05352052cc --- a/Zend/zend_inheritance.h +++ b/Zend/zend_inheritance.h @@@ -30,8 -33,9 +33,8 @@@ ZEND_API void zend_do_inheritance_ex(ze ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name); void zend_verify_abstract_class(zend_class_entry *ce); -void zend_check_deprecated_constructor(const zend_class_entry *ce); void zend_build_properties_info_table(zend_class_entry *ce); - zend_bool zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce); + zend_bool zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding); END_EXTERN_C()