@@ -1081,12 +1081,13 @@ static void perform_delayable_implementation_check(
1081
1081
/**
1082
1082
* @param check_only Set to false to throw compile errors on incompatible methods, or true to return INHERITANCE_ERROR.
1083
1083
* @param checked Whether the compatibility check has already succeeded in zend_can_early_bind().
1084
+ * @param force_mutable Whether we know that child may be modified, i.e. doesn't live in shm.
1084
1085
*/
1085
1086
static zend_always_inline inheritance_status do_inheritance_check_on_method_ex (
1086
1087
zend_function * child , zend_class_entry * child_scope ,
1087
1088
zend_function * parent , zend_class_entry * parent_scope ,
1088
1089
zend_class_entry * ce , zval * child_zv ,
1089
- bool check_visibility , bool check_only , bool checked ) /* {{{ */
1090
+ bool check_visibility , bool check_only , bool checked , bool force_mutable ) /* {{{ */
1090
1091
{
1091
1092
uint32_t child_flags ;
1092
1093
uint32_t parent_flags = parent -> common .fn_flags ;
@@ -1188,7 +1189,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
1188
1189
perform_delayable_implementation_check (ce , child , child_scope , parent , parent_scope );
1189
1190
}
1190
1191
1191
- if (!check_only && child -> common .scope == ce ) {
1192
+ if (!check_only && ( child -> common .scope == ce || force_mutable ) ) {
1192
1193
child -> common .fn_flags &= ~ZEND_ACC_OVERRIDE ;
1193
1194
}
1194
1195
@@ -1201,7 +1202,7 @@ static zend_never_inline void do_inheritance_check_on_method(
1201
1202
zend_function * parent , zend_class_entry * parent_scope ,
1202
1203
zend_class_entry * ce , zval * child_zv , bool check_visibility )
1203
1204
{
1204
- do_inheritance_check_on_method_ex (child , child_scope , parent , parent_scope , ce , child_zv , check_visibility , 0 , 0 );
1205
+ do_inheritance_check_on_method_ex (child , child_scope , parent , parent_scope , ce , child_zv , check_visibility , 0 , 0 , /* force_mutable */ false );
1205
1206
}
1206
1207
1207
1208
static zend_always_inline void do_inherit_method (zend_string * key , zend_function * parent , zend_class_entry * ce , bool is_interface , bool checked ) /* {{{ */
@@ -1219,7 +1220,7 @@ static zend_always_inline void do_inherit_method(zend_string *key, zend_function
1219
1220
if (checked ) {
1220
1221
do_inheritance_check_on_method_ex (
1221
1222
func , func -> common .scope , parent , parent -> common .scope , ce , child ,
1222
- /* check_visibility */ 1 , 0 , checked );
1223
+ /* check_visibility */ 1 , 0 , checked , /* force_mutable */ false );
1223
1224
} else {
1224
1225
do_inheritance_check_on_method (
1225
1226
func , func -> common .scope , parent , parent -> common .scope , ce , child ,
@@ -1946,6 +1947,7 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
1946
1947
{
1947
1948
zend_function * existing_fn = NULL ;
1948
1949
zend_function * new_fn ;
1950
+ bool check_inheritance = false;
1949
1951
1950
1952
if ((existing_fn = zend_hash_find_ptr (& ce -> function_table , key )) != NULL ) {
1951
1953
/* if it is the same function with the same visibility and has not been assigned a class scope yet, regardless
@@ -1980,11 +1982,7 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
1980
1982
ZSTR_VAL (ce -> name ), ZSTR_VAL (name ),
1981
1983
ZSTR_VAL (existing_fn -> common .scope -> name ), ZSTR_VAL (existing_fn -> common .function_name ));
1982
1984
} else {
1983
- /* Inherited members are overridden by members inserted by traits.
1984
- * Check whether the trait method fulfills the inheritance requirements. */
1985
- do_inheritance_check_on_method (
1986
- fn , fixup_trait_scope (fn , ce ), existing_fn , fixup_trait_scope (existing_fn , ce ),
1987
- ce , NULL , /* check_visibility */ 1 );
1985
+ check_inheritance = true;
1988
1986
}
1989
1987
}
1990
1988
@@ -2004,6 +2002,14 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
2004
2002
function_add_ref (new_fn );
2005
2003
fn = zend_hash_update_ptr (& ce -> function_table , key , new_fn );
2006
2004
zend_add_magic_method (ce , fn , key );
2005
+
2006
+ if (check_inheritance ) {
2007
+ /* Inherited members are overridden by members inserted by traits.
2008
+ * Check whether the trait method fulfills the inheritance requirements. */
2009
+ do_inheritance_check_on_method_ex (
2010
+ fn , fixup_trait_scope (fn , ce ), existing_fn , fixup_trait_scope (existing_fn , ce ),
2011
+ ce , NULL , /* check_visibility */ 1 , false, false, /* force_mutable */ true);
2012
+ }
2007
2013
}
2008
2014
/* }}} */
2009
2015
@@ -3239,7 +3245,7 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e
3239
3245
do_inheritance_check_on_method_ex (
3240
3246
child_func , child_func -> common .scope ,
3241
3247
parent_func , parent_func -> common .scope ,
3242
- ce , NULL , /* check_visibility */ 1 , 1 , 0 );
3248
+ ce , NULL , /* check_visibility */ 1 , 1 , 0 , /* force_mutable */ false );
3243
3249
if (UNEXPECTED (status == INHERITANCE_WARNING )) {
3244
3250
overall_status = INHERITANCE_WARNING ;
3245
3251
} else if (UNEXPECTED (status != INHERITANCE_SUCCESS )) {
0 commit comments