diff --git a/Zend/tests/enum/extending-builtin-error.phpt b/Zend/tests/enum/extending-builtin-error.phpt new file mode 100644 index 00000000000..9d007689bc2 --- /dev/null +++ b/Zend/tests/enum/extending-builtin-error.phpt @@ -0,0 +1,10 @@ +--TEST-- +GH-16315: Extending built-in enum +--FILE-- + +--EXPECTF-- +Fatal error: Class Demo cannot extend enum RoundingMode in %s on line 3 diff --git a/Zend/tests/enum/extending-user-error.phpt b/Zend/tests/enum/extending-user-error.phpt new file mode 100644 index 00000000000..c68db491f35 --- /dev/null +++ b/Zend/tests/enum/extending-user-error.phpt @@ -0,0 +1,12 @@ +--TEST-- +GH-16315: Extending userland enum +--FILE-- + +--EXPECTF-- +Fatal error: Class Demo cannot extend enum MyEnum in %s on line 5 diff --git a/Zend/tests/enum/final.phpt b/Zend/tests/enum/final.phpt index 353e1868d2f..a373b28ddec 100644 --- a/Zend/tests/enum/final.phpt +++ b/Zend/tests/enum/final.phpt @@ -5,8 +5,9 @@ Enum is final enum Foo {} -class Bar extends Foo {} +$final = new ReflectionClass(Foo::class)->isFinal(); +var_dump($final); ?> ---EXPECTF-- -Fatal error: Class Bar cannot extend final class Foo in %s on line %d +--EXPECT-- +bool(true) diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 88f1d3447c2..16af5f0ac61 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1757,7 +1757,12 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par if (UNEXPECTED(!(parent_ce->ce_flags & ZEND_ACC_INTERFACE))) { zend_error_noreturn(E_COMPILE_ERROR, "Interface %s cannot extend class %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name)); } - } else if (UNEXPECTED(parent_ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_FINAL))) { + } else if (UNEXPECTED(parent_ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_FINAL|ZEND_ACC_ENUM))) { + /* Class must not extend an enum (GH-16315); check enums first since + * enums are implemented as final classes */ + if (parent_ce->ce_flags & ZEND_ACC_ENUM) { + zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend enum %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name)); + } /* Class must not extend a final class */ if (parent_ce->ce_flags & ZEND_ACC_FINAL) { zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend final class %s", ZSTR_VAL(ce->name), ZSTR_VAL(parent_ce->name));