Skip to content

Commit e5c6456

Browse files
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.
1 parent f4b27bd commit e5c6456

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ PHP NEWS
88
(ilutov)
99
. Fixed bug GH-20194 (null offset deprecation not emitted for writes).
1010
(Girgias)
11+
. Fixed bug GH-GH-20377 (final promoted properties without explicit visibility
12+
not automatically assigned). (DanielEScherzer)
1113

1214
- Opcache:
1315
. Fixed bug GH-20012 (heap buffer overflow in jit). (Arnaud)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-20377: Constructor promotion with a final property without visibility set
3+
--FILE--
4+
<?php
5+
6+
class Demo {
7+
public function __construct(
8+
final string $foo,
9+
final public string $bar,
10+
) {}
11+
}
12+
13+
$d = new Demo("first", "second");
14+
var_dump($d);
15+
16+
?>
17+
--EXPECTF--
18+
object(Demo)#%d (2) {
19+
["foo"]=>
20+
string(5) "first"
21+
["bar"]=>
22+
string(6) "second"
23+
}

Zend/zend_compile.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7770,6 +7770,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
77707770
}
77717771
}
77727772

7773+
const uint32_t promotion_flags = ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL;
77737774
for (i = 0; i < list->children; ++i) {
77747775
zend_ast *param_ast = list->child[i];
77757776
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
77817782
zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast));
77827783
bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
77837784
bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
7784-
uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY | ZEND_ACC_FINAL);
7785+
uint32_t property_flags = param_ast->attr & promotion_flags;
77857786
bool is_promoted = property_flags || hooks_ast;
77867787

77877788
CG(zend_lineno) = param_ast->lineno;
@@ -8008,7 +8009,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
80088009
zend_ast *param_ast = list->child[i];
80098010
zend_ast *hooks_ast = param_ast->child[5];
80108011
bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
8011-
uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_PPP_SET_MASK | ZEND_ACC_READONLY);
8012+
uint32_t flags = param_ast->attr & promotion_flags;
80128013
bool is_promoted = flags || hooks_ast;
80138014
if (!is_promoted) {
80148015
continue;

0 commit comments

Comments
 (0)