diff --git a/Zend/tests/property_hooks/default_value_inheritance.phpt b/Zend/tests/property_hooks/default_value_inheritance.phpt new file mode 100644 index 00000000000..3821e19634e --- /dev/null +++ b/Zend/tests/property_hooks/default_value_inheritance.phpt @@ -0,0 +1,54 @@ +--TEST-- +Property default values are not inherited +--FILE-- + parent::$a::get(); } + public int $b { get => parent::$b::get(); } + public $c = 2 { get => parent::$c::get(); } + public int $d = 2 { get => parent::$d::get(); } +} + +class GC extends C { + public $a { get => parent::$a::get(); } + public int $b { get => parent::$b::get(); } + public $c { get => parent::$c::get(); } + public int $d { get => parent::$d::get(); } +} + +function test(P $p) { + var_dump($p->a); + try { + var_dump($p->b); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } + var_dump($p->c); + try { + var_dump($p->d); + } catch (Error $e) { + echo $e->getMessage(), "\n"; + } +} + +test(new C); +test(new GC); + +?> +--EXPECT-- +NULL +Typed property C::$b must not be accessed before initialization +int(2) +int(2) +NULL +Typed property GC::$b must not be accessed before initialization +NULL +Typed property GC::$d must not be accessed before initialization diff --git a/Zend/tests/property_hooks/dump.phpt b/Zend/tests/property_hooks/dump.phpt index d7cd57183d6..84db6cb3175 100644 --- a/Zend/tests/property_hooks/dump.phpt +++ b/Zend/tests/property_hooks/dump.phpt @@ -34,7 +34,7 @@ class Test { } class Child extends Test { - public $addedHooks { + public $addedHooks = 'addedHooks' { get { return strtoupper(parent::$addedHooks::get()); } } private $changed = 'changed Child' { diff --git a/Zend/tests/property_hooks/generator_hook_002.phpt b/Zend/tests/property_hooks/generator_hook_002.phpt index 0eeb99c8cf9..5945720c340 100644 --- a/Zend/tests/property_hooks/generator_hook_002.phpt +++ b/Zend/tests/property_hooks/generator_hook_002.phpt @@ -8,7 +8,7 @@ class A { } class B extends A { - public $prop { + public $prop = 42 { get { yield parent::$prop::get() + 1; yield parent::$prop::get() + 2; diff --git a/Zend/tests/property_hooks/parent_get_plain.phpt b/Zend/tests/property_hooks/parent_get_plain.phpt index f461b39a8a3..c3dc72d51fe 100644 --- a/Zend/tests/property_hooks/parent_get_plain.phpt +++ b/Zend/tests/property_hooks/parent_get_plain.phpt @@ -8,7 +8,7 @@ class P { } class C extends P { - public $prop { + public $prop = 42 { get => parent::$prop::get(); } } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index d08dd9191be..883e82d099f 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1490,14 +1490,21 @@ static void do_inherit_property(zend_property_info *parent_info, zend_string *ke zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ZSTR_VAL(ce->name), ZSTR_VAL(key), zend_visibility_string(parent_info->flags), ZSTR_VAL(parent_info->ce->name), (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); } if (!(child_info->flags & ZEND_ACC_STATIC) && !(parent_info->flags & ZEND_ACC_VIRTUAL)) { + int parent_num = OBJ_PROP_TO_NUM(parent_info->offset); if (child_info->offset != ZEND_VIRTUAL_PROPERTY_OFFSET) { - int parent_num = OBJ_PROP_TO_NUM(parent_info->offset); int child_num = OBJ_PROP_TO_NUM(child_info->offset); /* Don't keep default properties in GC (they may be freed by opcache) */ zval_ptr_dtor_nogc(&(ce->default_properties_table[parent_num])); ce->default_properties_table[parent_num] = ce->default_properties_table[child_num]; ZVAL_UNDEF(&ce->default_properties_table[child_num]); + } else { + /* Default value was removed in child, remove it from parent too. */ + if (ZEND_TYPE_IS_SET(child_info->type)) { + ZVAL_UNDEF(&ce->default_properties_table[parent_num]); + } else { + ZVAL_NULL(&ce->default_properties_table[parent_num]); + } } child_info->offset = parent_info->offset;