diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-09-23 16:12:18 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-09-23 16:20:26 +0200 |
commit | 5dcbc65a53b7f7c6e517b19260c637017528b3f9 (patch) | |
tree | efe5dce103f86dfe9ba616466bc2d2403fecdfa6 | |
parent | b7745d6eeb39dffc616ef48b92b6b2cfc7e571a5 (diff) | |
download | php-git-5dcbc65a53b7f7c6e517b19260c637017528b3f9.tar.gz |
Canonicalize typed prop/param default value errors
Use shared logic to determine what values are valid, and a single
error message format.
-rw-r--r-- | Zend/tests/bug69767.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/errmsg_013.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/object_types/invalid_default_value.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/type_declarations/iterable_002.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/type_declarations/typed_properties_013.phpt | 2 | ||||
-rw-r--r-- | Zend/tests/type_declarations/typed_properties_014.phpt | 2 | ||||
-rw-r--r-- | Zend/zend_compile.c | 101 | ||||
-rw-r--r-- | tests/lang/type_hints_003.phpt | 2 |
9 files changed, 48 insertions, 69 deletions
diff --git a/Zend/tests/bug69767.phpt b/Zend/tests/bug69767.phpt index 9458546dea..095bfd89d5 100644 --- a/Zend/tests/bug69767.phpt +++ b/Zend/tests/bug69767.phpt @@ -5,4 +5,4 @@ Bug #69767 (Default parameter value with wrong type segfaults) function foo(String $bar = 0) {} ?> --EXPECTF-- -Fatal error: Default value for parameters with a string type can only be string or NULL in %sbug69767.php on line %d +Fatal error: Cannot use int as default value for parameter $bar of type string in %s on line %d diff --git a/Zend/tests/errmsg_013.phpt b/Zend/tests/errmsg_013.phpt index 606282458b..037ef9b1aa 100644 --- a/Zend/tests/errmsg_013.phpt +++ b/Zend/tests/errmsg_013.phpt @@ -11,4 +11,4 @@ class test { echo "Done\n"; ?> --EXPECTF-- -Fatal error: Default value for parameters with array type can only be an array or NULL in %s on line %d +Fatal error: Cannot use string as default value for parameter $a of type array in %s on line %d diff --git a/Zend/tests/object_types/invalid_default_value.phpt b/Zend/tests/object_types/invalid_default_value.phpt index 2768e00e7d..39272b05c0 100644 --- a/Zend/tests/object_types/invalid_default_value.phpt +++ b/Zend/tests/object_types/invalid_default_value.phpt @@ -7,4 +7,4 @@ function test(object $obj = 42) { } ?> --EXPECTF-- -Fatal error: Default value for parameters with an object type can only be NULL in %s on line %d +Fatal error: Cannot use int as default value for parameter $obj of type object in %s on line %d diff --git a/Zend/tests/type_declarations/iterable_002.phpt b/Zend/tests/type_declarations/iterable_002.phpt index b9e02e40cd..fdc3b20df5 100644 --- a/Zend/tests/type_declarations/iterable_002.phpt +++ b/Zend/tests/type_declarations/iterable_002.phpt @@ -17,4 +17,4 @@ function baz(iterable $iterable = 1) { ?> --EXPECTF-- -Fatal error: Default value for parameters with iterable type can only be an array or NULL in %s on line %d +Fatal error: Cannot use int as default value for parameter $iterable of type iterable in %s on line %d diff --git a/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt b/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt index fd7f96ab95..fc6fc21b17 100644 --- a/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt +++ b/Zend/tests/type_declarations/scalar_float_with_invalid_default.phpt @@ -12,4 +12,4 @@ test(); ?> --EXPECTF-- -Fatal error: Default value for parameters with a float type can only be float, integer, or NULL in %s on line %d +Fatal error: Cannot use bool as default value for parameter $arg of type float in %s on line %d diff --git a/Zend/tests/type_declarations/typed_properties_013.phpt b/Zend/tests/type_declarations/typed_properties_013.phpt index 01c2f4b6a0..7236e21a2c 100644 --- a/Zend/tests/type_declarations/typed_properties_013.phpt +++ b/Zend/tests/type_declarations/typed_properties_013.phpt @@ -7,4 +7,4 @@ class Foo { } ?> --EXPECTF-- -Fatal error: Default value for property of type int can only be int in %s on line 3 +Fatal error: Cannot use string as default value for property Foo::$bar of type int in %s on line 3 diff --git a/Zend/tests/type_declarations/typed_properties_014.phpt b/Zend/tests/type_declarations/typed_properties_014.phpt index 2a02f0381e..f7a4449abd 100644 --- a/Zend/tests/type_declarations/typed_properties_014.phpt +++ b/Zend/tests/type_declarations/typed_properties_014.phpt @@ -7,4 +7,4 @@ class Foo { } ?> --EXPECTF-- -Fatal error: Default value for property of type array can only be an array in %s on line 3 +Fatal error: Cannot use int as default value for property Foo::$bar of type array in %s on line 3 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 373792548f..1e20ff95b9 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5343,6 +5343,29 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null } /* }}} */ +static zend_bool zend_is_valid_default_value(zend_type type, zval *value) +{ + ZEND_ASSERT(ZEND_TYPE_IS_SET(type)); + if (Z_TYPE_P(value) == IS_NULL && ZEND_TYPE_ALLOW_NULL(type)) { + return 1; + } + + if (ZEND_TYPE_IS_CLASS(type)) { + return 0; + } + if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) { + return 1; + } + if ((ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) { + /* Integers are allowed as initializers for floating-point values. */ + return 1; + } + if ((ZEND_TYPE_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) { + return 1; + } + return 0; +} + void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -5449,41 +5472,13 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - if (default_type > IS_NULL && default_type != IS_CONSTANT_AST) { - if (is_class) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a class type can only be NULL"); - } else { - if (arg_type & MAY_BE_CALLABLE) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with callable type can only be NULL"); - } else if (arg_type & MAY_BE_ARRAY) { - if (default_type != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with array type can only be an array or NULL"); - } - } else if (arg_type & MAY_BE_DOUBLE) { - if (default_type != IS_DOUBLE && default_type != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a float type can only be float, integer, or NULL"); - } - } else if (arg_type & MAY_BE_ITERABLE) { - if (default_type != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with iterable type can only be an array or NULL"); - } - } else if (arg_type & MAY_BE_OBJECT) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with an object type can only be NULL"); - } else if (!ZEND_TYPE_CONTAINS_CODE(arg_type, default_type)) { - zend_string *type_str = - zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(arg_type)); - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "with a %s type can only be %s or NULL", - ZSTR_VAL(type_str), ZSTR_VAL(type_str)); - zend_string_release(type_str); - } - } + if (default_type > IS_NULL && default_type != IS_CONSTANT_AST + && !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) { + zend_string *type_str = zend_type_to_string(arg_info->type); + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use %s as default value for parameter $%s of type %s", + zend_get_type_by_const(default_type), + ZSTR_VAL(name), ZSTR_VAL(type_str)); } /* Allocate cache slot to speed-up run-time class resolution */ @@ -6034,35 +6029,19 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / if (value_ast) { zend_const_expr_to_zval(&value_zv, value_ast); - if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) { + if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv) + && !zend_is_valid_default_value(type, &value_zv)) { + zend_string *str = zend_type_to_string(type); if (Z_TYPE(value_zv) == IS_NULL) { - if (!ZEND_TYPE_ALLOW_NULL(type)) { - zend_string *str = zend_type_to_string(type); - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s may not be null. " - "Use the nullable type ?%s to allow null default value", - ZSTR_VAL(str), ZSTR_VAL(str)); - } - } else if (ZEND_TYPE_IS_CLASS(type)) { zend_error_noreturn(E_COMPILE_ERROR, - "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type))); - } else if (ZEND_TYPE_MASK(type) & (MAY_BE_ARRAY|MAY_BE_ITERABLE)) { - if (Z_TYPE(value_zv) != IS_ARRAY) { - zend_string *str = zend_type_to_string(type); - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s can only be an array", - ZSTR_VAL(str)); - } - } else if (ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) { - if (Z_TYPE(value_zv) != IS_DOUBLE && Z_TYPE(value_zv) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type float can only be float or int"); - } - } else if (!ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(value_zv))) { - zend_string *str = zend_type_to_string(type); + "Default value for property of type %s may not be null. " + "Use the nullable type ?%s to allow null default value", + ZSTR_VAL(str), ZSTR_VAL(str)); + } else { zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s can only be %s", - ZSTR_VAL(str), ZSTR_VAL(str)); + "Cannot use %s as default value for property %s::$%s of type %s", + zend_get_type_by_const(Z_TYPE(value_zv)), + ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str)); } } } else if (!ZEND_TYPE_IS_SET(type)) { diff --git a/tests/lang/type_hints_003.phpt b/tests/lang/type_hints_003.phpt index f6b04dabff..00471b9448 100644 --- a/tests/lang/type_hints_003.phpt +++ b/tests/lang/type_hints_003.phpt @@ -8,4 +8,4 @@ class T { } ?> --EXPECTF-- -Fatal error: Default value for parameters with a class type can only be NULL in %stype_hints_003.php on line 3 +Fatal error: Cannot use int as default value for parameter $p of type P in %s on line %d |