Skip to content

Commit

Permalink
Cleanup class linking
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Aug 27, 2018
1 parent ea96289 commit 2fbfdde
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 99 deletions.
41 changes: 9 additions & 32 deletions Zend/zend_compile.c
Expand Up @@ -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;
}
}
Expand All @@ -1129,25 +1122,14 @@ 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 */
if (zend_hash_add_ptr(EG(class_table), Z_STR_P(lcname), ce) == 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));
}

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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
72 changes: 39 additions & 33 deletions Zend/zend_inheritance.c
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
/* }}} */

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
/* }}} */

Expand Down Expand Up @@ -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);
}
}
/* }}} */
Expand Down
6 changes: 2 additions & 4 deletions Zend/zend_inheritance.h
Expand Up @@ -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);

Expand Down
17 changes: 2 additions & 15 deletions Zend/zend_vm_def.h
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
}
Expand Down
17 changes: 2 additions & 15 deletions Zend/zend_vm_execute.h
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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();
}
Expand Down

0 comments on commit 2fbfdde

Please sign in to comment.