diff --git a/NEWS b/NEWS index 8652023266a36..382d23f1f4e97 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ PHP NEWS (ilutov) . Fixed bug GH-20194 (null offset deprecation not emitted for writes). (Girgias) + . Fixed bug GH-GH-20377 (final promoted properties without explicit visibility + not automatically assigned). (DanielEScherzer) - Opcache: . Fixed bug GH-20012 (heap buffer overflow in jit). (Arnaud) diff --git a/Zend/tests/ctor_promotion/ctor_promotion_final.phpt b/Zend/tests/ctor_promotion/ctor_promotion_final.phpt new file mode 100644 index 0000000000000..abfb5b7088082 --- /dev/null +++ b/Zend/tests/ctor_promotion/ctor_promotion_final.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-20377: Constructor promotion with a final property without visibility set +--FILE-- + +--EXPECTF-- +object(Demo)#%d (2) { + ["foo"]=> + string(5) "first" + ["bar"]=> + string(6) "second" +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0180e6e8e1c0a..8be1ee14f4859 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7770,6 +7770,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 } } + const uint32_t promotion_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL; for (i = 0; i < list->children; ++i) { zend_ast *param_ast = list->child[i]; zend_ast *type_ast = param_ast->child[0]; @@ -7781,7 +7782,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast)); bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0; bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0; - uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL); + uint32_t property_flags = param_ast->attr & promotion_flags; bool is_promoted = property_flags || hooks_ast; CG(zend_lineno) = param_ast->lineno; @@ -8008,7 +8009,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 zend_ast *param_ast = list->child[i]; zend_ast *hooks_ast = param_ast->child[5]; bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0; - uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY); + uint32_t flags = param_ast->attr & promotion_flags; bool is_promoted = flags || hooks_ast; if (!is_promoted) { continue;