diff options
| author | Nikita Popov <nikic@php.net> | 2016-06-04 13:13:25 +0200 |
|---|---|---|
| committer | Nikita Popov <nikic@php.net> | 2016-06-04 13:27:11 +0200 |
| commit | fe907562ada8929863561b27355e802db4f14a79 (patch) | |
| tree | 36a7307d6dc53de49a9cb591e9aea86d1bce2965 | |
| parent | cb3825a8dc551e6a43b4ea3a01dbd0584bf606bb (diff) | |
| download | php-git-fe907562ada8929863561b27355e802db4f14a79.tar.gz | |
Forbid "return;" for typed returns already at compile-time
These would otherwise generate a "none returned" error at runtime.
Catch them early.
| -rw-r--r-- | Zend/tests/return_types/029.phpt | 4 | ||||
| -rw-r--r-- | Zend/tests/return_types/bug71092.phpt | 4 | ||||
| -rw-r--r-- | Zend/tests/type_declarations/typed_return_without_value.phpt | 14 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 13 |
4 files changed, 28 insertions, 7 deletions
diff --git a/Zend/tests/return_types/029.phpt b/Zend/tests/return_types/029.phpt index 041b354130..adc07cde7f 100644 --- a/Zend/tests/return_types/029.phpt +++ b/Zend/tests/return_types/029.phpt @@ -9,7 +9,7 @@ function foo() : array { try { throw new Exception("xxxx"); } finally { - return ; + return null; } } @@ -21,7 +21,7 @@ Stack trace: #0 %s(%d): foo() #1 {main} -Next TypeError: Return value of foo() must be of the type array, none returned in %s29.php:%d +Next TypeError: Return value of foo() must be of the type array, null returned in %s29.php:%d Stack trace: #0 %s(%d): foo() #1 {main} diff --git a/Zend/tests/return_types/bug71092.phpt b/Zend/tests/return_types/bug71092.phpt index a1ebc79085..1d4fe983b3 100644 --- a/Zend/tests/return_types/bug71092.phpt +++ b/Zend/tests/return_types/bug71092.phpt @@ -9,14 +9,14 @@ function boom(): array { $data = [['id']]; switch ($data[0]) { case ['id']: - return; + return null; } } boom(); ?> --EXPECTF-- -Fatal error: Uncaught TypeError: Return value of boom() must be of the type array, none returned in %sbug71092.php:%d +Fatal error: Uncaught TypeError: Return value of boom() must be of the type array, null returned in %sbug71092.php:%d Stack trace: #0 %s(%d): boom() #1 {main} diff --git a/Zend/tests/type_declarations/typed_return_without_value.phpt b/Zend/tests/type_declarations/typed_return_without_value.phpt new file mode 100644 index 0000000000..1bf932becb --- /dev/null +++ b/Zend/tests/type_declarations/typed_return_without_value.phpt @@ -0,0 +1,14 @@ +--TEST-- +Typed return without value generates compile-time error +--FILE-- +<?php + +function test() : int { + return; +} + +test(); + +?> +--EXPECTF-- +Fatal error: A function with return type must return a value in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9ebe966f16..4bcec416a7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2264,7 +2264,8 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */ } /* }}} */ -static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */ +static void zend_emit_return_type_check( + znode *expr, zend_arg_info *return_info, zend_bool implicit) /* {{{ */ { /* `return ...;` is illegal in a void function (but `return;` isn't) */ if (return_info->type_hint == IS_VOID) { @@ -2278,6 +2279,11 @@ static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) if (return_info->type_hint != IS_UNDEF) { zend_op *opline; + if (!expr && !implicit) { + zend_error_noreturn(E_COMPILE_ERROR, + "A function with return type must return a value"); + } + if (expr && expr->op_type == IS_CONST) { if ((return_info->type_hint == Z_TYPE(expr->u.constant)) ||((return_info->type_hint == _IS_BOOL) @@ -2312,7 +2318,7 @@ void zend_emit_final_return(int return_one) /* {{{ */ zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - zend_emit_return_type_check(NULL, CG(active_op_array)->arg_info - 1); + zend_emit_return_type_check(NULL, CG(active_op_array)->arg_info - 1, 1); } zn.op_type = IS_CONST; @@ -4058,7 +4064,8 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ /* Generator return types are handled separately */ if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { - zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1); + zend_emit_return_type_check( + expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); } zend_handle_loops_and_finally(); |
