diff --git a/Zend/tests/deprecation_to_exception_during_inheritance.phpt b/Zend/tests/deprecation_to_exception_during_inheritance.phpt new file mode 100644 index 00000000000..9c10035930e --- /dev/null +++ b/Zend/tests/deprecation_to_exception_during_inheritance.phpt @@ -0,0 +1,19 @@ +--TEST-- +Deprecation promoted to exception should result in fatal error during inheritance +--FILE-- + +--EXPECTF-- +Fatal error: During inheritance of DateTime: Uncaught Exception: Declaration of DateTime@anonymous::getTimezone() should be compatible with DateTime::getTimezone(): DateTimeZone|false in %s:%d +Stack trace: +#0 %s(%d): {closure}(8192, 'Declaration of ...', '%s', 8) +#1 {main} in %s on line %d diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 457f4aa7ce1..5a486af48ae 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -968,6 +968,22 @@ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *ex, int severit } /* }}} */ +ZEND_NORETURN void zend_exception_uncaught_error(const char *format, ...) { + va_list va; + va_start(va, format); + zend_string *prefix = zend_vstrpprintf(0, format, va); + va_end(va); + + ZEND_ASSERT(EG(exception)); + zval exception_zv; + ZVAL_OBJ_COPY(&exception_zv, EG(exception)); + zend_clear_exception(); + + zend_string *exception_str = zval_get_string(&exception_zv); + zend_error_noreturn(E_ERROR, + "%s: Uncaught %s", ZSTR_VAL(prefix), ZSTR_VAL(exception_str)); +} + ZEND_API ZEND_COLD void zend_throw_exception_object(zval *exception) /* {{{ */ { if (exception == NULL || Z_TYPE_P(exception) != IS_OBJECT) { diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 2bfafba1359..dd98fc1ccb7 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -68,6 +68,7 @@ extern ZEND_API void (*zend_throw_exception_hook)(zend_object *ex); /* show an exception using zend_error(severity,...), severity should be E_ERROR */ ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *exception, int severity); +ZEND_NORETURN void zend_exception_uncaught_error(const char *prefix, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2); ZEND_API zend_string *zend_trace_to_string(HashTable *trace, bool include_main); ZEND_API ZEND_COLD void zend_throw_unwind_exit(void); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 0a6c28e59e5..b66345c1c33 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1518,14 +1518,7 @@ zend_class_entry *zend_fetch_class_by_name(zend_string *class_name, zend_string } if (EG(exception)) { if (!(fetch_type & ZEND_FETCH_CLASS_EXCEPTION)) { - zend_string *exception_str; - zval exception_zv; - ZVAL_OBJ(&exception_zv, EG(exception)); - Z_ADDREF(exception_zv); - zend_clear_exception(); - exception_str = zval_get_string(&exception_zv); - zend_error_noreturn(E_ERROR, - "During class fetch: Uncaught %s", ZSTR_VAL(exception_str)); + zend_exception_uncaught_error("During class fetch"); } return NULL; } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 05ee34da2b5..3cbfd04790e 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -877,6 +877,10 @@ static void ZEND_COLD emit_incompatible_method_error( zend_error_at(E_DEPRECATED, NULL, func_lineno(child), "Declaration of %s should be compatible with %s", ZSTR_VAL(child_prototype), ZSTR_VAL(parent_prototype)); + if (EG(exception)) { + zend_exception_uncaught_error( + "During inheritance of %s", ZSTR_VAL(parent_scope->name)); + } } } else { zend_error_at(E_COMPILE_ERROR, NULL, func_lineno(child), @@ -2454,14 +2458,8 @@ static void check_unrecoverable_load_failure(zend_class_entry *ce) { || ((ce->ce_flags & ZEND_ACC_IMMUTABLE) && CG(unlinked_uses) && zend_hash_index_del(CG(unlinked_uses), (zend_long)(zend_uintptr_t)ce) == SUCCESS)) { - zend_string *exception_str; - zval exception_zv; - ZEND_ASSERT(EG(exception) && "Exception must have been thrown"); - ZVAL_OBJ_COPY(&exception_zv, EG(exception)); - zend_clear_exception(); - exception_str = zval_get_string(&exception_zv); - zend_error_noreturn(E_ERROR, - "During inheritance of %s with variance dependencies: Uncaught %s", ZSTR_VAL(ce->name), ZSTR_VAL(exception_str)); + zend_exception_uncaught_error( + "During inheritance of %s with variance dependencies", ZSTR_VAL(ce->name)); } }