From: Dmitry Stogov Date: Mon, 27 Aug 2018 13:40:25 +0000 (+0300) Subject: Cleanup class linking X-Git-Tag: php-7.4.0alpha1~2049 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2fbfdde1b618b67fda83e624edfe6e7163dc4f6d;p=php Cleanup class linking --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2b3900164a..13622fbe27 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1095,14 +1095,7 @@ ZEND_API int do_bind_class(zval *lcname) /* {{{ */ return FAILURE; } else { ce->refcount++; - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { - zend_do_bind_traits(ce); - } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { - zend_do_implement_interfaces(ce); - } else if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - zend_verify_abstract_class(ce); - } + zend_do_link_class(ce, NULL); return SUCCESS; } } @@ -1129,12 +1122,6 @@ ZEND_API int do_bind_inherited_class(zval *lcname, zend_class_entry *parent_ce) ce = (zend_class_entry*)Z_PTR_P(zv); - if (zend_hash_exists(EG(class_table), Z_STR_P(lcname))) { - 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)); - } - - zend_do_inheritance(ce, parent_ce); - ce->refcount++; /* Register the derived class */ @@ -1142,12 +1129,7 @@ ZEND_API int do_bind_inherited_class(zval *lcname, zend_class_entry *parent_ce) 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)); } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { - zend_do_bind_traits(ce); - } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { - zend_do_implement_interfaces(ce); - } + zend_do_link_class(ce, parent_ce); return SUCCESS; } @@ -6356,13 +6338,10 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ if (implements_ast) { zend_compile_implements(implements_ast); - if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - zend_verify_abstract_class(ce); - } - } else if (extends_ast) { - if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - zend_verify_abstract_class(ce); - } + } + + if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { + zend_verify_abstract_class(ce); } CG(active_class_entry) = original_ce; @@ -6380,17 +6359,15 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { CG(zend_lineno) = decl->end_lineno; zend_do_inheritance(ce, parent_ce); + if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { + zend_verify_abstract_class(ce); + } CG(zend_lineno) = ast->lineno; zend_string_release(lcname); return; } } } else { - if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - CG(zend_lineno) = decl->end_lineno; - zend_verify_abstract_class(ce); - CG(zend_lineno) = ast->lineno; - } if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { zend_string_release(lcname); return; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index ef6864ecfe..59db678b09 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -999,11 +999,10 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent do_inherit_parent_constructor(ce); - if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) { - ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; - } else if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) { - /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */ - zend_verify_abstract_class(ce); + if (ce->type == ZEND_INTERNAL_CLASS) { + if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { + ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS; + } } ce->ce_flags |= parent_ce->ce_flags & (ZEND_HAS_STATIC_IN_METHODS | ZEND_ACC_USE_GUARDS); } @@ -1100,7 +1099,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } /* }}} */ -ZEND_API void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */ +static void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */ { zend_class_entry **interfaces, *iface; uint32_t num_interfaces = 0; @@ -1183,10 +1182,6 @@ ZEND_API void zend_do_implement_interfaces(zend_class_entry *ce) /* {{{ */ zend_do_inherit_interfaces(ce, iface); } } - - if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - zend_verify_abstract_class(ce); - } } /* }}} */ @@ -1802,7 +1797,7 @@ static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce, } /* }}} */ -ZEND_API void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */ +static void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */ { HashTable **exclude_tables; zend_class_entry **aliases; @@ -1855,16 +1850,8 @@ ZEND_API void zend_do_bind_traits(zend_class_entry *ce) /* {{{ */ efree(traits); - /* verify that all abstract methods from traits have been implemented */ - zend_verify_abstract_class(ce); - /* Emit E_DEPRECATED for PHP 4 constructors */ zend_check_deprecated_constructor(ce); - - /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */ - if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { - ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; - } } /* }}} */ @@ -1930,22 +1917,41 @@ void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */ zend_function *func; zend_abstract_info ai; - if ((ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) && !(ce->ce_flags & (ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - memset(&ai, 0, sizeof(ai)); + ZEND_ASSERT((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS); + memset(&ai, 0, sizeof(ai)); - ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { - zend_verify_abstract_class_function(func, &ai); - } ZEND_HASH_FOREACH_END(); + ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { + zend_verify_abstract_class_function(func, &ai); + } ZEND_HASH_FOREACH_END(); - if (ai.cnt) { - zend_error_noreturn(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", - ZSTR_VAL(ce->name), ai.cnt, - ai.cnt > 1 ? "s" : "", - DISPLAY_ABSTRACT_FN(0), - DISPLAY_ABSTRACT_FN(1), - DISPLAY_ABSTRACT_FN(2) - ); - } + if (ai.cnt) { + zend_error_noreturn(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")", + ZSTR_VAL(ce->name), ai.cnt, + ai.cnt > 1 ? "s" : "", + DISPLAY_ABSTRACT_FN(0), + DISPLAY_ABSTRACT_FN(1), + DISPLAY_ABSTRACT_FN(2) + ); + } else { + /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */ + ce->ce_flags &= ~ZEND_ACC_IMPLICIT_ABSTRACT_CLASS; + } +} +/* }}} */ + +ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent) /* {{{ */ +{ + if (parent) { + zend_do_inheritance(ce, parent); + } + if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { + zend_do_bind_traits(ce); + } + if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { + zend_do_implement_interfaces(ce); + } + if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { + zend_verify_abstract_class(ce); } } /* }}} */ diff --git a/Zend/zend_inheritance.h b/Zend/zend_inheritance.h index e30e264110..d6cca74389 100644 --- a/Zend/zend_inheritance.h +++ b/Zend/zend_inheritance.h @@ -25,12 +25,10 @@ BEGIN_EXTERN_C() ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface); - -ZEND_API void zend_do_bind_traits(zend_class_entry *ce); -ZEND_API void zend_do_implement_interfaces(zend_class_entry *ce); - ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce); +ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent_ce); + void zend_verify_abstract_class(zend_class_entry *ce); void zend_check_deprecated_constructor(const zend_class_entry *ce); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6b5a350e51..e51589a40a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6707,14 +6707,7 @@ ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY, JMP_ADDR) ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { - zend_do_bind_traits(ce); - } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { - zend_do_implement_interfaces(ce); - } else if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - zend_verify_abstract_class(ce); - } + zend_do_link_class(ce, NULL); ce->ce_flags |= ZEND_ACC_ANON_BOUND; ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -6744,13 +6737,7 @@ ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, CONST, CONST, JMP_ADDR) HANDLE_EXCEPTION(); } - zend_do_inheritance(ce, parent); - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { - zend_do_bind_traits(ce); - } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { - zend_do_implement_interfaces(ce); - } + zend_do_link_class(ce, parent); ce->ce_flags |= ZEND_ACC_ANON_BOUND; ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 19e3304203..711c9fae06 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1600,14 +1600,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_CONTINUE(); } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { - zend_do_bind_traits(ce); - } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { - zend_do_implement_interfaces(ce); - } else if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) { - zend_verify_abstract_class(ce); - } + zend_do_link_class(ce, NULL); ce->ce_flags |= ZEND_ACC_ANON_BOUND; ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -5832,13 +5825,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_INHERITED_CLASS_S HANDLE_EXCEPTION(); } - zend_do_inheritance(ce, parent); - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { - zend_do_bind_traits(ce); - } - if (ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES) { - zend_do_implement_interfaces(ce); - } + zend_do_link_class(ce, parent); ce->ce_flags |= ZEND_ACC_ANON_BOUND; ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); }