]> granicus.if.org Git - php/commitdiff
Fixed bug #79867
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 17 Jul 2020 13:09:29 +0000 (15:09 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 17 Jul 2020 13:10:45 +0000 (15:10 +0200)
In line with usual rules, give untyped properties a null default
value. Otherwise constructor promotion would give you a property
declaration that cannot be achieved through any other means.

NEWS
Zend/tests/ctor_promotion_untyped_default.phpt [new file with mode: 0644]
Zend/zend_compile.c

diff --git a/NEWS b/NEWS
index 00100bed800ae7455b595077b49c3a91ad16af55..55bba33d123ac709b6bb4fc3f692f2fe05756203 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,8 @@ PHP                                                                        NEWS
     (Nikita)
   . Fixed bug #79852 (count(DOMNodeList) doesn't match
     count(IteratorIterator(DOMNodeList))). (Nikita)
+  . Fixed bug #79867 (Promoted untyped properties should get null default
+    value). (Nikita)
 
 09 Jul 2020, PHP 8.0.0alpha2
 
diff --git a/Zend/tests/ctor_promotion_untyped_default.phpt b/Zend/tests/ctor_promotion_untyped_default.phpt
new file mode 100644 (file)
index 0000000..50b4962
--- /dev/null
@@ -0,0 +1,29 @@
+--TEST--
+Bug #79867: Promoted untyped properties should get null default value
+--FILE--
+<?php
+
+class A {
+    public function __construct(
+        public $untyped = 1,
+        public int $typed = 2,
+    ) {}
+}
+
+class B extends A {
+    public function __construct() {
+        // Missing parent::__construct() call,
+        // properties will not be initialized.
+    }
+}
+
+var_dump(new B);
+
+?>
+--EXPECT--
+object(B)#1 (1) {
+  ["untyped"]=>
+  NULL
+  ["typed"]=>
+  uninitialized(int)
+}
index 6725e7ee826f531e2b3396140b31a44a6282025f..4529aea5ba008f014b663cb17b57083c05cca903 100644 (file)
@@ -6197,16 +6197,21 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
                                        ZSTR_VAL(scope->name), ZSTR_VAL(name), ZSTR_VAL(str));
                        }
 
-                       /* Always use uninitialized as the default. */
-                       zval default_value;
-                       ZVAL_UNDEF(&default_value);
-
                        /* Recompile the type, as it has different memory management requirements. */
                        zend_type type = ZEND_TYPE_INIT_NONE(0);
                        if (type_ast) {
                                type = zend_compile_typename(type_ast, /* force_allow_null */ 0, /* use_arena */ 1);
                        }
 
+                       /* Don't give the property an explicit default value. For typed properties this means
+                        * uninitialized, for untyped properties it means an implicit null default value. */
+                       zval default_value;
+                       if (ZEND_TYPE_IS_SET(type)) {
+                               ZVAL_UNDEF(&default_value);
+                       } else {
+                               ZVAL_NULL(&default_value);
+                       }
+
                        zend_string *doc_comment =
                                doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
                        zend_property_info *prop = zend_declare_typed_property(