diff --git a/Zend/tests/enum/backed-duplicate-int.phpt b/Zend/tests/enum/backed-duplicate-int.phpt index 4da70bc3ddbc4..fb64ff29322ea 100644 --- a/Zend/tests/enum/backed-duplicate-int.phpt +++ b/Zend/tests/enum/backed-duplicate-int.phpt @@ -8,6 +8,33 @@ enum Foo: int { case Baz = 0; } +try { + var_dump(Foo::Bar); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::Bar); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::from(42)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::tryFrom('bar')); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + ?> ---EXPECTF-- -Fatal error: Duplicate value in enum Foo for cases Bar and Baz in %s on line %s +--EXPECT-- +Duplicate value in enum Foo for cases Bar and Baz +Duplicate value in enum Foo for cases Bar and Baz +Duplicate value in enum Foo for cases Bar and Baz +Foo::tryFrom(): Argument #1 ($value) must be of type int, string given diff --git a/Zend/tests/enum/backed-duplicate-string.phpt b/Zend/tests/enum/backed-duplicate-string.phpt index 7d42c2ac30062..22224ada35a36 100644 --- a/Zend/tests/enum/backed-duplicate-string.phpt +++ b/Zend/tests/enum/backed-duplicate-string.phpt @@ -10,6 +10,33 @@ enum Suit: string { case Spades = 'H'; } +try { + var_dump(Suit::Hearts); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Suit::Hearts); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Suit::from(42)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Suit::tryFrom('bar')); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + ?> ---EXPECTF-- -Fatal error: Duplicate value in enum Suit for cases Hearts and Spades in %s on line %s +--EXPECT-- +Duplicate value in enum Suit for cases Hearts and Spades +Duplicate value in enum Suit for cases Hearts and Spades +Duplicate value in enum Suit for cases Hearts and Spades +Duplicate value in enum Suit for cases Hearts and Spades diff --git a/Zend/tests/enum/backed-int-const-invalid-expr.phpt b/Zend/tests/enum/backed-int-const-invalid-expr.phpt index f0c421a3671ab..77d9995c2d89e 100644 --- a/Zend/tests/enum/backed-int-const-invalid-expr.phpt +++ b/Zend/tests/enum/backed-int-const-invalid-expr.phpt @@ -11,4 +11,4 @@ var_dump(Foo::Bar->value); ?> --EXPECTF-- -Fatal error: Enum case value must be compile-time evaluatable in %s on line %d +Fatal error: Constant expression contains invalid operations in %s on line %d diff --git a/Zend/tests/enum/backed-mismatch.phpt b/Zend/tests/enum/backed-mismatch.phpt index 0b28fb3be5ea9..73602f7b15b48 100644 --- a/Zend/tests/enum/backed-mismatch.phpt +++ b/Zend/tests/enum/backed-mismatch.phpt @@ -7,6 +7,33 @@ enum Foo: int { case Bar = 'bar'; } +try { + var_dump(Foo::Bar); +} catch (Error $e) { + echo get_class($e), ': ', $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::Bar); +} catch (Error $e) { + echo get_class($e), ': ', $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::from(42)); +} catch (Error $e) { + echo get_class($e), ': ', $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::from('bar')); +} catch (Error $e) { + echo get_class($e), ': ', $e->getMessage(), "\n"; +} + ?> ---EXPECTF-- -Fatal error: Enum case type string does not match enum backing type int in %s on line %d +--EXPECT-- +TypeError: Enum case type string does not match enum backing type int +TypeError: Enum case type string does not match enum backing type int +TypeError: Enum case type string does not match enum backing type int +TypeError: Foo::from(): Argument #1 ($value) must be of type int, string given diff --git a/Zend/tests/enum/gh7821.phpt b/Zend/tests/enum/gh7821.phpt new file mode 100644 index 0000000000000..70307c96d982f --- /dev/null +++ b/Zend/tests/enum/gh7821.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-7821: Can't use arbitrary constant expressions in enum cases +--FILE-- +value); +var_dump(B::D->value); + +?> +--EXPECT-- +string(1) "A" +string(1) "B" +string(1) "A" +string(1) "B" diff --git a/Zend/tests/enum/gh8418.phpt b/Zend/tests/enum/gh8418.phpt new file mode 100644 index 0000000000000..97901fa4d68bf --- /dev/null +++ b/Zend/tests/enum/gh8418.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-8418: Enum constant expression evaluation doesn't work with warmed cache +--FILE-- +value); + +?> +--EXPECT-- +int(42) diff --git a/Zend/tests/enum/non-backed-enum-with-expr-value.phpt b/Zend/tests/enum/non-backed-enum-with-expr-value.phpt index 95bd85f39625b..8bd1d1f7854e3 100644 --- a/Zend/tests/enum/non-backed-enum-with-expr-value.phpt +++ b/Zend/tests/enum/non-backed-enum-with-expr-value.phpt @@ -9,4 +9,4 @@ enum Foo { ?> --EXPECTF-- -Fatal error: Case Bar of non-backed enum Foo must not have a value, try adding ": int" to the enum declaration in %s on line %d +Fatal error: Case Bar of non-backed enum Foo must not have a value in %s on line %d diff --git a/Zend/tests/enum/non-backed-enum-with-int-value.phpt b/Zend/tests/enum/non-backed-enum-with-int-value.phpt index 4932e63d180b9..9b4384c3f9a7b 100644 --- a/Zend/tests/enum/non-backed-enum-with-int-value.phpt +++ b/Zend/tests/enum/non-backed-enum-with-int-value.phpt @@ -9,4 +9,4 @@ enum Foo { ?> --EXPECTF-- -Fatal error: Case Bar of non-backed enum Foo must not have a value, try adding ": int" to the enum declaration in %s on line %d +Fatal error: Case Bar of non-backed enum Foo must not have a value in %s on line %d diff --git a/Zend/tests/enum/non-backed-enum-with-string-value.phpt b/Zend/tests/enum/non-backed-enum-with-string-value.phpt index f1a06e1a17a9c..6151ccd5fd4b0 100644 --- a/Zend/tests/enum/non-backed-enum-with-string-value.phpt +++ b/Zend/tests/enum/non-backed-enum-with-string-value.phpt @@ -9,4 +9,4 @@ enum Foo { ?> --EXPECTF-- -Fatal error: Case Bar of non-backed enum Foo must not have a value, try adding ": string" to the enum declaration in %s on line %d +Fatal error: Case Bar of non-backed enum Foo must not have a value in %s on line %d diff --git a/Zend/tests/enum/update-class-constant-failure.phpt b/Zend/tests/enum/update-class-constant-failure.phpt new file mode 100644 index 0000000000000..8ea1ffda684ac --- /dev/null +++ b/Zend/tests/enum/update-class-constant-failure.phpt @@ -0,0 +1,17 @@ +--TEST-- +Test failure of updating class constants +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "NONEXISTENT" in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 464364d697b60..220b76efca6ff 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -30,6 +30,7 @@ #include "zend_closures.h" #include "zend_inheritance.h" #include "zend_ini.h" +#include "zend_enum.h" #include @@ -1493,6 +1494,12 @@ ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) / } } + if (class_type->type == ZEND_USER_CLASS && class_type->ce_flags & ZEND_ACC_ENUM && class_type->enum_backing_type != IS_UNDEF) { + if (zend_enum_build_backed_enum_table(class_type) == FAILURE) { + return FAILURE; + } + } + ce_flags |= ZEND_ACC_CONSTANTS_UPDATED; ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS; ce_flags &= ~ZEND_ACC_HAS_AST_PROPERTIES; diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index e996a3f26ab2c..2c23421f9f3ef 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -776,12 +776,18 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast zend_string *case_name = zend_ast_get_str(case_name_ast); zend_ast *case_value_ast = ast->child[2]; - zval *case_value_zv = case_value_ast != NULL - ? zend_ast_get_zval(case_value_ast) - : NULL; + + zval case_value_zv; + ZVAL_UNDEF(&case_value_zv); + if (case_value_ast != NULL) { + if (UNEXPECTED(zend_ast_evaluate(&case_value_zv, case_value_ast, scope) != SUCCESS)) { + return FAILURE; + } + } zend_class_entry *ce = zend_lookup_class(class_name); - zend_enum_new(result, ce, case_name, case_value_zv); + zend_enum_new(result, ce, case_name, case_value_ast != NULL ? &case_value_zv : NULL); + zval_ptr_dtor_nogc(&case_value_zv); break; } case ZEND_AST_CLASS_CONST: diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0ec50dc58922c..bf98796c1eb47 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7575,9 +7575,6 @@ static void zend_compile_enum_backing_type(zend_class_entry *ce, zend_ast *enum_ ce->enum_backing_type = IS_STRING; } zend_type_release(type, 0); - - ce->backed_enum_table = emalloc(sizeof(HashTable)); - zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0); } static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */ @@ -7789,69 +7786,20 @@ static void zend_compile_enum_case(zend_ast *ast) ZVAL_STR_COPY(&case_name_zval, enum_case_name); zend_ast *case_name_ast = zend_ast_create_zval(&case_name_zval); - zend_ast *case_value_zval_ast = NULL; zend_ast *case_value_ast = ast->child[1]; + // Remove case_value_ast from the original AST to avoid freeing it, as it will be freed by zend_const_expr_to_zval + ast->child[1] = NULL; if (enum_class->enum_backing_type != IS_UNDEF && case_value_ast == NULL) { zend_error_noreturn(E_COMPILE_ERROR, "Case %s of backed enum %s must have a value", ZSTR_VAL(enum_case_name), ZSTR_VAL(enum_class_name)); - } - if (case_value_ast != NULL) { - zend_eval_const_expr(&ast->child[1]); - case_value_ast = ast->child[1]; - if (case_value_ast->kind != ZEND_AST_ZVAL) { - zend_error_noreturn( - E_COMPILE_ERROR, "Enum case value must be compile-time evaluatable"); - } - - zval case_value_zv; - ZVAL_COPY(&case_value_zv, zend_ast_get_zval(case_value_ast)); - if (enum_class->enum_backing_type == IS_UNDEF) { - if (Z_TYPE(case_value_zv) == IS_LONG || Z_TYPE(case_value_zv) == IS_STRING) { - zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value, try adding \": %s\" to the enum declaration", - ZSTR_VAL(enum_case_name), - ZSTR_VAL(enum_class_name), - zend_zval_type_name(&case_value_zv)); - } else { - zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value", - ZSTR_VAL(enum_case_name), - ZSTR_VAL(enum_class_name)); - } - } - - if (enum_class->enum_backing_type != Z_TYPE(case_value_zv)) { - zend_error_noreturn(E_COMPILE_ERROR, "Enum case type %s does not match enum backing type %s", - zend_get_type_by_const(Z_TYPE(case_value_zv)), - zend_get_type_by_const(enum_class->enum_backing_type)); - } - - case_value_zval_ast = zend_ast_create_zval(&case_value_zv); - Z_TRY_ADDREF(case_name_zval); - if (enum_class->enum_backing_type == IS_LONG) { - zend_long long_key = Z_LVAL(case_value_zv); - zval *existing_case_name = zend_hash_index_find(enum_class->backed_enum_table, long_key); - if (existing_case_name) { - zend_error_noreturn(E_COMPILE_ERROR, "Duplicate value in enum %s for cases %s and %s", - ZSTR_VAL(enum_class_name), - Z_STRVAL_P(existing_case_name), - ZSTR_VAL(enum_case_name)); - } - zend_hash_index_add_new(enum_class->backed_enum_table, long_key, &case_name_zval); - } else { - ZEND_ASSERT(enum_class->enum_backing_type == IS_STRING); - zend_string *string_key = Z_STR(case_value_zv); - zval *existing_case_name = zend_hash_find(enum_class->backed_enum_table, string_key); - if (existing_case_name != NULL) { - zend_error_noreturn(E_COMPILE_ERROR, "Duplicate value in enum %s for cases %s and %s", - ZSTR_VAL(enum_class_name), - Z_STRVAL_P(existing_case_name), - ZSTR_VAL(enum_case_name)); - } - zend_hash_add_new(enum_class->backed_enum_table, string_key, &case_name_zval); - } + } else if (enum_class->enum_backing_type == IS_UNDEF && case_value_ast != NULL) { + zend_error_noreturn(E_COMPILE_ERROR, "Case %s of non-backed enum %s must not have a value", + ZSTR_VAL(enum_case_name), + ZSTR_VAL(enum_class_name)); } - zend_ast *const_enum_init_ast = zend_ast_create(ZEND_AST_CONST_ENUM_INIT, class_name_ast, case_name_ast, case_value_zval_ast); + zend_ast *const_enum_init_ast = zend_ast_create(ZEND_AST_CONST_ENUM_INIT, class_name_ast, case_name_ast, case_value_ast); zval value_zv; zend_const_expr_to_zval(&value_zv, &const_enum_init_ast, /* allow_dynamic */ false); diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 70ac2742ca7ae..a4a450d22fba6 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -21,6 +21,7 @@ #include "zend_compile.h" #include "zend_enum_arginfo.h" #include "zend_interfaces.h" +#include "zend_enum.h" #define ZEND_ENUM_DISALLOW_MAGIC_METHOD(propertyName, methodName) \ do { \ @@ -183,6 +184,72 @@ void zend_enum_add_interfaces(zend_class_entry *ce) } } +zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) +{ + ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM); + ZEND_ASSERT(ce->type == ZEND_USER_CLASS); + + uint32_t backing_type = ce->enum_backing_type; + ZEND_ASSERT(backing_type != IS_UNDEF); + + ce->backed_enum_table = emalloc(sizeof(HashTable)); + zend_hash_init(ce->backed_enum_table, 0, NULL, ZVAL_PTR_DTOR, 0); + + zend_string *enum_class_name = ce->name; + + zend_string *name; + zval *val; + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&ce->constants_table, name, val) { + zend_class_constant *c = Z_PTR_P(val); + if ((ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) == 0) { + continue; + } + + zval *c_value = &c->value; + zval *case_name = zend_enum_fetch_case_name(Z_OBJ_P(c_value)); + zval *case_value = zend_enum_fetch_case_value(Z_OBJ_P(c_value)); + + if (ce->enum_backing_type != Z_TYPE_P(case_value)) { + zend_type_error("Enum case type %s does not match enum backing type %s", + zend_get_type_by_const(Z_TYPE_P(case_value)), + zend_get_type_by_const(ce->enum_backing_type)); + goto failure; + } + + if (ce->enum_backing_type == IS_LONG) { + zend_long long_key = Z_LVAL_P(case_value); + zval *existing_case_name = zend_hash_index_find(ce->backed_enum_table, long_key); + if (existing_case_name) { + zend_throw_error(NULL, "Duplicate value in enum %s for cases %s and %s", + ZSTR_VAL(enum_class_name), + Z_STRVAL_P(existing_case_name), + ZSTR_VAL(name)); + goto failure; + } + zend_hash_index_add_new(ce->backed_enum_table, long_key, case_name); + } else { + ZEND_ASSERT(ce->enum_backing_type == IS_STRING); + zend_string *string_key = Z_STR_P(case_value); + zval *existing_case_name = zend_hash_find(ce->backed_enum_table, string_key); + if (existing_case_name != NULL) { + zend_throw_error(NULL, "Duplicate value in enum %s for cases %s and %s", + ZSTR_VAL(enum_class_name), + Z_STRVAL_P(existing_case_name), + ZSTR_VAL(name)); + goto failure; + } + zend_hash_add_new(ce->backed_enum_table, string_key, case_name); + } + } ZEND_HASH_FOREACH_END(); + + return SUCCESS; + +failure: + zend_hash_release(ce->backed_enum_table); + ce->backed_enum_table = NULL; + return FAILURE; +} + static ZEND_NAMED_FUNCTION(zend_enum_cases_func) { zend_class_entry *ce = execute_data->func->common.scope; @@ -209,6 +276,12 @@ static ZEND_NAMED_FUNCTION(zend_enum_cases_func) ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_class_entry *ce, zend_long long_key, zend_string *string_key, bool try) { + if (ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (zend_update_class_constants(ce) == FAILURE) { + return FAILURE; + } + } + zval *case_name_zv; if (ce->enum_backing_type == IS_LONG) { case_name_zv = zend_hash_index_find(ce->backed_enum_table, long_key); diff --git a/Zend/zend_enum.h b/Zend/zend_enum.h index e9cda0fd580f5..797eb0c8ab5b6 100644 --- a/Zend/zend_enum.h +++ b/Zend/zend_enum.h @@ -29,6 +29,7 @@ extern ZEND_API zend_class_entry *zend_ce_backed_enum; void zend_register_enum_ce(void); void zend_enum_add_interfaces(zend_class_entry *ce); +zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce); zend_object *zend_enum_new(zval *result, zend_class_entry *ce, zend_string *case_name, zval *backing_value_zv); void zend_verify_enum(zend_class_entry *ce); void zend_enum_register_funcs(zend_class_entry *ce); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 6c8e7f020f287..86cf4c6f9f118 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -330,9 +330,6 @@ ZEND_API void destroy_zend_class(zval *zv) if (ce->attributes) { zend_hash_release(ce->attributes); } - if (ce->backed_enum_table) { - zend_hash_release(ce->backed_enum_table); - } if (ce->num_interfaces > 0 && !(ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) { uint32_t i; @@ -403,6 +400,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (ce->num_interfaces > 0 && (ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) { efree(ce->interfaces); } + if (ce->backed_enum_table) { + zend_hash_release(ce->backed_enum_table); + } break; case ZEND_INTERNAL_CLASS: if (ce->backed_enum_table) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0dc7f4d5f4d90..7197e2aa54cef 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5896,6 +5896,13 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO HANDLE_EXCEPTION(); } value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 87480a0c8ec16..e86c20120a147 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7065,6 +7065,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS HANDLE_EXCEPTION(); } value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { @@ -24610,6 +24617,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_ HANDLE_EXCEPTION(); } value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { @@ -33448,6 +33462,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS HANDLE_EXCEPTION(); } value = &c->value; + // Enums require loading of all class constants to build the backed enum table + if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) { + if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + HANDLE_EXCEPTION(); + } + } if (Z_TYPE_P(value) == IS_CONSTANT_AST) { zval_update_constant_ex(value, c->ce); if (UNEXPECTED(EG(exception) != NULL)) { diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index e3300d1ebb381..badbac2185535 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -848,14 +848,6 @@ static void zend_file_cache_serialize_class(zval *zv, } } - if (ce->backed_enum_table) { - HashTable *ht; - SERIALIZE_PTR(ce->backed_enum_table); - ht = ce->backed_enum_table; - UNSERIALIZE_PTR(ht); - zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); - } - SERIALIZE_PTR(ce->constructor); SERIALIZE_PTR(ce->destructor); SERIALIZE_PTR(ce->clone); @@ -1645,12 +1637,6 @@ static void zend_file_cache_unserialize_class(zval *zv, } } - if (ce->backed_enum_table) { - UNSERIALIZE_PTR(ce->backed_enum_table); - zend_file_cache_unserialize_hash( - ce->backed_enum_table, script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); - } - UNSERIALIZE_PTR(ce->constructor); UNSERIALIZE_PTR(ce->destructor); UNSERIALIZE_PTR(ce->clone); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 82dd4ccf434aa..cc0572f011edc 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -336,35 +336,6 @@ uint32_t zend_accel_get_class_name_map_ptr(zend_string *type_name) return 0; } -static HashTable *zend_persist_backed_enum_table(HashTable *backed_enum_table) -{ - HashTable *ptr; - zend_hash_persist(backed_enum_table); - - if (HT_IS_PACKED(backed_enum_table)) { - zval *zv; - - ZEND_HASH_PACKED_FOREACH_VAL(backed_enum_table, zv) { - zend_persist_zval(zv); - } ZEND_HASH_FOREACH_END(); - } else { - Bucket *p; - - ZEND_HASH_MAP_FOREACH_BUCKET(backed_enum_table, p) { - if (p->key != NULL) { - zend_accel_store_interned_string(p->key); - } - zend_persist_zval(&p->val); - } ZEND_HASH_FOREACH_END(); - } - - ptr = zend_shared_memdup_free(backed_enum_table, sizeof(HashTable)); - GC_SET_REFCOUNT(ptr, 2); - GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT); - - return ptr; -} - static void zend_persist_type(zend_type *type) { if (ZEND_TYPE_HAS_LIST(*type)) { zend_type_list *list = ZEND_TYPE_LIST(*type); @@ -1072,9 +1043,7 @@ zend_class_entry *zend_persist_class_entry(zend_class_entry *orig_ce) } } - if (ce->backed_enum_table) { - ce->backed_enum_table = zend_persist_backed_enum_table(ce->backed_enum_table); - } + ZEND_ASSERT(ce->backed_enum_table == NULL); } return ce; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index b79158e7294af..c2aa9800f9f89 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -547,27 +547,6 @@ void zend_persist_class_entry_calc(zend_class_entry *ce) ADD_SIZE(sizeof(zend_trait_precedence*) * (i + 1)); } } - - if (ce->backed_enum_table) { - ADD_SIZE(sizeof(HashTable)); - zend_hash_persist_calc(ce->backed_enum_table); - if (HT_IS_PACKED(ce->backed_enum_table)) { - zval *zv; - - ZEND_HASH_PACKED_FOREACH_VAL(ce->backed_enum_table, zv) { - zend_persist_zval_calc(zv); - } ZEND_HASH_FOREACH_END(); - } else { - Bucket *p; - - ZEND_HASH_MAP_FOREACH_BUCKET(ce->backed_enum_table, p) { - if (p->key != NULL) { - ADD_INTERNED_STRING(p->key); - } - zend_persist_zval_calc(&p->val); - } ZEND_HASH_FOREACH_END(); - } - } } } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 5c9bcc731b475..11c78c43308f1 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1485,7 +1485,7 @@ static void reflection_enum_case_factory(zend_class_entry *ce, zend_string *name { reflection_object *intern; - zend_class_entry *case_reflection_class = ce->backed_enum_table == IS_UNDEF + zend_class_entry *case_reflection_class = ce->enum_backing_type == IS_UNDEF ? reflection_enum_unit_case_ptr : reflection_enum_backed_case_ptr; reflection_instantiate(case_reflection_class, object);