@@ -1081,12 +1081,13 @@ static void perform_delayable_implementation_check(
10811081/**
10821082 * @param check_only Set to false to throw compile errors on incompatible methods, or true to return INHERITANCE_ERROR.
10831083 * @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.
10841085 */
10851086static zend_always_inline inheritance_status do_inheritance_check_on_method_ex (
10861087 zend_function * child , zend_class_entry * child_scope ,
10871088 zend_function * parent , zend_class_entry * parent_scope ,
10881089 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 ) /* {{{ */
10901091{
10911092 uint32_t child_flags ;
10921093 uint32_t parent_flags = parent -> common .fn_flags ;
@@ -1188,7 +1189,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(
11881189 perform_delayable_implementation_check (ce , child , child_scope , parent , parent_scope );
11891190 }
11901191
1191- if (!check_only && child -> common .scope == ce ) {
1192+ if (!check_only && ( child -> common .scope == ce || force_mutable ) ) {
11921193 child -> common .fn_flags &= ~ZEND_ACC_OVERRIDE ;
11931194 }
11941195
@@ -1201,7 +1202,7 @@ static zend_never_inline void do_inheritance_check_on_method(
12011202 zend_function * parent , zend_class_entry * parent_scope ,
12021203 zend_class_entry * ce , zval * child_zv , bool check_visibility )
12031204{
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 );
12051206}
12061207
12071208static 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
12191220 if (checked ) {
12201221 do_inheritance_check_on_method_ex (
12211222 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 );
12231224 } else {
12241225 do_inheritance_check_on_method (
12251226 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_
19461947{
19471948 zend_function * existing_fn = NULL ;
19481949 zend_function * new_fn ;
1950+ bool check_inheritance = false;
19491951
19501952 if ((existing_fn = zend_hash_find_ptr (& ce -> function_table , key )) != NULL ) {
19511953 /* 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_
19801982 ZSTR_VAL (ce -> name ), ZSTR_VAL (name ),
19811983 ZSTR_VAL (existing_fn -> common .scope -> name ), ZSTR_VAL (existing_fn -> common .function_name ));
19821984 } 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;
19881986 }
19891987 }
19901988
@@ -2004,6 +2002,14 @@ static void zend_add_trait_method(zend_class_entry *ce, zend_string *name, zend_
20042002 function_add_ref (new_fn );
20052003 fn = zend_hash_update_ptr (& ce -> function_table , key , new_fn );
20062004 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+ }
20072013}
20082014/* }}} */
20092015
@@ -3239,7 +3245,7 @@ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_e
32393245 do_inheritance_check_on_method_ex (
32403246 child_func , child_func -> common .scope ,
32413247 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 );
32433249 if (UNEXPECTED (status == INHERITANCE_WARNING )) {
32443250 overall_status = INHERITANCE_WARNING ;
32453251 } else if (UNEXPECTED (status != INHERITANCE_SUCCESS )) {
0 commit comments