@@ -1996,6 +1996,31 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent)
1996
1996
}
1997
1997
/* }}} */
1998
1998
1999
+ static void _inheritance_runtime_error_msg (zend_function * child , zend_function * parent )
2000
+ {
2001
+ int error_level ;
2002
+ const char * error_verb ;
2003
+ zend_string * method_prototype = zend_get_function_declaration (parent );
2004
+ zend_string * child_prototype = zend_get_function_declaration (child );
2005
+
2006
+ if (child -> common .prototype && (
2007
+ child -> common .prototype -> common .fn_flags & ZEND_ACC_ABSTRACT
2008
+ )) {
2009
+ error_level = E_ERROR ;
2010
+ error_verb = "must" ;
2011
+ } else if ((parent -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) &&
2012
+ !_check_inherited_return_type (child , child -> common .arg_info - 1 , parent , parent -> common .arg_info - 1 )) {
2013
+ error_level = E_ERROR ;
2014
+ error_verb = "must" ;
2015
+ } else {
2016
+ error_level = E_WARNING ;
2017
+ error_verb = "should" ;
2018
+ }
2019
+ zend_error (error_level , "Declaration of %s %s be compatible with %s" , ZSTR_VAL (child_prototype ), error_verb , ZSTR_VAL (method_prototype ));
2020
+ zend_string_efree (child_prototype );
2021
+ zend_string_efree (method_prototype );
2022
+ }
2023
+
1999
2024
ZEND_API void zend_verify_variance (zend_class_entry * ce ) /* {{{ */
2000
2025
{
2001
2026
// todo: name? "verify" typically means something else
@@ -2022,14 +2047,30 @@ ZEND_API void zend_verify_variance(zend_class_entry *ce) /* {{{ */
2022
2047
/* Check return type compatibility, but only if the prototype already
2023
2048
* specifies a return type. Adding a new return type is always valid. */
2024
2049
if (parent -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) {
2025
- int check = _check_inherited_return_type (
2026
- child , child -> common .arg_info - 1 ,
2027
- parent , parent -> common .arg_info - 1 );
2028
- if (check < 0 ) {
2029
- zend_error_noreturn (E_ERROR , "Bad return!" );
2050
+ if (child -> common .fn_flags & ZEND_ACC_HAS_RETURN_TYPE ) {
2051
+ int check = _check_inherited_return_type (
2052
+ child , & child -> common .arg_info [-1 ],
2053
+ parent , & parent -> common .arg_info [-1 ]);
2054
+ if (check < 0 ) {
2055
+ _inheritance_runtime_error_msg (child , parent );
2056
+ // todo: what to do with errors, not warnings?
2057
+ continue ;
2058
+ }
2059
+ } else {
2060
+ _inheritance_runtime_error_msg (child , parent );
2061
+ // todo: what to do with errors, not warnings?
2062
+ continue ;
2030
2063
}
2031
2064
}
2032
2065
2066
+ if (parent -> common .required_num_args < child -> common .required_num_args
2067
+ || parent -> common .num_args > child -> common .num_args )
2068
+ {
2069
+ _inheritance_runtime_error_msg (child , parent );
2070
+ // todo: what to do with errors, not warnings?
2071
+ continue ;
2072
+ }
2073
+
2033
2074
num_args = parent -> common .num_args ;
2034
2075
if (parent -> common .fn_flags & ZEND_ACC_VARIADIC ) {
2035
2076
num_args ++ ;
0 commit comments