Skip to content

Commit 409d93d

Browse files
committed
Implement delyed early binding for classes without parents
Fixes GH-8846
1 parent 5820528 commit 409d93d

File tree

9 files changed

+957
-847
lines changed

9 files changed

+957
-847
lines changed

Zend/zend_compile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8098,7 +8098,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
80988098
zend_add_literal_string(&key);
80998099

81008100
opline->opcode = ZEND_DECLARE_CLASS;
8101-
if (extends_ast && toplevel
8101+
if (toplevel
81028102
&& (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
81038103
/* We currently don't early-bind classes that implement interfaces or use traits */
81048104
&& !ce->num_interfaces && !ce->num_traits

Zend/zend_inheritance.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3184,6 +3184,10 @@ ZEND_API zend_class_entry *zend_do_link_class(zend_class_entry *ce, zend_string
31843184
/* Check whether early binding is prevented due to unresolved types in inheritance checks. */
31853185
static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
31863186
{
3187+
if (parent_ce == NULL) {
3188+
return INHERITANCE_SUCCESS;
3189+
}
3190+
31873191
zend_string *key;
31883192
zend_function *parent_func;
31893193
zend_property_info *parent_info;
@@ -3278,7 +3282,9 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
32783282
zend_class_entry *orig_linking_class;
32793283
uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
32803284

3281-
UPDATE_IS_CACHEABLE(parent_ce);
3285+
if (parent_ce) {
3286+
UPDATE_IS_CACHEABLE(parent_ce);
3287+
}
32823288
if (is_cacheable) {
32833289
if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
32843290
zend_class_entry *ret = zend_inheritance_cache_get(ce, parent_ce, NULL);
@@ -3321,7 +3327,9 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
33213327
zend_begin_record_errors();
33223328
}
33233329

3324-
zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS);
3330+
if (parent_ce) {
3331+
zend_do_inheritance_ex(ce, parent_ce, status == INHERITANCE_SUCCESS);
3332+
}
33253333
if (parent_ce && parent_ce->num_interfaces) {
33263334
zend_do_inherit_interfaces(ce, parent_ce);
33273335
}

Zend/zend_vm_def.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7791,7 +7791,7 @@ ZEND_VM_HANDLER(144, ZEND_DECLARE_CLASS, CONST, ANY)
77917791
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
77927792
}
77937793

7794-
ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
7794+
ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST|UNUSED)
77957795
{
77967796
USE_OPLINE
77977797

@@ -7801,7 +7801,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
78017801
zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
78027802
if (zv) {
78037803
SAVE_OPLINE();
7804-
ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
7804+
ce = zend_bind_class_in_slot(zv, lcname, OP2_TYPE == IS_CONST ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
78057805
if (!ce) {
78067806
HANDLE_EXCEPTION();
78077807
}

0 commit comments

Comments
 (0)