1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-20377: emit assignment for all final promoted properties (#20378)

Previously, the assignment op line was only emitted when one of the other flags
allowed for promoted properties (visibility, set visibility, or readonly) was
also used, or when the property had hooks. The property was still added to the
class, but the magical assignment `$this->prop = $prop` was missing. Add that
assignment even when no visibility is explicitly specified, and a test to
confirm the fix.
This commit is contained in:
Daniel Scherzer
2025-11-03 14:36:57 -08:00
committed by GitHub
parent f4b27bdc0d
commit e5c6456d37
3 changed files with 28 additions and 2 deletions

2
NEWS
View File

@@ -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)

View File

@@ -0,0 +1,23 @@
--TEST--
GH-20377: Constructor promotion with a final property without visibility set
--FILE--
<?php
class Demo {
public function __construct(
final string $foo,
final public string $bar,
) {}
}
$d = new Demo("first", "second");
var_dump($d);
?>
--EXPECTF--
object(Demo)#%d (2) {
["foo"]=>
string(5) "first"
["bar"]=>
string(6) "second"
}

View File

@@ -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;