diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 084c47f45bc47..04244b0de626a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -8057,8 +8057,11 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
ce->ce_flags |= ZEND_ACC_LINKED;
zend_observer_class_linked_notify(ce, lcname);
return;
+ } else {
+ goto link_unbound;
}
} else if (!extends_ast) {
+link_unbound:
/* Link unbound simple class */
zend_build_properties_info_table(ce);
ce->ce_flags |= ZEND_ACC_LINKED;
@@ -8098,11 +8101,17 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
zend_add_literal_string(&key);
opline->opcode = ZEND_DECLARE_CLASS;
- if (extends_ast && toplevel
+ if (toplevel
&& (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
/* We currently don't early-bind classes that implement interfaces or use traits */
&& !ce->num_interfaces && !ce->num_traits
) {
+ if (!extends_ast) {
+ /* Use empty string for classes without parents to avoid new handler, and special
+ * handling of zend_early_binding. */
+ opline->op2_type = IS_CONST;
+ LITERAL_STR(opline->op2, ZSTR_EMPTY_ALLOC());
+ }
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
opline->extended_value = zend_alloc_cache_slot();
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index ff3a4d7080751..17bbae8335445 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -3276,8 +3276,17 @@ ZEND_API zend_class_entry *zend_try_early_bind(zend_class_entry *ce, zend_class_
inheritance_status status;
zend_class_entry *proto = NULL;
zend_class_entry *orig_linking_class;
- uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
+ if (ce->ce_flags & ZEND_ACC_LINKED) {
+ ZEND_ASSERT(ce->parent == NULL);
+ if (UNEXPECTED(!register_early_bound_ce(delayed_early_binding, lcname, ce))) {
+ return NULL;
+ }
+ zend_observer_class_linked_notify(ce, lcname);
+ return ce;
+ }
+
+ uint32_t is_cacheable = ce->ce_flags & ZEND_ACC_IMMUTABLE;
UPDATE_IS_CACHEABLE(parent_ce);
if (is_cacheable) {
if (zend_inheritance_cache_get && zend_inheritance_cache_add) {
diff --git a/ext/opcache/tests/gh8846-1.inc b/ext/opcache/tests/gh8846-1.inc
new file mode 100644
index 0000000000000..6169e1cfea4a9
--- /dev/null
+++ b/ext/opcache/tests/gh8846-1.inc
@@ -0,0 +1,4 @@
+
+--CLEAN--
+
+--EXPECTF--
+bool(true)
+
+Fatal error: Cannot declare class Foo, because the name is already in use in %sgh8846-2.inc on line %d
+
+bool(true)
+Ok
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 1a67e2b6e661b..e021270eff3d3 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -357,9 +357,10 @@ static void zend_accel_do_delayed_early_binding(
zval *zv = zend_hash_find_known_hash(EG(class_table), early_binding->rtd_key);
if (zv) {
zend_class_entry *orig_ce = Z_CE_P(zv);
- zend_class_entry *parent_ce =
- zend_hash_find_ex_ptr(EG(class_table), early_binding->lc_parent_name, 1);
- if (parent_ce) {
+ zend_class_entry *parent_ce = !(orig_ce->ce_flags & ZEND_ACC_LINKED)
+ ? zend_hash_find_ex_ptr(EG(class_table), early_binding->lc_parent_name, 1)
+ : NULL;
+ if (parent_ce || (orig_ce->ce_flags & ZEND_ACC_LINKED)) {
ce = zend_try_early_bind(orig_ce, parent_ce, early_binding->lcname, zv);
}
}