]> granicus.if.org Git - php/commitdiff
Treat abstract ctors the same, regardless of origin
authorNikita Popov <nikita.ppv@gmail.com>
Wed, 27 Mar 2019 17:09:09 +0000 (18:09 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 27 Mar 2019 17:09:09 +0000 (18:09 +0100)
Abstract ctor signatures should always be respected by all children,
independently of whether it comes from an interface or an abstract
class. Previously abstract ctor signatures (if they didn't come from
an interface) were only checked to one level of inheritance.

Zend/tests/bug61970_2.phpt
Zend/tests/constructor_abstract_grantparent.phpt [new file with mode: 0644]
Zend/zend_inheritance.c

index 3e4b5222bebf3dafb9718031cb4ee498efad1790..403ba7510a23a9a58414166142b514398c2c903f 100644 (file)
@@ -15,4 +15,4 @@ class Baz extends Bar {
     protected function __construct(){}
 }
 --EXPECTF--
-Fatal error: Access level to Baz::__construct() must be public (as in class Bar) in %s on line 12
+Fatal error: Access level to Baz::__construct() must be public (as in class Foo) in %s on line 12
diff --git a/Zend/tests/constructor_abstract_grantparent.phpt b/Zend/tests/constructor_abstract_grantparent.phpt
new file mode 100644 (file)
index 0000000..b813c4c
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+LSP checks are performed against an abstract constructor even if it is not a direct parent
+--FILE--
+<?php
+
+abstract class A {
+    abstract function __construct(X $x);
+}
+class B extends A {
+    function __construct(X $x) {}
+}
+class C extends B {
+    function __construct() {}
+}
+
+?>
+--EXPECTF--
+Fatal error: Declaration of C::__construct() must be compatible with A::__construct(X $x) in %s on line 10
index 72bc9cfaae90e8a9789ee4208f787764579dcadf..0916d91f77222a02ba218e66363572aee8873d6a 100644 (file)
@@ -597,11 +597,11 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function *
                                        proto = parent;
                                }
                        } else if (proto) {
-                               if (proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) {
-                                       /* ctors only have a prototype if it comes from an interface */
-                                       /* and if that is the case, we want to check inheritance against it */
+                               /* ctors only have a prototype if is abstract (or comes from an interface) */
+                               /* and if that is the case, we want to check inheritance against it */
+                               if (proto->common.fn_flags & ZEND_ACC_ABSTRACT) {
                                        parent = proto;
-                               } else if (!(proto->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+                               } else {
                                        break;
                                }
                        } else {