]> granicus.if.org Git - php/commitdiff
Cleanup class linking
authorDmitry Stogov <dmitry@zend.com>
Mon, 27 Aug 2018 13:40:25 +0000 (16:40 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 27 Aug 2018 13:40:25 +0000 (16:40 +0300)
Zend/zend_compile.c
Zend/zend_inheritance.c
Zend/zend_inheritance.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 2b3900164a90012afd8e2877e27727f8303b82b2..13622fbe27dbfc8054126fb5ba5757e58f484268 100644 (file)
@@ -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;
index ef6864ecfea1581c6f77d80aa984d77aabca4c3e..59db678b099fa12a2206cd9335b2e1ad3ba4bd80 100644 (file)
@@ -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);
        }
 }
 /* }}} */
index e30e26411042c2bb32041b317b3627956370c9ab..d6cca74389b3d34158b9ffaa34206ac29a1864ac 100644 (file)
 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);
 
index 6b5a350e5133e5f494b5cc42a326be8c6f0e71f3..e51589a40a1b220da6124250a401c1bc52e9575e 100644 (file)
@@ -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();
 }
index 19e33042036e6d1477ce32f8140023495720307e..711c9fae0691371b39a02c1957294611a8b55451 100644 (file)
@@ -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();
 }