From 058554810649da431efa3ab851be17b0d2f96fb8 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 27 Mar 2019 18:09:09 +0100 Subject: [PATCH] Treat abstract ctors the same, regardless of origin 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 | 2 +- .../constructor_abstract_grantparent.phpt | 18 ++++++++++++++++++ Zend/zend_inheritance.c | 8 ++++---- 3 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 Zend/tests/constructor_abstract_grantparent.phpt diff --git a/Zend/tests/bug61970_2.phpt b/Zend/tests/bug61970_2.phpt index 3e4b5222be..403ba7510a 100644 --- a/Zend/tests/bug61970_2.phpt +++ b/Zend/tests/bug61970_2.phpt @@ -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 index 0000000000..b813c4c1f7 --- /dev/null +++ b/Zend/tests/constructor_abstract_grantparent.phpt @@ -0,0 +1,18 @@ +--TEST-- +LSP checks are performed against an abstract constructor even if it is not a direct parent +--FILE-- + +--EXPECTF-- +Fatal error: Declaration of C::__construct() must be compatible with A::__construct(X $x) in %s on line 10 diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 72bc9cfaae..0916d91f77 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -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 { -- 2.40.0