diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-12-08 12:40:42 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-12-08 12:40:42 +0300 |
commit | a75c195000b3226904103244fa9c3d0ce1111838 (patch) | |
tree | 1242c6dc6078647c43a295e4c83d8b6d00e88324 /Zend/zend_inheritance.c | |
parent | a8b7d0c29d13902f748c08d8a58e3d304450a1a2 (diff) | |
download | php-git-a75c195000b3226904103244fa9c3d0ce1111838.tar.gz |
Implemented the RFC `Support Class Constant Visibility`.
Squashed commit of the following:
commit f11ca0e7a57793fa0e3e7f6d451720e6c42bb0b9
Author: Dmitry Stogov <dmitry@zend.com>
Date: Tue Dec 8 12:38:42 2015 +0300
Fixed test expectation
commit 211f873f542504d0a0f72b6b5cb23908a1c99a2d
Author: Dmitry Stogov <dmitry@zend.com>
Date: Tue Dec 8 12:28:38 2015 +0300
Embed zend_class_constant.flags into zend_class_constants.value.u2.access_flags
commit 51deab84b2cdbf9cdb1a838cf33b2ee45c61748b
Author: Dmitry Stogov <dmitry@zend.com>
Date: Mon Dec 7 11:18:55 2015 +0300
Fixed issues found by Nikita
commit 544dbd5b47e40d38a8ccb96bc5583e9cb7fdd723
Author: Dmitry Stogov <dmitry@zend.com>
Date: Sat Dec 5 02:41:05 2015 +0300
Refactored immplementation of https://wiki.php.net/rfc/class_const_visibility
@reeze created an RFC here and I emailed internals here and didn't get any responses positive/negative.
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r-- | Zend/zend_inheritance.c | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 73b67f5216..d9367d82f5 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -698,21 +698,29 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_ } /* }}} */ -static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */ +static void do_inherit_class_constant(zend_string *name, zend_class_constant *parent_const, zend_class_entry *ce) /* {{{ */ { - if (!zend_hash_exists(&ce->constants_table, name)) { - if (!Z_ISREF_P(zv)) { - if (parent_ce->type == ZEND_INTERNAL_CLASS) { - ZVAL_NEW_PERSISTENT_REF(zv, zv); - } else { - ZVAL_NEW_REF(zv, zv); - } + zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, name); + + if (c != NULL) { + if (UNEXPECTED((Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PPP_MASK) > (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PPP_MASK))) { + zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in class %s)%s", + ZSTR_VAL(ce->name), ZSTR_VAL(name), zend_visibility_string(Z_ACCESS_FLAGS(parent_const->value)), ZSTR_VAL(ce->parent->name), (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PUBLIC) ? "" : " or weaker"); } - if (Z_CONSTANT_P(Z_REFVAL_P(zv))) { + } else if (!(Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PRIVATE)) { + if (Z_CONSTANT(parent_const->value)) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } - Z_ADDREF_P(zv); - _zend_hash_append(&ce->constants_table, name, zv); + if (Z_REFCOUNTED(parent_const->value)) { + Z_ADDREF(parent_const->value); + } + if (ce->type & ZEND_INTERNAL_CLASS) { + c = pemalloc(sizeof(zend_class_constant), 1); + } else { + c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); + } + memcpy(c, parent_const, sizeof(zend_class_constant)); + _zend_hash_append_ptr(&ce->constants_table, name, c); } } /* }}} */ @@ -722,7 +730,6 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent zend_property_info *property_info; zend_function *func; zend_string *key; - zval *zv; if (UNEXPECTED(ce->ce_flags & ZEND_ACC_INTERFACE)) { /* Interface can only inherit other interfaces */ @@ -859,12 +866,14 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent } if (zend_hash_num_elements(&parent_ce->constants_table)) { + zend_class_constant *c; + zend_hash_extend(&ce->constants_table, zend_hash_num_elements(&ce->constants_table) + zend_hash_num_elements(&parent_ce->constants_table), 0); - ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) { - do_inherit_class_constant(key, zv, ce, parent_ce); + ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) { + do_inherit_class_constant(key, c, ce); } ZEND_HASH_FOREACH_END(); } @@ -894,14 +903,12 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent } /* }}} */ -static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */ +static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zend_class_constant *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */ { - zval *old_constant; + zend_class_constant *old_constant; - if ((old_constant = zend_hash_find(child_constants_table, name)) != NULL) { - if (!Z_ISREF_P(old_constant) || - !Z_ISREF_P(parent_constant) || - Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) { + if ((old_constant = zend_hash_find_ptr(child_constants_table, name)) != NULL) { + if (old_constant->ce != parent_constant->ce) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", ZSTR_VAL(name), ZSTR_VAL(iface->name)); } return 0; @@ -910,21 +917,16 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zva } /* }}} */ -static void do_inherit_iface_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ +static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ { - if (do_inherit_constant_check(&ce->constants_table, zv, name, iface)) { - if (!Z_ISREF_P(zv)) { - if (iface->type == ZEND_INTERNAL_CLASS) { - ZVAL_NEW_PERSISTENT_REF(zv, zv); - } else { - ZVAL_NEW_REF(zv, zv); - } + if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) { + if (Z_REFCOUNTED(c->value)) { + Z_ADDREF(c->value); } - Z_ADDREF_P(zv); - if (Z_CONSTANT_P(Z_REFVAL_P(zv))) { + if (Z_CONSTANT(c->value)) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } - zend_hash_update(&ce->constants_table, name, zv); + zend_hash_update_ptr(&ce->constants_table, name, c); } } /* }}} */ @@ -936,7 +938,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0; zend_function *func; zend_string *key; - zval *zv; + zend_class_constant *c; for (i = 0; i < ce->num_interfaces; i++) { if (ce->interfaces[i] == NULL) { @@ -952,8 +954,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } if (ignore) { /* Check for attempt to redeclare interface constants */ - ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, zv) { - do_inherit_constant_check(&iface->constants_table, zv, key, iface); + ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) { + do_inherit_constant_check(&iface->constants_table, c, key, iface); } ZEND_HASH_FOREACH_END(); } else { if (ce->num_interfaces >= current_iface_num) { @@ -965,8 +967,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } ce->interfaces[ce->num_interfaces++] = iface; - ZEND_HASH_FOREACH_STR_KEY_VAL(&iface->constants_table, key, zv) { - do_inherit_iface_constant(key, zv, ce, iface); + ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) { + do_inherit_iface_constant(key, c, ce, iface); } ZEND_HASH_FOREACH_END(); ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) { |