summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c24
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 {