]> granicus.if.org Git - php/commitdiff
Refactor error implementation significantly to centralize error mode behavior. Add...
authorAnthony Ferrara <ircmaxell@gmail.com>
Wed, 18 Mar 2015 16:23:09 +0000 (12:23 -0400)
committerAnthony Ferrara <ircmaxell@gmail.com>
Wed, 18 Mar 2015 16:23:09 +0000 (12:23 -0400)
Zend/tests/typehints/scalar_basic.phpt
Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_exceptions.c
Zend/zend_exceptions.h
Zend/zend_execute.c
Zend/zend_execute.h

index af10b559efeea602708ce4381caf67e0308f546b..df1abe2607eac89d400eaa2c27ca2ba3ce6ef87c 100644 (file)
@@ -6,7 +6,6 @@ Scalar type hint basics
 $errnames = [
     E_NOTICE => 'E_NOTICE',
     E_WARNING => 'E_WARNING',
-    E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR'
 ];
 set_error_handler(function (int $errno, string $errmsg, string $file, int $line) use ($errnames) {
     echo "$errnames[$errno]: $errmsg on line $line\n";
@@ -48,194 +47,231 @@ $values = [
 foreach ($functions as $type => $function) {
     echo PHP_EOL, "Testing '$type' typehint:", PHP_EOL;
     foreach ($values as $value) {
-        echo "*** Trying ";
+        echo PHP_EOL . "*** Trying ";
         var_dump($value);
-        var_dump($function($value));
+        try {
+               var_dump($function($value));
+        } catch (\TypeException $e) {
+               echo "*** Caught " . $e->getMessage() . PHP_EOL;
+        }
     }
 }
+echo PHP_EOL . "Done";
+?>
 --EXPECTF--
 
 Testing 'int' typehint:
+
 *** Trying int(1)
 int(1)
+
 *** Trying string(1) "1"
 int(1)
+
 *** Trying float(1)
 int(1)
+
 *** Trying float(1.5)
 int(1)
+
 *** Trying string(2) "1a"
 E_NOTICE: A non well formed numeric value encountered on line %d
 int(1)
+
 *** Trying string(1) "a"
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined on line %d
-string(1) "a"
+*** Caught Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined in %s on line %d
+
 *** Trying string(0) ""
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined on line %d
-string(0) ""
+*** Caught Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined in %s on line %d
+
 *** Trying int(%d)
 int(%d)
+
 *** Trying float(NAN)
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, float given, called in %s on line %d and defined on line %d
-float(NAN)
+*** Caught Argument 1 passed to {closure}() must be of the type integer, float given, called in %s on line %d and defined in %s on line %d
+
 *** Trying bool(true)
 int(1)
+
 *** Trying bool(false)
 int(0)
+
 *** Trying NULL
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, null given, called in %s on line %d and defined on line %d
-NULL
+*** Caught Argument 1 passed to {closure}() must be of the type integer, null given, called in %s on line %d and defined in %s on line %d
+
 *** Trying array(0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, array given, called in %s on line %d and defined on line %d
-array(0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type integer, array given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(stdClass)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined on line %d
-object(stdClass)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(Stringable)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined on line %d
-object(Stringable)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying resource(%d) of type (stream)
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, resource given, called in %s on line %d and defined on line %d
-resource(%d) of type (stream)
+*** Caught Argument 1 passed to {closure}() must be of the type integer, resource given, called in %s on line %d and defined in %s on line %d
 
 Testing 'float' typehint:
+
 *** Trying int(1)
 float(1)
+
 *** Trying string(1) "1"
 float(1)
+
 *** Trying float(1)
 float(1)
+
 *** Trying float(1.5)
 float(1.5)
+
 *** Trying string(2) "1a"
 E_NOTICE: A non well formed numeric value encountered on line %d
 float(1)
+
 *** Trying string(1) "a"
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined on line %d
-string(1) "a"
+*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined in %s on line %d
+
 *** Trying string(0) ""
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined on line %d
-string(0) ""
+*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined in %s on line %d
+
 *** Trying int(%d)
 float(%s)
+
 *** Trying float(NAN)
 float(NAN)
+
 *** Trying bool(true)
 float(1)
+
 *** Trying bool(false)
 float(0)
+
 *** Trying NULL
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, null given, called in %s on line %d and defined on line %d
-NULL
+*** Caught Argument 1 passed to {closure}() must be of the type float, null given, called in %s on line %d and defined in %s on line %d
+
 *** Trying array(0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, array given, called in %s on line %d and defined on line %d
-array(0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type float, array given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(stdClass)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined on line %d
-object(stdClass)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(Stringable)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined on line %d
-object(Stringable)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying resource(%d) of type (stream)
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, resource given, called in %s on line %d and defined on line %d
-resource(%d) of type (stream)
+*** Caught Argument 1 passed to {closure}() must be of the type float, resource given, called in %s on line %d and defined in %s on line %d
 
 Testing 'string' typehint:
+
 *** Trying int(1)
 string(1) "1"
+
 *** Trying string(1) "1"
 string(1) "1"
+
 *** Trying float(1)
 string(1) "1"
+
 *** Trying float(1.5)
 string(3) "1.5"
+
 *** Trying string(2) "1a"
 string(2) "1a"
+
 *** Trying string(1) "a"
 string(1) "a"
+
 *** Trying string(0) ""
 string(0) ""
+
 *** Trying int(%d)
 string(%d) "%d"
+
 *** Trying float(NAN)
 string(3) "NAN"
+
 *** Trying bool(true)
 string(1) "1"
+
 *** Trying bool(false)
 string(0) ""
+
 *** Trying NULL
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, null given, called in %s on line %d and defined on line %d
-NULL
+*** Caught Argument 1 passed to {closure}() must be of the type string, null given, called in %s on line %d and defined in %s on line %d
+
 *** Trying array(0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, array given, called in %s on line %d and defined on line %d
-array(0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type string, array given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(stdClass)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, object given, called in %s on line %d and defined on line %d
-object(stdClass)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type string, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(Stringable)#%s (0) {
 }
 string(6) "foobar"
+
 *** Trying resource(%d) of type (stream)
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, resource given, called in %s on line %d and defined on line %d
-resource(%d) of type (stream)
+*** Caught Argument 1 passed to {closure}() must be of the type string, resource given, called in %s on line %d and defined in %s on line %d
 
 Testing 'bool' typehint:
+
 *** Trying int(1)
 bool(true)
+
 *** Trying string(1) "1"
 bool(true)
+
 *** Trying float(1)
 bool(true)
+
 *** Trying float(1.5)
 bool(true)
+
 *** Trying string(2) "1a"
 bool(true)
+
 *** Trying string(1) "a"
 bool(true)
+
 *** Trying string(0) ""
 bool(false)
+
 *** Trying int(%d)
 bool(true)
+
 *** Trying float(NAN)
 bool(true)
+
 *** Trying bool(true)
 bool(true)
+
 *** Trying bool(false)
 bool(false)
+
 *** Trying NULL
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, null given, called in %s on line %d and defined on line %d
-NULL
+*** Caught Argument 1 passed to {closure}() must be of the type boolean, null given, called in %s on line %d and defined in %s on line %d
+
 *** Trying array(0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, array given, called in %s on line %d and defined on line %d
-array(0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type boolean, array given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(stdClass)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined on line %d
-object(stdClass)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying object(Stringable)#%s (0) {
 }
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined on line %d
-object(Stringable)#%s (0) {
-}
+*** Caught Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined in %s on line %d
+
 *** Trying resource(%d) of type (stream)
-E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, resource given, called in %s on line %d and defined on line %d
-resource(%d) of type (stream)
+*** Caught Argument 1 passed to {closure}() must be of the type boolean, resource given, called in %s on line %d and defined in %s on line %d
+
+Done
\ No newline at end of file
index fe507d7154b1248b460fbe7c50b7f541cfd376b8..8ed8b2abc155568c11836f1875fc29c531a615b8 100644 (file)
@@ -1277,6 +1277,35 @@ ZEND_API ZEND_NORETURN void zend_error_noreturn(int type, const char *format, ..
 # endif
 #endif
 
+ZEND_API void zend_type_error(const char *format, ...) /* {{{ */
+{
+       va_list va;
+       char *message = NULL;
+
+       va_start(va, format);
+       zend_vspprintf(&message, 0, format, va);
+       zend_throw_exception(zend_get_type_exception(), message, 0);
+       efree(message);
+       va_end(va);
+} /* }}} */
+
+ZEND_API void zend_internal_type_error(zend_bool strict, const char *format, ...) /* {{{ */
+{
+       va_list va;
+       char *message = NULL;
+
+       va_start(va, format);
+       zend_vspprintf(&message, 0, format, va);
+       if (strict) {
+               zend_throw_exception(zend_get_type_exception(), message, 0);
+       } else {
+               zend_error(E_WARNING, message);
+       }
+       efree(message);
+
+       va_end(va);
+} /* }}} */
+
 ZEND_API void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) /* {{{ */
 {
 #if ZEND_DEBUG
index 94cab74af162b7c800bb9909e09aef0cd3e9e487..db132a583a54360ce97e6f568758694026656053 100644 (file)
@@ -285,6 +285,8 @@ extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len);
 extern ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len);
 
 ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API void zend_type_error(const char *format, ...);
+ZEND_API void zend_internal_type_error(zend_bool strict, const char *format, ...);
 
 void zenderror(const char *error);
 
index 02eab229f0c0cd7109a8cc1773dad15cedae9648..af389623a3540c1df3a4cbde62273fadc9e89f5e 100644 (file)
@@ -153,9 +153,8 @@ ZEND_API void _zend_wrong_param_count(zend_bool strict) /* {{{ */
 {
        const char *space;
        const char *class_name = get_active_class_name(&space);
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
 
-       zend_error(error_type, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
+       zend_internal_type_error(strict, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
 }
 /* }}} */
 
@@ -239,9 +238,8 @@ ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, in
 {
        zend_function *active_function = EG(current_execute_data)->func;
        const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
 
-       zend_error(error_type, "%s%s%s() expects %s %d parameter%s, %d given",
+       zend_internal_type_error(strict, "%s%s%s() expects %s %d parameter%s, %d given",
                class_name, \
                class_name[0] ? "::" : "", \
                active_function->common.function_name->val,
@@ -260,9 +258,8 @@ ZEND_API void zend_wrong_paramer_type_error(int num, zend_expected_type expected
                Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
                NULL
        };
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
 
-       zend_error(error_type, "%s%s%s() expects parameter %d to be %s, %s given",
+       zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be %s, %s given",
                class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
 }
 /* }}} */
@@ -271,9 +268,8 @@ ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg, zen
 {
        const char *space;
        const char *class_name = get_active_class_name(&space);
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
 
-       zend_error(error_type, "%s%s%s() expects parameter %d to be %s, %s given",
+       zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be %s, %s given",
                class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
 }
 /* }}} */
@@ -292,7 +288,6 @@ ZEND_API void zend_wrong_callback_error(int severity, int num, char *error) /* {
 ZEND_API int zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null, zend_bool strict) /* {{{ */
 {
        zend_class_entry *ce_base = *pce;
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
 
        if (check_null && Z_TYPE_P(arg) == IS_NULL) {
                *pce = NULL;
@@ -305,7 +300,7 @@ ZEND_API int zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, in
                        const char *space;
                        const char *class_name = get_active_class_name(&space);
 
-                       zend_error(error_type, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
+                       zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
                                class_name, space, get_active_function_name(), num,
                                ce_base->name->val, Z_STRVAL_P(arg));
                        *pce = NULL;
@@ -316,7 +311,7 @@ ZEND_API int zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, in
                const char *space;
                const char *class_name = get_active_class_name(&space);
 
-               zend_error(error_type, "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
+               zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
                        class_name, space, get_active_function_name(), num,
                        Z_STRVAL_P(arg));
                return 0;
@@ -580,7 +575,6 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec
 {
        const char *expected_type = NULL;
        char *error = NULL;
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
        int severity;
 
        expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity, strict);
@@ -590,11 +584,11 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec
                        const char *class_name = get_active_class_name(&space);
 
                        if (error) {
-                               zend_error(error_type, "%s%s%s() expects parameter %d %s",
-                                               class_name, space, get_active_function_name(), arg_num, error);
+                               zend_internal_type_error(strict, "%s%s%s() expects parameter %d %s",
+                                                       class_name, space, get_active_function_name(), arg_num, error);
                                efree(error);
                        } else {
-                               zend_error(error_type, "%s%s%s() expects parameter %d to be %s, %s given",
+                               zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be %s, %s given",
                                                class_name, space, get_active_function_name(), arg_num, expected_type,
                                                zend_zval_type_name(arg));
                        }
@@ -636,7 +630,6 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
        zend_bool have_varargs = 0;
        zval **varargs = NULL;
        int *n_varargs = NULL;
-       int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING;
 
        for (spec_walk = type_spec; *spec_walk; spec_walk++) {
                c = *spec_walk;
@@ -670,7 +663,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
                                                zend_function *active_function = EG(current_execute_data)->func;
                                                const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
                                                
-                                               zend_error(error_type, "%s%s%s(): only one varargs specifier (* or +) is permitted",
+                                               zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
                                                                class_name,
                                                                class_name[0] ? "::" : "",
                                                                active_function->common.function_name->val);
@@ -690,7 +683,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
                                if (!quiet) {
                                        zend_function *active_function = EG(current_execute_data)->func;
                                        const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
-                                       zend_error(error_type, "%s%s%s(): bad type specifier while parsing parameters",
+                                       zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
                                                        class_name,
                                                        class_name[0] ? "::" : "",
                                                        active_function->common.function_name->val);
@@ -713,7 +706,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
                if (!quiet) {
                        zend_function *active_function = EG(current_execute_data)->func;
                        const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
-                       zend_error(error_type, "%s%s%s() expects %s %d parameter%s, %d given",
+                       zend_internal_type_error(strict, "%s%s%s() expects %s %d parameter%s, %d given",
                                        class_name,
                                        class_name[0] ? "::" : "",
                                        active_function->common.function_name->val,
@@ -728,7 +721,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
        arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
 
        if (num_args > arg_count) {
-               zend_error(error_type, "%s(): could not obtain parameters for parsing",
+               zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
                        get_active_function_name());
                return FAILURE;
        }
@@ -782,7 +775,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
        if (0 == (type_spec)[0] && 0 != __num_args && !(flags & ZEND_PARSE_PARAMS_QUIET)) { \
                const char *__space; \
                const char * __class_name = get_active_class_name(&__space); \
-               zend_error((flags & ZEND_PARSE_PARAMS_STRICT) ? (E_EXCEPTION | E_ERROR) : E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
+               zend_internal_type_error((flags & ZEND_PARSE_PARAMS_STRICT), "%s%s%s() expects exactly 0 parameters, %d given", \
                        __class_name, __space, \
                        get_active_function_name(), __num_args); \
                return FAILURE; \
index 7070934426cb5a26389cbb78787070845a66f415..2a8af1bf28dd451ab2ad5cdb286e1e6075917280 100644 (file)
@@ -35,6 +35,7 @@ static zend_class_entry *default_exception_ce;
 static zend_class_entry *error_exception_ce;
 static zend_class_entry *engine_exception_ce;
 static zend_class_entry *parse_exception_ce;
+static zend_class_entry *type_exception_ce;
 static zend_object_handlers default_exception_handlers;
 ZEND_API void (*zend_throw_exception_hook)(zval *ex);
 
@@ -778,6 +779,10 @@ void zend_register_default_exception(void) /* {{{ */
        INIT_CLASS_ENTRY(ce, "ParseException", NULL);
        parse_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce);
        parse_exception_ce->create_object = zend_default_exception_new;
+
+       INIT_CLASS_ENTRY(ce, "TypeException", NULL);
+       type_exception_ce = zend_register_internal_class_ex(&ce, engine_exception_ce);
+       type_exception_ce->create_object = zend_default_exception_new;
 }
 /* }}} */
 
@@ -811,6 +816,12 @@ ZEND_API zend_class_entry *zend_get_parse_exception(void) /* {{{ */
 }
 /* }}} */
 
+ZEND_API zend_class_entry *zend_get_type_exception(void) /* {{{ */
+{
+       return type_exception_ce;
+}
+/* }}} */
+
 
 ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */
 {
@@ -892,7 +903,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */
        ZVAL_OBJ(&exception, ex);
        ce_exception = Z_OBJCE(exception);
        EG(exception) = NULL;
-       if (ce_exception == parse_exception_ce || ce_exception == engine_exception_ce) {
+       if (ce_exception == parse_exception_ce || ce_exception == engine_exception_ce || ce_exception == type_exception_ce) {
                zend_string *message = zval_get_string(GET_PROPERTY(&exception, "message"));
                zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file"));
                zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line"));
index 10609fecb66ad6b268780701aafc992e1d9e0b85..e2c1f1fac7fe4207572ccae8ae6090f05114e7b3 100644 (file)
@@ -39,6 +39,7 @@ ZEND_API zend_class_entry *zend_exception_get_default(void);
 ZEND_API zend_class_entry *zend_get_error_exception(void);
 ZEND_API zend_class_entry *zend_get_engine_exception(void);
 ZEND_API zend_class_entry *zend_get_parse_exception(void);
+ZEND_API zend_class_entry *zend_get_type_exception(void);
 ZEND_API void zend_register_default_classes(void);
 
 /* exception_ce   NULL or zend_exception_get_default() or a derived class
index 4321c0f33090448950ac9e13ce7e3d6c7e3d15b8..36bf6b1bea9fefc84ba394a0701de2e89c03a836 100644 (file)
@@ -598,7 +598,7 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ch
        }
 }
 
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg)
+ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg)
 {
        zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
        const char *fname = zf->common.function_name->val;
@@ -621,16 +621,19 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uin
                }
 
                if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
-                       zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno);
+                       zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined in %s on line %d", 
+                                       arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, 
+                                       ptr->func->op_array.filename->val, ptr->opline->lineno,
+                                       zf->op_array.filename->val, EG(current_execute_data)->opline->lineno);
                } else {
-                       zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
+                       zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
                }
 
                if (arg) {
                        ZVAL_COPY_VALUE(arg, &old_arg);
                }
        } else {
-               zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
+               zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
        }
 }
 
@@ -717,27 +720,27 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z
                if (Z_TYPE_P(arg) == IS_OBJECT) {
                        need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
                        if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
-                               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
+                               zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
                        }
                } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
                        need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
-                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
+                       zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
                }
        } else if (cur_arg_info->type_hint) {
                ZVAL_DEREF(arg);
                if (cur_arg_info->type_hint == IS_ARRAY) {
                        if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
-                               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg);
+                               zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg);
                        }
                } else if (cur_arg_info->type_hint == IS_CALLABLE) {
                        if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
-                               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
+                               zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
                        }
                } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(cur_arg_info->type_hint, Z_TYPE_P(arg)))) {
                        if (Z_TYPE_P(arg) == IS_NULL) {
                                if (!cur_arg_info->allow_null) {
 failure:
-                                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
+                                       zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
                                }
                                return;
                        }
@@ -769,27 +772,27 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg,
                if (Z_TYPE_P(arg) == IS_OBJECT) {
                        need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
                        if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
-                               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
+                               zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
                        }
                } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) {
                        need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
-                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
+                       zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
                }
        } else if (cur_arg_info->type_hint) {
                ZVAL_DEREF(arg);
                if (cur_arg_info->type_hint == IS_ARRAY) {
                        if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) {
-                               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg);
+                               zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg);
                        }
                } else if (cur_arg_info->type_hint == IS_CALLABLE) {
                        if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) {
-                               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
+                               zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
                        }
                } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(cur_arg_info->type_hint,  Z_TYPE_P(arg)))) {
                        if (Z_TYPE_P(arg) == IS_NULL) {
                                if (!cur_arg_info->allow_null) {
 failure:
-                                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
+                                       zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
                                }
                                return;
                        }
@@ -818,15 +821,15 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
                char *class_name;
 
                need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
-               zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL);
+               zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL);
                return 0;
        } else if (cur_arg_info->type_hint) {
                if (cur_arg_info->type_hint == IS_ARRAY) {
-                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL);
+                       zend_verify_arg_error(zf, arg_num, "be of the type array", "", "none", "", NULL);
                } else if (cur_arg_info->type_hint == IS_CALLABLE) {
-                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be callable", "", "none", "", NULL);
+                       zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL);
                } else {
-                       zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "", NULL);
+                       zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "", NULL);
                }
                return 0;
        }
@@ -850,7 +853,7 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t ar
        }
 }
 
-ZEND_API void zend_verify_return_error(int error_type, const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
+ZEND_API void zend_verify_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
 {
        const char *fname = zf->common.function_name->val;
        const char *fsep;
@@ -864,8 +867,7 @@ ZEND_API void zend_verify_return_error(int error_type, const zend_function *zf,
                fclass = "";
        }
 
-       zend_error(error_type,
-               "Return value of %s%s%s() must %s%s, %s%s returned",
+       zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned",
                fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
 }
 
@@ -882,30 +884,30 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret, zend_b
                if (Z_TYPE_P(ret) == IS_OBJECT) {
                        need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
                        if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
-                               zend_verify_return_error(E_CORE_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
+                               zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
                                return 0;
                        }
                } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
                        need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
-                       zend_verify_return_error(E_CORE_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), "");
+                       zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
                        return 0;
                }
        } else if (ret_info->type_hint) {
                if (ret_info->type_hint == IS_ARRAY) {
                        if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
-                               zend_verify_return_error(E_CORE_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), "");
+                               zend_verify_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), "");
                                return 0;
                        }
                } else if (ret_info->type_hint == IS_CALLABLE) {
                        if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
-                               zend_verify_return_error(E_CORE_ERROR, zf, "be callable", "", zend_zval_type_name(ret), "");
+                               zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
                                return 0;
                        }
                } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(ret)))) {
                        if (Z_TYPE_P(ret) == IS_NULL) {
                                if (!ret_info->allow_null) {
 failure:
-                                       zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
+                                       zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
                                }
                                return 0;
                        }
@@ -930,26 +932,26 @@ static void zend_verify_return_type(zend_function *zf, zval *ret, zend_bool stri
                if (Z_TYPE_P(ret) == IS_OBJECT) {
                        need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
                        if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
-                               zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
+                               zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
                        }
                } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
                        need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
-                       zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), "");
+                       zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
                }
        } else if (ret_info->type_hint) {
                if (ret_info->type_hint == IS_ARRAY) {
                        if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
-                               zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), "");
+                               zend_verify_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), "");
                        }
                } else if (ret_info->type_hint == IS_CALLABLE) {
                        if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
-                               zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be callable", "", zend_zval_type_name(ret), "");
+                               zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
                        }
                } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(ret)))) {
                        if (Z_TYPE_P(ret) == IS_NULL) {
                                if (!ret_info->allow_null) {
 failure:
-                                       zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
+                                       zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
                                }
                                return;
                        }
@@ -970,15 +972,15 @@ static inline int zend_verify_missing_return_type(zend_function *zf)
                char *class_name;
 
                need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
-               zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, need_msg, class_name, "none", "");
+               zend_verify_return_error(zf, need_msg, class_name, "none", "");
                return 0;
        } else if (ret_info->type_hint) {
                if (ret_info->type_hint == IS_ARRAY) {
-                       zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type array", "", "none", "");
+                       zend_verify_return_error(zf, "be of the type array", "", "none", "");
                } else if (ret_info->type_hint == IS_CALLABLE) {
-                       zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be callable", "", "none", "");
+                       zend_verify_return_error(zf, "be callable", "", "none", "");
                } else {
-                       zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), "none", "");
+                       zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), "none", "");
                }
                return 0;
        }
index 0149da692990835d68cefe6add19e35779630111..c040c8f63325d94cf740cdb4dc57b7b8e0630233 100644 (file)
@@ -49,8 +49,8 @@ ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, c
 
 ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce);
 ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce);
-ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg);
-ZEND_API void zend_verify_return_error(int error_type, const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind);
+ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg);
+ZEND_API void zend_verify_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind);
 
 static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type)
 {