diff options
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index fccc45c994..b7fa412d9f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6440,10 +6440,32 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ if (!zend_hash_exists(CG(class_table), lcname)) { zend_hash_add_ptr(CG(class_table), lcname, ce); } else { - /* this anonymous class has been included */ + /* This anonymous class has been included, reuse the existing definition. + * NB: This behavior is buggy, and this should always result in a separate + * class declaration. However, until the problem of RTD key collisions is + * solved, this gives a behavior close to what is expected. */ zval zv; ZVAL_PTR(&zv, ce); destroy_zend_class(&zv); + ce = zend_hash_find_ptr(CG(class_table), lcname); + + /* Manually replicate emission of necessary inheritance opcodes here. We cannot + * reuse the general code, as we only want to emit the opcodes, without modifying + * the reused class definition. */ + if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) { + zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL); + } + if (implements_ast) { + zend_ast_list *iface_list = zend_ast_get_list(implements_ast); + uint32_t i; + for (i = 0; i < iface_list->children; i++) { + opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, &declare_node, NULL); + opline->op2_type = IS_CONST; + opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), + zend_resolve_class_name_ast(iface_list->child[i])); + } + zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL); + } return; } } else { |