From 45c5b49379ec625ab96160b042147b5c999dfbc0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 27 Mar 2019 17:57:04 +0100 Subject: [PATCH] Saner prototype assignment --- Zend/zend_compile.h | 3 +++ Zend/zend_inheritance.c | 25 ++++++++----------- .../tests/ReflectionClass_toString_002.phpt | 2 +- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 646aef4663310..33cdba06e78b0 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -326,6 +326,9 @@ typedef struct _zend_oparray_context { /* function is a destructor | | | */ #define ZEND_ACC_DTOR (1 << 29) /* | X | | */ /* | | | */ +/* function is a destructor | | | */ +#define ZEND_ACC_HAS_ABSTRACT_PARENT (1 << 30) /* | X | | */ +/* | | | */ /* op_array uses strict mode types | | | */ #define ZEND_ACC_STRICT_TYPES (1U << 31) /* | X | | */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 0916d91f77222..e09868a18acd8 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -587,27 +587,24 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * child->common.fn_flags |= ZEND_ACC_CHANGED; } + if (parent_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_HAS_ABSTRACT_PARENT)) { + child->common.fn_flags |= ZEND_ACC_HAS_ABSTRACT_PARENT; + } + do { if (!(parent_flags & ZEND_ACC_PRIVATE)) { - zend_function *proto = parent->common.prototype ? - parent->common.prototype : parent; - - if (!(parent_flags & ZEND_ACC_CTOR)) { - if (!proto) { - proto = parent; - } - } else if (proto) { + if (parent_flags & ZEND_ACC_CTOR) { /* 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 */ + zend_function *proto = parent->common.prototype + ? parent->common.prototype : parent; if (proto->common.fn_flags & ZEND_ACC_ABSTRACT) { parent = proto; } else { break; } - } else { - break; } - if (child_zv && child->common.prototype != proto) { + if (child_zv && child->common.prototype != parent) { do { if (child->common.scope != ce && child->type == ZEND_USER_FUNCTION @@ -622,7 +619,7 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * Z_PTR_P(child_zv) = child = new_function; } } - child->common.prototype = proto; + child->common.prototype = parent; } while (0); } /* Prevent derived classes from restricting access that was available in parent classes (except deriving from non-abstract ctors) */ @@ -638,9 +635,7 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * zend_string *method_prototype = zend_get_function_declaration(parent); zend_string *child_prototype = zend_get_function_declaration(child); - if (child->common.prototype && ( - child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT - )) { + if (child->common.fn_flags & ZEND_ACC_HAS_ABSTRACT_PARENT) { error_level = E_COMPILE_ERROR; error_verb = "must"; } else if ((parent->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) && diff --git a/ext/reflection/tests/ReflectionClass_toString_002.phpt b/ext/reflection/tests/ReflectionClass_toString_002.phpt index 5395ae66b9d0a..3317e19c29291 100644 --- a/ext/reflection/tests/ReflectionClass_toString_002.phpt +++ b/ext/reflection/tests/ReflectionClass_toString_002.phpt @@ -114,7 +114,7 @@ Class [ class D extends C ] { } - Methods [1] { - Method [ public method f ] { + Method [ public method f ] { @@ %s 12 - 12 } }