@@ -1284,18 +1284,26 @@ static void emit_incompatible_property_error(
1284
1284
ZSTR_VAL (parent -> ce -> name ));
1285
1285
}
1286
1286
1287
+ static bool property_has_operation (zend_property_info * prop_info , zend_property_hook_kind kind )
1288
+ {
1289
+ return (!(prop_info -> flags & ZEND_ACC_VIRTUAL )
1290
+ && (kind == ZEND_PROPERTY_HOOK_GET || !(prop_info -> flags & ZEND_ACC_READONLY )))
1291
+ || (prop_info -> hooks && prop_info -> hooks [kind ]);
1292
+ }
1293
+
1287
1294
static void inherit_property_hook (
1288
1295
zend_class_entry * ce ,
1289
- zend_property_info * parent_info , zend_function * * parent_ptr ,
1290
- zend_property_info * child_info , zend_function * * child_ptr
1296
+ zend_property_info * parent_info ,
1297
+ zend_property_info * child_info ,
1298
+ zend_property_hook_kind kind
1291
1299
) {
1292
- zend_function * parent = * parent_ptr ;
1293
- zend_function * child = * child_ptr ;
1300
+ zend_function * parent = parent_info -> hooks ? parent_info -> hooks [ kind ] : NULL ;
1301
+ zend_function * child = child_info -> hooks ? child_info -> hooks [ kind ] : NULL ;
1294
1302
1295
- if (child && ( child -> common . fn_flags & ZEND_ACC_OVERRIDE )) {
1296
- if (!( parent_info -> flags & ZEND_ACC_VIRTUAL ) || parent ) {
1297
- child -> common . fn_flags &= ~ ZEND_ACC_OVERRIDE ;
1298
- }
1303
+ if (child
1304
+ && ( child -> common . fn_flags & ZEND_ACC_OVERRIDE )
1305
+ && property_has_operation ( parent_info , kind )) {
1306
+ child -> common . fn_flags &= ~ ZEND_ACC_OVERRIDE ;
1299
1307
}
1300
1308
1301
1309
if (!parent ) {
@@ -1304,10 +1312,18 @@ static void inherit_property_hook(
1304
1312
1305
1313
if (!child ) {
1306
1314
if (parent -> common .fn_flags & ZEND_ACC_ABSTRACT ) {
1315
+ /* Backed properties are considered to always implement get, and set when they are not readonly. */
1316
+ if (property_has_operation (child_info , kind )) {
1317
+ return ;
1318
+ }
1307
1319
ce -> ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS ;
1308
1320
}
1309
-
1310
- * child_ptr = zend_duplicate_function (parent , ce );
1321
+ if (!child_info -> hooks ) {
1322
+ ce -> num_hooked_props ++ ;
1323
+ child_info -> hooks = zend_arena_alloc (& CG (arena ), ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1324
+ memset (child_info -> hooks , 0 , ZEND_PROPERTY_HOOK_STRUCT_SIZE );
1325
+ }
1326
+ child_info -> hooks [kind ] = zend_duplicate_function (parent , ce );
1311
1327
return ;
1312
1328
}
1313
1329
@@ -1375,17 +1391,7 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
1375
1391
(child_info -> flags & ZEND_ACC_STATIC ) ? "static " : "non static " , ZSTR_VAL (ce -> name ), ZSTR_VAL (key ));
1376
1392
}
1377
1393
if (UNEXPECTED ((child_info -> flags & ZEND_ACC_READONLY ) != (parent_info -> flags & ZEND_ACC_READONLY ))) {
1378
- /* If the parent property is abstract, the child may be readonly if the parent only requires read. */
1379
- if (parent_info -> flags & ZEND_ACC_ABSTRACT ) {
1380
- ZEND_ASSERT (!(parent_info -> flags & ZEND_ACC_READONLY ));
1381
- ZEND_ASSERT (parent_info -> hooks );
1382
- if (UNEXPECTED (parent_info -> hooks [ZEND_PROPERTY_HOOK_SET ])) {
1383
- zend_error_noreturn (E_COMPILE_ERROR ,
1384
- "Readonly property %s::$%s does not satisfy abstract read-write property %s::$%s" ,
1385
- ZSTR_VAL (ce -> name ), ZSTR_VAL (key ),
1386
- ZSTR_VAL (parent_info -> ce -> name ), ZSTR_VAL (key ));
1387
- }
1388
- } else {
1394
+ if (!(parent_info -> flags & ZEND_ACC_ABSTRACT )) {
1389
1395
zend_error_noreturn (E_COMPILE_ERROR ,
1390
1396
"Cannot redeclare %s property %s::$%s as %s %s::$%s" ,
1391
1397
parent_info -> flags & ZEND_ACC_READONLY ? "readonly" : "non-readonly" ,
@@ -1413,18 +1419,10 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke
1413
1419
child_info -> flags &= ~ZEND_ACC_VIRTUAL ;
1414
1420
}
1415
1421
1416
- zend_function * * parent_hooks = parent_info -> hooks ;
1417
- zend_function * * child_hooks = child_info -> hooks ;
1418
- if (child_hooks ) {
1422
+ if (parent_info -> hooks || child_info -> hooks ) {
1419
1423
for (uint32_t i = 0 ; i < ZEND_PROPERTY_HOOK_COUNT ; i ++ ) {
1420
- if (parent_hooks ) {
1421
- inherit_property_hook (ce , parent_info , & parent_hooks [i ], child_info , & child_hooks [i ]);
1422
- } else if (child_hooks [i ]) {
1423
- child_hooks [i ]-> common .fn_flags &= ~ZEND_ACC_OVERRIDE ;
1424
- }
1424
+ inherit_property_hook (ce , parent_info , child_info , i );
1425
1425
}
1426
- } else if (parent_hooks ) {
1427
- ce -> num_hooked_props ++ ;
1428
1426
}
1429
1427
1430
1428
prop_variance variance = prop_get_variance (parent_info );
0 commit comments