summaryrefslogtreecommitdiff
path: root/Zend/tests
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/tests')
-rw-r--r--Zend/tests/001.phpt21
-rw-r--r--Zend/tests/002.phpt31
-rw-r--r--Zend/tests/003.phpt24
-rw-r--r--Zend/tests/030.phpt38
-rw-r--r--Zend/tests/add_006.phpt8
-rw-r--r--Zend/tests/add_007.phpt5
-rw-r--r--Zend/tests/anon/013.phpt15
-rw-r--r--Zend/tests/anon/014.phpt16
-rw-r--r--Zend/tests/assert/expect_015.phpt6
-rw-r--r--Zend/tests/assert/indirect_var_access_misoptimization.phpt19
-rw-r--r--Zend/tests/assign_dim_obj_null_return.phpt56
-rw-r--r--Zend/tests/bug29015.phpt11
-rw-r--r--Zend/tests/bug29368_1.phpt29
-rw-r--r--Zend/tests/bug29883.phpt2
-rw-r--r--Zend/tests/bug31098.phpt2
-rw-r--r--Zend/tests/bug33996.phpt22
-rw-r--r--Zend/tests/bug38047.phpt10
-rw-r--r--Zend/tests/bug41813.phpt2
-rw-r--r--Zend/tests/bug49866.phpt2
-rw-r--r--Zend/tests/bug52484.phpt6
-rw-r--r--Zend/tests/bug52484_2.phpt6
-rw-r--r--Zend/tests/bug52484_3.phpt6
-rw-r--r--Zend/tests/bug52879.phpt2
-rw-r--r--Zend/tests/bug53432.phpt65
-rw-r--r--Zend/tests/bug55705.phpt2
-rw-r--r--Zend/tests/bug62814.phpt20
-rw-r--r--Zend/tests/bug63734.phpt2
-rw-r--r--Zend/tests/bug65784.phpt11
-rw-r--r--Zend/tests/bug68370.phpt4
-rw-r--r--Zend/tests/bug68652.phpt1
-rw-r--r--Zend/tests/bug69446.phpt2
-rw-r--r--Zend/tests/bug69446_2.phpt2
-rw-r--r--Zend/tests/bug69534.phpt2
-rw-r--r--Zend/tests/bug69676_2.phpt22
-rw-r--r--Zend/tests/bug69676_3.phpt69
-rw-r--r--Zend/tests/bug69989_2.phpt42
-rw-r--r--Zend/tests/bug69989_3.phpt44
-rw-r--r--Zend/tests/bug70089.phpt2
-rw-r--r--Zend/tests/bug70685.phpt2
-rw-r--r--Zend/tests/bug70689.phpt6
-rw-r--r--Zend/tests/bug70805_1.phpt2
-rw-r--r--Zend/tests/bug70805_2.phpt2
-rw-r--r--Zend/tests/bug70918.phpt47
-rw-r--r--Zend/tests/bug71196.phpt13
-rw-r--r--Zend/tests/bug71266.phpt22
-rw-r--r--Zend/tests/bug71428.1.phpt4
-rw-r--r--Zend/tests/bug71428.3.phpt4
-rw-r--r--Zend/tests/bug71539.phpt16
-rw-r--r--Zend/tests/bug71539_1.phpt30
-rw-r--r--Zend/tests/bug71539_2.phpt30
-rw-r--r--Zend/tests/bug71539_3.phpt19
-rw-r--r--Zend/tests/bug71539_4.phpt19
-rw-r--r--Zend/tests/bug71539_5.phpt19
-rw-r--r--Zend/tests/bug71539_6.phpt15
-rw-r--r--Zend/tests/bug71572.phpt27
-rw-r--r--Zend/tests/bug71818.phpt30
-rw-r--r--Zend/tests/bug72107.phpt14
-rw-r--r--Zend/tests/bug72119.phpt5
-rw-r--r--Zend/tests/bug72162.phpt2
-rw-r--r--Zend/tests/bug72177.phpt35
-rw-r--r--Zend/tests/bug72177_2.phpt34
-rw-r--r--Zend/tests/bug72188.phpt27
-rw-r--r--Zend/tests/bug72215.phpt16
-rw-r--r--Zend/tests/bug72215_1.phpt21
-rw-r--r--Zend/tests/bug72215_2.phpt22
-rw-r--r--Zend/tests/bug72215_3.phpt15
-rw-r--r--Zend/tests/bug72216.phpt16
-rw-r--r--Zend/tests/bug72221.phpt11
-rw-r--r--Zend/tests/bug72335.phpt18
-rw-r--r--Zend/tests/bug72347.phpt17
-rw-r--r--Zend/tests/bug72373.phpt20
-rw-r--r--Zend/tests/bug72395.phpt10
-rw-r--r--Zend/tests/bug72441.phpt14
-rw-r--r--Zend/tests/bug72543.phpt39
-rw-r--r--Zend/tests/bug72543_1.phpt19
-rw-r--r--Zend/tests/bug72543_2.phpt19
-rw-r--r--Zend/tests/bug72543_3.phpt12
-rw-r--r--Zend/tests/bug72543_4.phpt11
-rw-r--r--Zend/tests/bug72543_5.phpt10
-rw-r--r--Zend/tests/bug72598.phpt26
-rw-r--r--Zend/tests/bug72598_2.phpt27
-rw-r--r--Zend/tests/bug72918.phpt22
-rw-r--r--Zend/tests/bug73288.phpt34
-rw-r--r--Zend/tests/bug74093.phpt20
-rw-r--r--Zend/tests/bug74164.phpt20
-rw-r--r--Zend/tests/bug74340.phpt30
-rw-r--r--Zend/tests/bug74862.phpt43
-rw-r--r--Zend/tests/bug74862_2.phpt46
-rw-r--r--Zend/tests/bug75079.phpt39
-rw-r--r--Zend/tests/bug75079_2.phpt36
-rw-r--r--Zend/tests/bug75786.phpt18
-rw-r--r--Zend/tests/bug76025.phpt18
-rw-r--r--Zend/tests/bug76383.phpt13
-rw-r--r--Zend/tests/bug76502.phpt36
-rw-r--r--Zend/tests/bug76534.phpt17
-rw-r--r--Zend/tests/bug76754.phpt18
-rw-r--r--Zend/tests/call_user_func_006.phpt28
-rw-r--r--Zend/tests/call_user_func_008.phpt54
-rw-r--r--Zend/tests/call_user_func_009.phpt17
-rw-r--r--Zend/tests/class_properties_const.phpt2
-rw-r--r--Zend/tests/closure_027.phpt10
-rw-r--r--Zend/tests/closure_061.phpt4
-rw-r--r--Zend/tests/closure_use_auto_global.phpt16
-rw-r--r--Zend/tests/closure_use_parameter_name.phpt14
-rw-r--r--Zend/tests/closure_use_variable_twice.phpt15
-rw-r--r--Zend/tests/closures/closure_from_callable.inc187
-rw-r--r--Zend/tests/closures/closure_from_callable_basic.phpt122
-rw-r--r--Zend/tests/closures/closure_from_callable_error.phpt215
-rw-r--r--Zend/tests/closures/closure_from_callable_lsb.phpt21
-rw-r--r--Zend/tests/closures/closure_from_callable_non_static_statically.phpt20
-rw-r--r--Zend/tests/closures/closure_from_callable_rebinding.phpt20
-rw-r--r--Zend/tests/closures/closure_from_callable_reflection.phpt46
-rw-r--r--Zend/tests/constant_expressions_dynamic.phpt4
-rw-r--r--Zend/tests/constant_expressions_self_referencing_array.phpt2
-rw-r--r--Zend/tests/dynamic_call_005.phpt29
-rw-r--r--Zend/tests/dynamic_call_006.phpt48
-rw-r--r--Zend/tests/dynamic_call_007.phpt17
-rw-r--r--Zend/tests/dynamic_call_008.phpt13
-rw-r--r--Zend/tests/dynamic_call_to_ref_returning_function.phpt39
-rw-r--r--Zend/tests/empty_str_offset.phpt12
-rw-r--r--Zend/tests/entry_block_with_predecessors.phpt33
-rw-r--r--Zend/tests/error_reporting06.phpt2
-rw-r--r--Zend/tests/error_reporting07.phpt2
-rw-r--r--Zend/tests/error_reporting08.phpt2
-rw-r--r--Zend/tests/exception_009.phpt2
-rw-r--r--Zend/tests/foreach_list_keyed.phpt36
-rw-r--r--Zend/tests/fr47160.phpt34
-rw-r--r--Zend/tests/func_get_args.phpt10
-rw-r--r--Zend/tests/function_arguments/argument_count_correct.phpt20
-rw-r--r--Zend/tests/function_arguments/argument_count_correct_strict.phpt20
-rw-r--r--Zend/tests/function_arguments/argument_count_incorrect_internal.phpt10
-rw-r--r--Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt18
-rw-r--r--Zend/tests/function_arguments/argument_count_incorrect_userland.phpt44
-rw-r--r--Zend/tests/function_arguments/argument_count_incorrect_userland_strict.phpt54
-rw-r--r--Zend/tests/gc_013.phpt4
-rw-r--r--Zend/tests/gc_014.phpt4
-rw-r--r--Zend/tests/gc_015.phpt4
-rw-r--r--Zend/tests/gc_017.phpt5
-rw-r--r--Zend/tests/gc_033.phpt2
-rw-r--r--Zend/tests/gc_035.phpt2
-rw-r--r--Zend/tests/generators/bug72523.phpt15
-rw-r--r--Zend/tests/generators/bug74157.phpt23
-rw-r--r--Zend/tests/generators/bug74606.phpt29
-rw-r--r--Zend/tests/generators/bug75396.phpt22
-rw-r--r--Zend/tests/generators/gc_with_root_parent_mismatch.phpt27
-rw-r--r--Zend/tests/generators/gc_with_yield_from.phpt47
-rw-r--r--Zend/tests/generators/generator_with_arg_unpacking.phpt12
-rw-r--r--Zend/tests/generators/generator_with_type_check.phpt13
-rw-r--r--Zend/tests/generators/generator_with_type_check_2.phpt22
-rw-r--r--Zend/tests/generators/return_from_by_ref_generator.phpt20
-rw-r--r--Zend/tests/generators/yield_from_iterator_agregate.phpt17
-rw-r--r--Zend/tests/global_with_side_effect_name.phpt22
-rw-r--r--Zend/tests/incompat_ctx_user.phpt11
-rw-r--r--Zend/tests/indexing_001.phpt41
-rw-r--r--Zend/tests/indirect_call_array_003.phpt11
-rw-r--r--Zend/tests/inference_infinite_loop.phpt17
-rw-r--r--Zend/tests/instanceof_001.phpt2
-rw-r--r--Zend/tests/int_conversion_exponents.phpt52
-rw-r--r--Zend/tests/isset_str_offset.phpt6
-rw-r--r--Zend/tests/jump16.phpt27
-rw-r--r--Zend/tests/jump17.phpt22
-rw-r--r--Zend/tests/list_001.phpt6
-rw-r--r--Zend/tests/list_008.phpt10
-rw-r--r--Zend/tests/list_009.phpt14
-rw-r--r--Zend/tests/list_010.phpt11
-rw-r--r--Zend/tests/list_011.phpt10
-rw-r--r--Zend/tests/list_012.phpt10
-rw-r--r--Zend/tests/list_013.phpt10
-rw-r--r--Zend/tests/list_014.phpt11
-rw-r--r--Zend/tests/list_empty_error_keyed.phpt11
-rw-r--r--Zend/tests/list_keyed.phpt71
-rw-r--r--Zend/tests/list_keyed_ArrayAccess.phpt54
-rw-r--r--Zend/tests/list_keyed_conversions.phpt34
-rw-r--r--Zend/tests/list_keyed_evaluation_order.inc60
-rw-r--r--Zend/tests/list_keyed_evaluation_order.phpt35
-rw-r--r--Zend/tests/list_keyed_evaluation_order_2.phpt77
-rw-r--r--Zend/tests/list_keyed_evaluation_order_3.phpt24
-rw-r--r--Zend/tests/list_keyed_evaluation_order_nested.phpt77
-rw-r--r--Zend/tests/list_keyed_non_literals.phpt30
-rw-r--r--Zend/tests/list_keyed_trailing_comma.phpt38
-rw-r--r--Zend/tests/list_keyed_undefined.phpt22
-rw-r--r--Zend/tests/list_mixed_keyed_unkeyed.phpt16
-rw-r--r--Zend/tests/list_mixed_nested_keyed_unkeyed.phpt34
-rw-r--r--Zend/tests/method_argument_binding.phpt46
-rw-r--r--Zend/tests/neg_num_string.phpt47
-rw-r--r--Zend/tests/new_args_without_ctor.phpt10
-rw-r--r--Zend/tests/ns_071.phpt2
-rw-r--r--Zend/tests/ns_072.phpt2
-rw-r--r--Zend/tests/nullable_types/array.phpt17
-rw-r--r--Zend/tests/nullable_types/contravariant_nullable_param_succeeds.phpt19
-rw-r--r--Zend/tests/nullable_types/contravariant_nullable_return_fails.phpt17
-rw-r--r--Zend/tests/nullable_types/covariant_nullable_param_fails.phpt17
-rw-r--r--Zend/tests/nullable_types/covariant_nullable_return_succeds.phpt16
-rw-r--r--Zend/tests/nullable_types/float.phpt16
-rw-r--r--Zend/tests/nullable_types/int.phpt16
-rw-r--r--Zend/tests/nullable_types/invariant_param_and_return_succeeds.phpt24
-rw-r--r--Zend/tests/nullable_types/nullable_type_parameters_do_not_have_default_value.phpt17
-rw-r--r--Zend/tests/nullable_types/string.phpt16
-rw-r--r--Zend/tests/numeric_string_errors.phpt195
-rw-r--r--Zend/tests/numeric_string_errors_assign.phpt236
-rw-r--r--Zend/tests/objects_022.phpt2
-rw-r--r--Zend/tests/oct_overflow_char.phpt10
-rw-r--r--Zend/tests/overloaded_func_001.phpt15
-rw-r--r--Zend/tests/overloaded_func_002.phpt13
-rw-r--r--Zend/tests/parse_str_with_unpack.phpt15
-rw-r--r--Zend/tests/php_errormsg_misoptimization.phpt20
-rw-r--r--Zend/tests/return_types/029.phpt9
-rw-r--r--Zend/tests/return_types/030.phpt23
-rw-r--r--Zend/tests/return_types/031.phpt14
-rw-r--r--Zend/tests/return_types/032.phpt14
-rw-r--r--Zend/tests/return_types/bug71092.phpt4
-rw-r--r--Zend/tests/return_types/generators002.phpt2
-rw-r--r--Zend/tests/return_types/void_allowed.phpt20
-rw-r--r--Zend/tests/return_types/void_disallowed1.phpt12
-rw-r--r--Zend/tests/return_types/void_disallowed2.phpt12
-rw-r--r--Zend/tests/return_types/void_parameter.phpt8
-rw-r--r--Zend/tests/self_and.phpt4
-rw-r--r--Zend/tests/self_instanceof_outside_class.phpt17
-rw-r--r--Zend/tests/self_method_or_prop_outside_class.phpt36
-rw-r--r--Zend/tests/self_mod.phpt4
-rw-r--r--Zend/tests/self_or.phpt4
-rw-r--r--Zend/tests/self_xor.phpt4
-rw-r--r--Zend/tests/shift_001.phpt4
-rw-r--r--Zend/tests/shift_002.phpt4
-rw-r--r--Zend/tests/str_offset_001.phpt97
-rw-r--r--Zend/tests/str_offset_003.phpt37
-rw-r--r--Zend/tests/str_offset_004.phpt49
-rw-r--r--Zend/tests/string_offset_errors.phpt27
-rw-r--r--Zend/tests/temporary_cleaning_001.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_003.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_004.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_005.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_006.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_008.phpt15
-rw-r--r--Zend/tests/temporary_cleaning_009.phpt27
-rw-r--r--Zend/tests/temporary_cleaning_010.phpt21
-rw-r--r--Zend/tests/temporary_cleaning_011.phpt20
-rw-r--r--Zend/tests/temporary_cleaning_012.phpt20
-rw-r--r--Zend/tests/this_as_global.phpt12
-rw-r--r--Zend/tests/this_as_parameter.phpt11
-rw-r--r--Zend/tests/this_as_static.phpt12
-rw-r--r--Zend/tests/this_in_catch.phpt18
-rw-r--r--Zend/tests/this_in_extract.phpt17
-rw-r--r--Zend/tests/this_in_foreach_001.phpt11
-rw-r--r--Zend/tests/this_in_foreach_002.phpt11
-rw-r--r--Zend/tests/this_in_foreach_003.phpt11
-rw-r--r--Zend/tests/this_in_foreach_004.phpt11
-rw-r--r--Zend/tests/this_in_isset.phpt41
-rw-r--r--Zend/tests/this_in_mb_parse_str.phpt19
-rw-r--r--Zend/tests/this_in_parse_str.phpt17
-rw-r--r--Zend/tests/this_in_unset.phpt8
-rw-r--r--Zend/tests/this_reassign.phpt17
-rw-r--r--Zend/tests/traits/no_static_arg_binding.phpt28
-rw-r--r--Zend/tests/try/bug70228.phpt6
-rw-r--r--Zend/tests/try/bug70228_2.phpt20
-rw-r--r--Zend/tests/try/bug70228_3.phpt31
-rw-r--r--Zend/tests/try/bug70228_4.phpt32
-rw-r--r--Zend/tests/try/bug70228_5.phpt20
-rw-r--r--Zend/tests/try/bug70228_6.phpt18
-rw-r--r--Zend/tests/try/bug70228_7.phpt29
-rw-r--r--Zend/tests/try/bug70228_8.phpt30
-rw-r--r--Zend/tests/try/bug71604.phpt25
-rw-r--r--Zend/tests/try/bug71604_2.phpt39
-rw-r--r--Zend/tests/try/bug71604_3.phpt38
-rw-r--r--Zend/tests/try/bug72213.phpt25
-rw-r--r--Zend/tests/try/bug72213_2.phpt25
-rw-r--r--Zend/tests/try/bug74444.phpt77
-rw-r--r--Zend/tests/try/exceptions.inc6
-rw-r--r--Zend/tests/try/try_finally_021.phpt20
-rw-r--r--Zend/tests/try/try_finally_022.phpt41
-rw-r--r--Zend/tests/try/try_finally_023.phpt37
-rw-r--r--Zend/tests/try/try_finally_024.phpt38
-rw-r--r--Zend/tests/try/try_finally_025.phpt28
-rw-r--r--Zend/tests/try/try_finally_026.phpt37
-rw-r--r--Zend/tests/try/try_finally_027.phpt34
-rw-r--r--Zend/tests/try/try_multicatch_001.phpt19
-rw-r--r--Zend/tests/try/try_multicatch_002.phpt21
-rw-r--r--Zend/tests/try/try_multicatch_003.phpt21
-rw-r--r--Zend/tests/try/try_multicatch_004.phpt21
-rw-r--r--Zend/tests/try/try_multicatch_005.phpt25
-rw-r--r--Zend/tests/try/try_multicatch_006.phpt22
-rw-r--r--Zend/tests/try/try_multicatch_007.phpt22
-rw-r--r--Zend/tests/type_declarations/iterable_001.phpt48
-rw-r--r--Zend/tests/type_declarations/iterable_002.phpt21
-rw-r--r--Zend/tests/type_declarations/iterable_003.phpt32
-rw-r--r--Zend/tests/type_declarations/iterable_004.phpt25
-rw-r--r--Zend/tests/type_declarations/iterable_005.phpt33
-rw-r--r--Zend/tests/type_declarations/nullable_typed_return_without_value.phpt14
-rw-r--r--Zend/tests/type_declarations/nullable_void.phpt11
-rw-r--r--Zend/tests/type_declarations/scalar_none.phpt10
-rw-r--r--Zend/tests/type_declarations/typed_return_without_value.phpt14
-rw-r--r--Zend/tests/typehints/fq_nullable.phpt13
-rw-r--r--Zend/tests/typehints/or_null.phpt317
-rw-r--r--Zend/tests/variadic/adding_additional_optional_parameter_error.phpt2
294 files changed, 6803 insertions, 286 deletions
diff --git a/Zend/tests/001.phpt b/Zend/tests/001.phpt
index bec7d8adbc..bbd4ea3ece 100644
--- a/Zend/tests/001.phpt
+++ b/Zend/tests/001.phpt
@@ -17,11 +17,20 @@ function test3($a, $b) {
test1();
test2(1);
-test2();
+try {
+ test2();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
+
test3(1,2);
call_user_func("test1");
-call_user_func("test3", 1);
+try {
+ call_user_func("test3", 1);
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
call_user_func("test3", 1, 2);
class test {
@@ -38,14 +47,10 @@ echo "Done\n";
--EXPECTF--
int(0)
int(1)
-
-Warning: Missing argument 1 for test2(), called in %s on line %d
-int(0)
+Exception: Too few arguments to function test2(), 0 passed in %s001.php on line 18 and exactly 1 expected
int(2)
int(0)
-
-Warning: Missing argument 2 for test3()%s
-int(1)
+Exception: Too few arguments to function test3(), 1 passed in %s001.php on line 27 and exactly 2 expected
int(2)
int(1)
diff --git a/Zend/tests/002.phpt b/Zend/tests/002.phpt
index b01c7fa329..1728330c08 100644
--- a/Zend/tests/002.phpt
+++ b/Zend/tests/002.phpt
@@ -23,11 +23,19 @@ function test3($a, $b) {
test1();
test1(10);
test2(1);
-test2();
+try {
+ test2();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
test3(1,2);
call_user_func("test1");
-call_user_func("test3", 1);
+try {
+ call_user_func("test3", 1);
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
call_user_func("test3", 1, 2);
class test {
@@ -62,14 +70,7 @@ int(1)
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
bool(false)
-
-Warning: Missing argument 1 for test2(), called in %s on line %d and defined in %s on line %d
-
-Warning: func_get_arg(): Argument 0 not passed to function in %s on line %d
-bool(false)
-
-Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
-bool(false)
+Exception: Too few arguments to function test2(), 0 passed in %s002.php on line %d and exactly 1 expected
int(1)
int(2)
@@ -84,15 +85,7 @@ bool(false)
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
bool(false)
-
-Warning: Missing argument 2 for test3()%s
-int(1)
-
-Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
-bool(false)
-
-Warning: func_get_arg(): Argument 2 not passed to function in %s on line %d
-bool(false)
+Exception: Too few arguments to function test3(), 1 passed in %s002.php on line %d and exactly 2 expected
int(1)
int(2)
diff --git a/Zend/tests/003.phpt b/Zend/tests/003.phpt
index 5c3b83d25e..91daa705d3 100644
--- a/Zend/tests/003.phpt
+++ b/Zend/tests/003.phpt
@@ -18,11 +18,19 @@ function test3($a, $b) {
test1();
test1(10);
test2(1);
-test2();
+try {
+ test2();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
test3(1,2);
call_user_func("test1");
-call_user_func("test3", 1);
+try {
+ call_user_func("test3", 1);
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
call_user_func("test3", 1, 2);
class test {
@@ -47,10 +55,7 @@ array(1) {
[0]=>
int(1)
}
-
-Warning: Missing argument 1 for test2(), called in %s on line %d and defined in %s on line %d
-array(0) {
-}
+Exception: Too few arguments to function test2(), 0 passed in %s003.php on line %d and exactly 1 expected
array(2) {
[0]=>
int(1)
@@ -59,12 +64,7 @@ array(2) {
}
array(0) {
}
-
-Warning: Missing argument 2 for test3()%s
-array(1) {
- [0]=>
- int(1)
-}
+Exception: Too few arguments to function test3(), 1 passed in %s003.php on line %d and exactly 2 expected
array(2) {
[0]=>
int(1)
diff --git a/Zend/tests/030.phpt b/Zend/tests/030.phpt
index 8afcb66bd8..2318420319 100644
--- a/Zend/tests/030.phpt
+++ b/Zend/tests/030.phpt
@@ -31,40 +31,4 @@ $test->bar();
?>
--EXPECTF--
-object(Exception)#%d (7) {
- ["message":protected]=>
- string(3) "foo"
- ["string":"Exception":private]=>
- string(0) ""
- ["code":protected]=>
- int(0)
- ["file":protected]=>
- string(%d) "%s030.php"
- ["line":protected]=>
- int(%d)
- ["trace":"Exception":private]=>
- array(1) {
- [0]=>
- array(6) {
- ["file"]=>
- string(%d) "%s030.php"
- ["line"]=>
- int(%d)
- ["function"]=>
- string(3) "bar"
- ["class"]=>
- string(3) "foo"
- ["type"]=>
- string(2) "->"
- ["args"]=>
- array(0) {
- }
- }
- }
- ["previous":"Exception":private]=>
- NULL
-}
-'test' => '0'
-'test_2' => '1'
-'test_3' => '2'
-ok
+Fatal error: Cannot re-assign $this in %s030.php on line 11
diff --git a/Zend/tests/add_006.phpt b/Zend/tests/add_006.phpt
index d56df2f329..fe1c0830e2 100644
--- a/Zend/tests/add_006.phpt
+++ b/Zend/tests/add_006.phpt
@@ -38,11 +38,19 @@ var_dump($c);
echo "Done\n";
?>
--EXPECTF--
+
+Warning: A non-numeric value encountered in %s on line %d
int(75636)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(951858)
int(48550510)
float(75661.68)
+
+Warning: A non-numeric value encountered in %s on line %d
int(75636)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(951858)
int(48550510)
float(75661.68)
diff --git a/Zend/tests/add_007.phpt b/Zend/tests/add_007.phpt
index 66f5405706..089b24ae0b 100644
--- a/Zend/tests/add_007.phpt
+++ b/Zend/tests/add_007.phpt
@@ -19,8 +19,13 @@ var_dump($c);
echo "Done\n";
?>
--EXPECTF--
+
+Warning: A non-numeric value encountered in %s on line %d
+
Exception: Unsupported operand types
+Warning: A non-numeric value encountered in %s on line %d
+
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
Stack trace:
#0 {main}
diff --git a/Zend/tests/anon/013.phpt b/Zend/tests/anon/013.phpt
new file mode 100644
index 0000000000..72ba3d61b7
--- /dev/null
+++ b/Zend/tests/anon/013.phpt
@@ -0,0 +1,15 @@
+--TEST--
+closure binding to anonymous class
+--FILE--
+<?php
+$class = new class {};
+$foo = function() {
+ return $this;
+};
+
+$closure = Closure::bind($foo, $class, $class);
+var_dump($closure());
+?>
+--EXPECTF--
+object(class@anonymous)#1 (0) {
+}
diff --git a/Zend/tests/anon/014.phpt b/Zend/tests/anon/014.phpt
new file mode 100644
index 0000000000..cacac47857
--- /dev/null
+++ b/Zend/tests/anon/014.phpt
@@ -0,0 +1,16 @@
+--TEST--
+anonymous class trait binding
+--FILE--
+<?php
+trait TaskTrait {
+ function run() {
+ return 'Running...';
+ }
+}
+$class = new class() {
+ use TaskTrait;
+};
+var_dump($class->run());
+?>
+--EXPECTF--
+string(10) "Running..."
diff --git a/Zend/tests/assert/expect_015.phpt b/Zend/tests/assert/expect_015.phpt
index 030913f7f9..1679640851 100644
--- a/Zend/tests/assert/expect_015.phpt
+++ b/Zend/tests/assert/expect_015.phpt
@@ -20,7 +20,7 @@ assert(0 && ($a = function () {
yield from $x;
}));
-assert(0 && ($a = function &(array &$a, X $b = null) use ($c,&$d) : X {
+assert(0 && ($a = function &(array &$a, ?X $b = null) use ($c,&$d) : ?X {
abstract class A extends B implements C, D {
const X = 12;
const Y = self::X, Z = "aaa";
@@ -154,14 +154,14 @@ Warning: assert(): assert(0 && ($a = function () {
$x = $a ? $b : $c;
$x = $a ?: $c;
$x = $a ?? $b;
- list($a, $b, $c) = [1, 2 => 'x', 'z' => 'c'];
+ [$a, $b, $c] = [1, 2 => 'x', 'z' => 'c'];
@foo();
$y = clone $x;
yield 1 => 2;
yield from $x;
})) failed in %sexpect_015.php on line %d
-Warning: assert(): assert(0 && ($a = function &(array &$a, X $b = null) use($c, &$d): X {
+Warning: assert(): assert(0 && ($a = function &(array &$a, ?X $b = null) use($c, &$d): ?X {
abstract class A extends B implements C, D {
const X = 12;
const Y = self::X, Z = 'aaa';
diff --git a/Zend/tests/assert/indirect_var_access_misoptimization.phpt b/Zend/tests/assert/indirect_var_access_misoptimization.phpt
new file mode 100644
index 0000000000..61c193ab60
--- /dev/null
+++ b/Zend/tests/assert/indirect_var_access_misoptimization.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Misoptimization when variable is modified by assert()
+--INI--
+zend.assertions=1
+--FILE--
+<?php
+
+function test() {
+ $i = 0;
+ assert('$i = new stdClass');
+ $i += 1;
+ var_dump($i);
+}
+test();
+
+?>
+--EXPECTF--
+Notice: Object of class stdClass could not be converted to int in %s on line %d
+int(2)
diff --git a/Zend/tests/assign_dim_obj_null_return.phpt b/Zend/tests/assign_dim_obj_null_return.phpt
new file mode 100644
index 0000000000..e833ef3591
--- /dev/null
+++ b/Zend/tests/assign_dim_obj_null_return.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Various null return conditions of dim/obj assignments
+--FILE--
+<?php
+
+function test() {
+ $array = [PHP_INT_MAX => 42];
+ $true = true;
+
+ var_dump($array[] = 123);
+ var_dump($array[[]] = 123);
+ var_dump($array[new stdClass] = 123);
+ var_dump($true[123] = 456);
+
+ var_dump($array[] += 123);
+ var_dump($array[[]] += 123);
+ var_dump($array[new stdClass] += 123);
+ var_dump($true[123] += 456);
+
+ var_dump($true->foo = 123);
+ var_dump($true->foo += 123);
+}
+
+test();
+
+?>
+--EXPECTF--
+Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
+NULL
+
+Warning: Illegal offset type in %s on line %d
+NULL
+
+Warning: Illegal offset type in %s on line %d
+NULL
+
+Warning: Cannot use a scalar value as an array in %s on line %d
+NULL
+
+Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
+NULL
+
+Warning: Illegal offset type in %s on line %d
+NULL
+
+Warning: Illegal offset type in %s on line %d
+NULL
+
+Warning: Cannot use a scalar value as an array in %s on line %d
+NULL
+
+Warning: Attempt to assign property of non-object in %s on line %d
+NULL
+
+Warning: Attempt to assign property of non-object in %s on line %d
+NULL
diff --git a/Zend/tests/bug29015.phpt b/Zend/tests/bug29015.phpt
index a36ed923f3..d4231d10b1 100644
--- a/Zend/tests/bug29015.phpt
+++ b/Zend/tests/bug29015.phpt
@@ -6,9 +6,16 @@ $a = new stdClass();
$x = "";
$a->$x = "string('')";
var_dump($a);
+$a->{"\0"} = 42;
+var_dump($a);
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot access empty property in %sbug29015.php:4
+object(stdClass)#1 (1) {
+ [""]=>
+ string(10) "string('')"
+}
+
+Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
#0 {main}
- thrown in %sbug29015.php on line 4
+ thrown in %s on line %d
diff --git a/Zend/tests/bug29368_1.phpt b/Zend/tests/bug29368_1.phpt
new file mode 100644
index 0000000000..09cf334384
--- /dev/null
+++ b/Zend/tests/bug29368_1.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #29368.1 (The destructor is called when an exception is thrown from the constructor).
+--FILE--
+<?php
+function throwme($arg)
+{
+ throw new Exception;
+}
+
+class foo {
+ function __construct() {
+ echo "Inside constructor\n";
+ throwme($this);
+ }
+
+ function __destruct() {
+ echo "Inside destructor\n";
+ }
+}
+
+try {
+ $bar = new foo;
+} catch(Exception $exc) {
+ echo "Caught exception!\n";
+}
+?>
+--EXPECT--
+Inside constructor
+Caught exception!
diff --git a/Zend/tests/bug29883.phpt b/Zend/tests/bug29883.phpt
index c92f147ff7..b6ad99aeaf 100644
--- a/Zend/tests/bug29883.phpt
+++ b/Zend/tests/bug29883.phpt
@@ -3,7 +3,7 @@ Bug #29883 (isset gives invalid values on strings)
--FILE--
<?php
$x = "bug";
-var_dump(isset($x[-1]));
+var_dump(isset($x[-10]));
var_dump(isset($x["1"]));
echo $x["1"]."\n";
?>
diff --git a/Zend/tests/bug31098.phpt b/Zend/tests/bug31098.phpt
index 23cec9bbf4..31823a1aa5 100644
--- a/Zend/tests/bug31098.phpt
+++ b/Zend/tests/bug31098.phpt
@@ -18,7 +18,7 @@ var_dump(isset($a['b']));
$simpleString = "Bogus String Text";
echo isset($simpleString->wrong)?"bug\n":"ok\n";
echo isset($simpleString["wrong"])?"bug\n":"ok\n";
-echo isset($simpleString[-1])?"bug\n":"ok\n";
+echo isset($simpleString[-20])?"bug\n":"ok\n";
echo isset($simpleString[0])?"ok\n":"bug\n";
echo isset($simpleString["0"])?"ok\n":"bug\n";
echo isset($simpleString["16"])?"ok\n":"bug\n";
diff --git a/Zend/tests/bug33996.phpt b/Zend/tests/bug33996.phpt
index c399ee9975..3936eb8845 100644
--- a/Zend/tests/bug33996.phpt
+++ b/Zend/tests/bug33996.phpt
@@ -19,15 +19,19 @@ function NormalTest($a)
echo "Hi!";
}
-NormalTest();
-FooTest();
+try {
+ NormalTest();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
+try {
+ FooTest();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
FooTest(new Foo());
?>
--EXPECTF--
-Warning: Missing argument 1 for NormalTest(), called in %sbug33996.php on line %d and defined in %sbug33996.php on line %d
-Hi!
-Fatal error: Uncaught TypeError: Argument 1 passed to FooTest() must be an instance of Foo, none given, called in %sbug33996.php on line %d and defined in %sbug33996.php:%d
-Stack trace:
-#0 %s(%d): FooTest()
-#1 {main}
- thrown in %sbug33996.php on line %d
+Exception: Too few arguments to function NormalTest(), 0 passed in %sbug33996.php on line 18 and exactly 1 expected
+Exception: Too few arguments to function FooTest(), 0 passed in %sbug33996.php on line 23 and exactly 1 expected
+Hello!
diff --git a/Zend/tests/bug38047.phpt b/Zend/tests/bug38047.phpt
index 5e7b3efc94..e6eeb6631d 100644
--- a/Zend/tests/bug38047.phpt
+++ b/Zend/tests/bug38047.phpt
@@ -43,7 +43,9 @@ Non-static method A::A_ftk() should not be called statically
1 %sbug38047.php:13 get_error_context()
2 %sbug38047.php:36 kalus_error_handler()
-Missing argument 1 for A::A_ftk(), called in %sbug38047.php on line 36 and defined
-1 %sbug38047.php:13 get_error_context()
-2 %sbug38047.php:7 kalus_error_handler()
-3 %sbug38047.php:36 A_ftk()
+
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7
+Stack trace:
+#0 %sbug38047.php(36): A::A_ftk()
+#1 {main}
+ thrown in %sbug38047.php on line 7
diff --git a/Zend/tests/bug41813.phpt b/Zend/tests/bug41813.phpt
index 0bb693075a..9a609d09c8 100644
--- a/Zend/tests/bug41813.phpt
+++ b/Zend/tests/bug41813.phpt
@@ -9,7 +9,7 @@ $foo[0]->bar = "xyz";
echo "Done\n";
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot use string offset as an array in %s:%d
+Fatal error: Uncaught Error: Cannot use string offset as an object in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
diff --git a/Zend/tests/bug49866.phpt b/Zend/tests/bug49866.phpt
index 3d96a59cd5..0b7c224c01 100644
--- a/Zend/tests/bug49866.phpt
+++ b/Zend/tests/bug49866.phpt
@@ -7,7 +7,7 @@ $b = &$a[1];
$b = "f";
echo $a;
--EXPECTF--
-Fatal error: Uncaught Error: Cannot create references to/from string offsets nor overloaded objects in %sbug49866.php:3
+Fatal error: Uncaught Error: Cannot create references to/from string offsets in %sbug49866.php:3
Stack trace:
#0 {main}
thrown in %sbug49866.php on line 3
diff --git a/Zend/tests/bug52484.phpt b/Zend/tests/bug52484.phpt
index 053529614d..1d2c2d7cdc 100644
--- a/Zend/tests/bug52484.phpt
+++ b/Zend/tests/bug52484.phpt
@@ -10,14 +10,14 @@ class A {
}
$a = new A();
-$prop = null;
+$prop = "\0";
unset($a->$prop);
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot access empty property in %s:%d
+Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
-#0 %s(%d): A->__unset('')
+#0 %s(%d): A->__unset('\x00')
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/bug52484_2.phpt b/Zend/tests/bug52484_2.phpt
index 6bb927535c..3b12950c66 100644
--- a/Zend/tests/bug52484_2.phpt
+++ b/Zend/tests/bug52484_2.phpt
@@ -10,14 +10,14 @@ class A {
}
$a = new A();
-$prop = null;
+$prop = "\0";
$a->$prop = 2;
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot access empty property in %s:%d
+Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
-#0 %s(%d): A->__set('', 2)
+#0 %s(%d): A->__set('\x00', 2)
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/bug52484_3.phpt b/Zend/tests/bug52484_3.phpt
index af32bc9be7..408dd453fd 100644
--- a/Zend/tests/bug52484_3.phpt
+++ b/Zend/tests/bug52484_3.phpt
@@ -10,14 +10,14 @@ class A {
}
$a = new A();
-$prop = null;
+$prop = "\0";
var_dump($a->$prop);
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot access empty property in %s:%d
+Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
-#0 %s(%d): A->__get('')
+#0 %s(%d): A->__get('\x00')
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/bug52879.phpt b/Zend/tests/bug52879.phpt
index 0193be4b45..6c3232f32d 100644
--- a/Zend/tests/bug52879.phpt
+++ b/Zend/tests/bug52879.phpt
@@ -8,7 +8,7 @@ class MyClass {
$this->myRef = $value;
}
}
-$myGlobal=new MyClass($myGlobal);
+$myGlobal=new MyClass();
$myGlobal->myRef=&$myGlobal;
$myGlobal->myNonExistentProperty="ok\n";
echo $myGlobal;
diff --git a/Zend/tests/bug53432.phpt b/Zend/tests/bug53432.phpt
new file mode 100644
index 0000000000..83df599313
--- /dev/null
+++ b/Zend/tests/bug53432.phpt
@@ -0,0 +1,65 @@
+--TEST--
+Bug #53432: Assignment via string index access on an empty string converts to array
+--FILE--
+<?php
+
+$str = '';
+var_dump($str[0] = 'a');
+var_dump($str);
+
+$str = '';
+var_dump($str[5] = 'a');
+var_dump($str);
+
+$str = '';
+var_dump($str[-1] = 'a');
+var_dump($str);
+
+$str = '';
+var_dump($str['foo'] = 'a');
+var_dump($str);
+
+$str = '';
+try {
+ var_dump($str[] = 'a');
+} catch (Error $e) {
+ echo "Error: {$e->getMessage()}\n";
+}
+var_dump($str);
+
+$str = '';
+try {
+ var_dump($str[0] += 1);
+} catch (Error $e) {
+ echo "Error: {$e->getMessage()}\n";
+}
+var_dump($str);
+
+$str = '';
+try {
+ var_dump($str[0][0] = 'a');
+} catch (Error $e) {
+ echo "Error: {$e->getMessage()}\n";
+}
+var_dump($str);
+
+?>
+--EXPECTF--
+string(1) "a"
+string(1) "a"
+string(1) "a"
+string(6) " a"
+
+Warning: Illegal string offset: -1 in %s on line %d
+NULL
+string(0) ""
+
+Warning: Illegal string offset 'foo' in %s on line %d
+string(1) "a"
+string(1) "a"
+Error: [] operator not supported for strings
+string(0) ""
+Error: Cannot use assign-op operators with string offsets
+string(0) ""
+Error: Cannot use string offset as an array
+string(0) ""
diff --git a/Zend/tests/bug55705.phpt b/Zend/tests/bug55705.phpt
index f051bca6dc..06811bbc1b 100644
--- a/Zend/tests/bug55705.phpt
+++ b/Zend/tests/bug55705.phpt
@@ -6,7 +6,7 @@ function f(callable $c) {}
f();
?>
--EXPECTF--
-Fatal error: Uncaught TypeError: Argument 1 passed to f() must be callable, none given, called in %s on line 3 and defined in %s:%d
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function f(), 0 passed in %s on line 3 and exactly 1 expected in %s:2
Stack trace:
#0 %s(%d): f()
#1 {main}
diff --git a/Zend/tests/bug62814.phpt b/Zend/tests/bug62814.phpt
new file mode 100644
index 0000000000..6646aa283f
--- /dev/null
+++ b/Zend/tests/bug62814.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #62814: It is possible to stiffen child class members visibility
+--FILE--
+<?php
+
+class A {
+ private function test() { }
+}
+
+class B extends A {
+ protected function test() { }
+}
+
+class C extends B {
+ private function test() { }
+}
+
+?>
+--EXPECTF--
+Fatal error: Access level to C::test() must be protected (as in class B) or weaker in %s on line %d
diff --git a/Zend/tests/bug63734.phpt b/Zend/tests/bug63734.phpt
index 8e5ee6d4ac..b68577d494 100644
--- a/Zend/tests/bug63734.phpt
+++ b/Zend/tests/bug63734.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #63734 (Garbage collector can free zvals that are still referenced)
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
class C {
diff --git a/Zend/tests/bug65784.phpt b/Zend/tests/bug65784.phpt
index c079b3d282..663ea95761 100644
--- a/Zend/tests/bug65784.phpt
+++ b/Zend/tests/bug65784.phpt
@@ -57,8 +57,13 @@ $bar = foo3();
string(9) "not catch"
NULL
-Fatal error: Uncaught Error: Class 'NotExists' not found in %sbug65784.php:%d
+Fatal error: Uncaught Exception: not catched in %sbug65784.php:42
Stack trace:
-#0 %s(%d): foo3()
+#0 %sbug65784.php(52): foo3()
#1 {main}
- thrown in %sbug65784.php on line %d
+
+Next Error: Class 'NotExists' not found in %sbug65784.php:46
+Stack trace:
+#0 %sbug65784.php(52): foo3()
+#1 {main}
+ thrown in %sbug65784.php on line 46
diff --git a/Zend/tests/bug68370.phpt b/Zend/tests/bug68370.phpt
index 25589bf455..73411ca9b9 100644
--- a/Zend/tests/bug68370.phpt
+++ b/Zend/tests/bug68370.phpt
@@ -13,6 +13,4 @@ $x = $c->test();
print_r($x);
unset($c, $x);
--EXPECTF--
-Array
-(
-)
+Fatal error: Cannot unset $this in %sbug68370.php on line 4
diff --git a/Zend/tests/bug68652.phpt b/Zend/tests/bug68652.phpt
index e86312ba63..8e54af2e34 100644
--- a/Zend/tests/bug68652.phpt
+++ b/Zend/tests/bug68652.phpt
@@ -28,6 +28,7 @@ class Bar {
}
public function __destruct() {
+ if (!isset(self::$instance)) return;
Foo::getInstance();
}
}
diff --git a/Zend/tests/bug69446.phpt b/Zend/tests/bug69446.phpt
index b448a2be7d..66595c170c 100644
--- a/Zend/tests/bug69446.phpt
+++ b/Zend/tests/bug69446.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #69446 (GC leak relating to removal of nested data after dtors run)
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
$bar = NULL;
diff --git a/Zend/tests/bug69446_2.phpt b/Zend/tests/bug69446_2.phpt
index 520bd1fe30..b7c6e0e329 100644
--- a/Zend/tests/bug69446_2.phpt
+++ b/Zend/tests/bug69446_2.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #69446 (GC leak relating to removal of nested data after dtors run)
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
$bar = NULL;
diff --git a/Zend/tests/bug69534.phpt b/Zend/tests/bug69534.phpt
index 1f0275485e..adf7b06617 100644
--- a/Zend/tests/bug69534.phpt
+++ b/Zend/tests/bug69534.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #69534 (Cycle leaks through declared properties on internal classes)
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
class Node extends SplObjectStorage {
diff --git a/Zend/tests/bug69676_2.phpt b/Zend/tests/bug69676_2.phpt
new file mode 100644
index 0000000000..6ec3d499e5
--- /dev/null
+++ b/Zend/tests/bug69676_2.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #69676: Resolution of self::FOO in class constants not correct (variation)
+--FILE--
+<?php
+
+class Foo {
+ const A = 'Foo::A';
+ const B = self::A . ' and ' . self::C;
+ const C = 'Foo::C';
+
+}
+
+class Bar extends Foo {
+ const A = 'Bar::A';
+ const C = 'Bar::C';
+}
+
+var_dump(Bar::B);
+
+?>
+--EXPECT--
+string(17) "Foo::A and Foo::C"
diff --git a/Zend/tests/bug69676_3.phpt b/Zend/tests/bug69676_3.phpt
new file mode 100644
index 0000000000..89f0090884
--- /dev/null
+++ b/Zend/tests/bug69676_3.phpt
@@ -0,0 +1,69 @@
+--TEST--
+Bug #69676: Resolution of self::FOO in class constants not correct (variation)
+--FILE--
+<?php
+
+class P {
+ const N = 'P';
+}
+class A extends P {
+ const selfN = self::N;
+ const parentN = parent::N;
+ const N = 'A';
+}
+class B extends A {
+ const N = 'B';
+}
+
+var_dump(B::selfN); // A
+var_dump(B::parentN); // P
+
+class A2 {
+ const selfN = self::N;
+ const N = 'A2';
+}
+class B2 extends A2 {
+ const indSelfN = self::selfN;
+ const N = 'B2';
+}
+class C2 extends B2 {
+ const N = 'C2';
+}
+
+var_dump(C2::indSelfN); // A2
+
+class A3 {
+ const selfN = self::N;
+ const N = 'A3';
+}
+class B3 extends A3 {
+ const exprSelfN = "expr" . self::selfN;
+ const N = 'B3';
+}
+class C3 extends B3 {
+ const N = 'C3';
+}
+
+var_dump(C3::exprSelfN); // exprA3
+
+class A4 {
+ const selfN = self::N;
+ const N = 'A4';
+}
+class B4 extends A4 {
+ const N = 'B4';
+ public $prop = self::selfN;
+}
+class C4 extends B4 {
+ const N = 'C4';
+}
+
+var_dump((new C4)->prop); // A4
+
+?>
+--EXPECT--
+string(1) "A"
+string(1) "P"
+string(2) "A2"
+string(6) "exprA3"
+string(2) "A4"
diff --git a/Zend/tests/bug69989_2.phpt b/Zend/tests/bug69989_2.phpt
new file mode 100644
index 0000000000..a6f320da3b
--- /dev/null
+++ b/Zend/tests/bug69989_2.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Collection of some cycles on unfinished generators
+--FILE--
+<?php
+
+// CV
+function gen1() {
+ $gen = yield;
+ yield;
+}
+
+$gen = gen1();
+$gen->send($gen);
+
+// This
+class Test {
+ public $gen;
+ public function gen2() {
+ yield;
+ }
+}
+
+$test = new Test;
+$test->gen = $test->gen2();
+
+// Closure object
+$gen3 = (function() use (&$gen3) {
+ yield;
+})();
+
+// Yield from array
+function gen4() {
+ yield from [yield];
+}
+
+$gen = gen4();
+$gen->send($gen);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/bug69989_3.phpt b/Zend/tests/bug69989_3.phpt
new file mode 100644
index 0000000000..260819197b
--- /dev/null
+++ b/Zend/tests/bug69989_3.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Generator cycle collection edge cases
+--FILE--
+<?php
+
+// Extra args
+function gen1() {
+ yield;
+}
+$obj = new stdClass;
+$obj->gen = gen1($obj);
+
+// Symtable
+function gen2() {
+ $varName = 'a';
+ $$varName = yield;
+ yield;
+}
+$gen = gen2();
+$gen->send($gen);
+
+// Symtable indirect
+function gen3() {
+ $varName = 'a';
+ $$varName = 42;
+ $var = yield;
+ yield;
+}
+$gen = gen3();
+$gen->send($gen);
+
+// Yield from root
+function gen4() {
+ yield from yield;
+}
+$gen = gen4();
+$gen2 = gen4($gen);
+$gen2->send([1, 2, 3]);
+$gen->send($gen2);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/bug70089.phpt b/Zend/tests/bug70089.phpt
index c61db00c9e..e1884d9dac 100644
--- a/Zend/tests/bug70089.phpt
+++ b/Zend/tests/bug70089.phpt
@@ -34,4 +34,4 @@ try {
string(36) "Cannot use string offset as an array"
string(27) "Cannot unset string offsets"
string(41) "Only variables can be passed by reference"
-string(64) "Cannot increment/decrement overloaded objects nor string offsets"
+string(41) "Cannot increment/decrement string offsets"
diff --git a/Zend/tests/bug70685.phpt b/Zend/tests/bug70685.phpt
index 7a49ff1825..8ae97f1bf0 100644
--- a/Zend/tests/bug70685.phpt
+++ b/Zend/tests/bug70685.phpt
@@ -15,7 +15,7 @@ var_dump($c);
?>
--EXPECTF--
-Warning: Cannot bind internal method SplDoublyLinkedList::count() to object of class cls in %s on line %d
+Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls in %s on line %d
NULL
Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d
diff --git a/Zend/tests/bug70689.phpt b/Zend/tests/bug70689.phpt
index e3feeed9b0..882dd89b75 100644
--- a/Zend/tests/bug70689.phpt
+++ b/Zend/tests/bug70689.phpt
@@ -19,4 +19,8 @@ try {
?>
--EXPECTF--
-Missing argument 1 for foo(), called in %sbug70689.php on line %d and defined
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function foo(), 0 passed in %sbug70689.php on line 12 and exactly 1 expected in %sbug70689.php:3
+Stack trace:
+#0 %sbug70689.php(12): foo()
+#1 {main}
+ thrown in %sbug70689.php on line 3
diff --git a/Zend/tests/bug70805_1.phpt b/Zend/tests/bug70805_1.phpt
index 0225b4ce82..af57cdb5d9 100644
--- a/Zend/tests/bug70805_1.phpt
+++ b/Zend/tests/bug70805_1.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #70805 (Segmentation faults whilst running Drupal 8 test suite) (Crash)
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
class A {
diff --git a/Zend/tests/bug70805_2.phpt b/Zend/tests/bug70805_2.phpt
index a9b11684f5..c878c83bbc 100644
--- a/Zend/tests/bug70805_2.phpt
+++ b/Zend/tests/bug70805_2.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #70805 (Segmentation faults whilst running Drupal 8 test suite) (Memleak)
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
class A {
diff --git a/Zend/tests/bug70918.phpt b/Zend/tests/bug70918.phpt
new file mode 100644
index 0000000000..81e2192d8a
--- /dev/null
+++ b/Zend/tests/bug70918.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #70918 (Segfault using static outside of class scope)
+--FILE--
+<?php
+try {
+ static::x;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ parent::x;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ self::x;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ new static;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ static::x();
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ static::$i;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+?>
+--EXPECT--
+string(52) "Cannot access static:: when no class scope is active"
+string(52) "Cannot access parent:: when no class scope is active"
+string(50) "Cannot access self:: when no class scope is active"
+string(52) "Cannot access static:: when no class scope is active"
+string(52) "Cannot access static:: when no class scope is active"
+string(52) "Cannot access static:: when no class scope is active"
diff --git a/Zend/tests/bug71196.phpt b/Zend/tests/bug71196.phpt
new file mode 100644
index 0000000000..ca25f9f4fc
--- /dev/null
+++ b/Zend/tests/bug71196.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Bug #71196 (Memory leak with out-of-order live ranges)
+--FILE--
+<?php
+try {
+ $a = "1";
+ [1, (y().$a.$a) . ($a.$a)];
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+?>
+--EXPECT--
+string(30) "Call to undefined function y()"
diff --git a/Zend/tests/bug71266.phpt b/Zend/tests/bug71266.phpt
new file mode 100644
index 0000000000..d67c6f6363
--- /dev/null
+++ b/Zend/tests/bug71266.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #71266 (Missing separation of properties HT in foreach etc)
+--FILE--
+<?php
+$one = 1;
+$two = 2;
+$arr = ['foo' => $one, 'bar' => $two];
+$obj = (object) $arr;
+foreach ($obj as $val) {
+ var_dump($val);
+ $obj->bar = 42;
+}
+
+$arr = ['foo' => $one, 'bar' => $two];
+$obj = (object) $arr;
+next($obj);
+var_dump(current($arr));
+?>
+--EXPECT--
+int(1)
+int(42)
+int(1)
diff --git a/Zend/tests/bug71428.1.phpt b/Zend/tests/bug71428.1.phpt
index fbf342380f..e4d3a22f67 100644
--- a/Zend/tests/bug71428.1.phpt
+++ b/Zend/tests/bug71428.1.phpt
@@ -1,7 +1,5 @@
--TEST--
bug #71428.1: inheritance with null default values
---XFAIL--
-This is a BC break
--FILE--
<?php
class A {
@@ -11,5 +9,5 @@ class B extends A {
public function m(array $a = []) {}
}
--EXPECTF--
-Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(array $a = NULL) in %sbug71428.1.php on line 7
+Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 7
diff --git a/Zend/tests/bug71428.3.phpt b/Zend/tests/bug71428.3.phpt
index 65d397052e..558e87c56e 100644
--- a/Zend/tests/bug71428.3.phpt
+++ b/Zend/tests/bug71428.3.phpt
@@ -1,7 +1,5 @@
--TEST--
bug #71428: Validation type inheritance with = NULL
---XFAIL--
-This is a BC break
--FILE--
<?php
class A { }
@@ -9,5 +7,5 @@ class B { public function m(A $a = NULL, $n) { echo "B.m";} };
class C extends B { public function m(A $a , $n) { echo "C.m";} };
?>
--EXPECTF--
-Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(A $a = NULL, $n) in %sbug71428.3.php on line 4
+Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(?A $a, $n) in %sbug71428.3.php on line 4
diff --git a/Zend/tests/bug71539.phpt b/Zend/tests/bug71539.phpt
new file mode 100644
index 0000000000..16b5ed8358
--- /dev/null
+++ b/Zend/tests/bug71539.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #71539 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$array = [];
+$array[0] =& $array[''];
+$array[0] = 42;
+var_dump($array);
+?>
+--EXPECT--
+array(2) {
+ [""]=>
+ &int(42)
+ [0]=>
+ &int(42)
+}
diff --git a/Zend/tests/bug71539_1.phpt b/Zend/tests/bug71539_1.phpt
new file mode 100644
index 0000000000..935c9155a4
--- /dev/null
+++ b/Zend/tests/bug71539_1.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #71539.1 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$x = (object)['a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5,'f'=>6,'g'=>7];
+$x->h =& $x->i;
+$x->h = 42;
+var_dump($x);
+?>
+--EXPECT--
+object(stdClass)#1 (9) {
+ ["a"]=>
+ int(1)
+ ["b"]=>
+ int(2)
+ ["c"]=>
+ int(3)
+ ["d"]=>
+ int(4)
+ ["e"]=>
+ int(5)
+ ["f"]=>
+ int(6)
+ ["g"]=>
+ int(7)
+ ["i"]=>
+ &int(42)
+ ["h"]=>
+ &int(42)
+}
diff --git a/Zend/tests/bug71539_2.phpt b/Zend/tests/bug71539_2.phpt
new file mode 100644
index 0000000000..380da467fb
--- /dev/null
+++ b/Zend/tests/bug71539_2.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #71539.2 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$a = [0,1,2,3,4,5,6];
+$a[200] =& $a[100];
+$a[100] =42;
+var_dump($a);
+?>
+--EXPECT--
+array(9) {
+ [0]=>
+ int(0)
+ [1]=>
+ int(1)
+ [2]=>
+ int(2)
+ [3]=>
+ int(3)
+ [4]=>
+ int(4)
+ [5]=>
+ int(5)
+ [6]=>
+ int(6)
+ [100]=>
+ &int(42)
+ [200]=>
+ &int(42)
+}
diff --git a/Zend/tests/bug71539_3.phpt b/Zend/tests/bug71539_3.phpt
new file mode 100644
index 0000000000..7212a6de47
--- /dev/null
+++ b/Zend/tests/bug71539_3.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #71539.3 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$array = [];
+$array[0][0] =& $array[''];
+$array[0][0] = 42;
+var_dump($array);
+?>
+--EXPECT--
+array(2) {
+ [""]=>
+ &int(42)
+ [0]=>
+ array(1) {
+ [0]=>
+ &int(42)
+ }
+}
diff --git a/Zend/tests/bug71539_4.phpt b/Zend/tests/bug71539_4.phpt
new file mode 100644
index 0000000000..5b9cee05c1
--- /dev/null
+++ b/Zend/tests/bug71539_4.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #71539.4 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$array = [0=>[]];
+$array[0][0] =& $array[0][''];
+$array[0][0] = 42;
+var_dump($array);
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ array(2) {
+ [""]=>
+ &int(42)
+ [0]=>
+ &int(42)
+ }
+}
diff --git a/Zend/tests/bug71539_5.phpt b/Zend/tests/bug71539_5.phpt
new file mode 100644
index 0000000000..14559bf65e
--- /dev/null
+++ b/Zend/tests/bug71539_5.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #71539.5 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$array = [];
+$array['']->prop =& $array[0];
+$array[0] = 42;
+var_dump($array);
+?>
+--EXPECT--
+array(2) {
+ [0]=>
+ &int(42)
+ [""]=>
+ object(stdClass)#1 (1) {
+ ["prop"]=>
+ &int(42)
+ }
+}
diff --git a/Zend/tests/bug71539_6.phpt b/Zend/tests/bug71539_6.phpt
new file mode 100644
index 0000000000..2bf4f6b1e0
--- /dev/null
+++ b/Zend/tests/bug71539_6.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #71539.5 (Memory error on $arr[$a] =& $arr[$b] if RHS rehashes)
+--FILE--
+<?php
+$name = 'a';
+for ($i = 0; $i < 100000; $i++) {
+ if ($name != 'i') {
+ $$name =& $GLOBALS;
+ }
+ $name++;
+}
+?>
+OK
+--EXPECT--
+OK \ No newline at end of file
diff --git a/Zend/tests/bug71572.phpt b/Zend/tests/bug71572.phpt
new file mode 100644
index 0000000000..4a823ec72f
--- /dev/null
+++ b/Zend/tests/bug71572.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #71572: String offset assignment from an empty string inserts null byte
+--FILE--
+<?php
+
+$str = "abc";
+var_dump($str{0} = "");
+var_dump($str{1} = "");
+var_dump($str{3} = "");
+var_dump($str{10} = "");
+var_dump($str);
+?>
+==DONE==
+--EXPECTF--
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+
+Warning: Cannot assign an empty string to a string offset in %s on line %d
+NULL
+string(3) "abc"
+==DONE== \ No newline at end of file
diff --git a/Zend/tests/bug71818.phpt b/Zend/tests/bug71818.phpt
new file mode 100644
index 0000000000..e09255ddac
--- /dev/null
+++ b/Zend/tests/bug71818.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #71818 (Memory leak when array altered in destructor)
+--INI--
+zend.enable_gc = 1
+--FILE--
+<?php
+class MemoryLeak
+{
+ public function __construct()
+ {
+ $this->things[] = $this;
+ }
+
+ public function __destruct()
+ {
+ $this->things[] = null;
+ }
+
+ private $things = [];
+}
+
+ini_set('memory_limit', '10M');
+
+for ($i = 0; $i < 100000; ++$i) {
+ $obj = new MemoryLeak();
+}
+echo "OK\n";
+?>
+--EXPECT--
+OK
diff --git a/Zend/tests/bug72107.phpt b/Zend/tests/bug72107.phpt
new file mode 100644
index 0000000000..3f4c46cf70
--- /dev/null
+++ b/Zend/tests/bug72107.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #72107: Segfault when using func_get_args as error handler
+--FILE--
+<?php
+set_error_handler('func_get_args');
+function test($a) {
+ echo $undef;
+}
+test(1);
+?>
+--EXPECTF--
+Warning: Cannot call func_get_args() dynamically in %s on line %d
+
+Notice: Undefined variable: undef in %s on line %d
diff --git a/Zend/tests/bug72119.phpt b/Zend/tests/bug72119.phpt
index b8f070a25a..064381ada0 100644
--- a/Zend/tests/bug72119.phpt
+++ b/Zend/tests/bug72119.phpt
@@ -14,5 +14,6 @@ class Hello implements Foo {
}
echo "OK\n";
?>
---EXPECT--
-OK
+--EXPECTF--
+Fatal error: Declaration of Hello::bar(array $baz = Array) must be compatible with Foo::bar(?array $baz = NULL) in %s on line %d
+
diff --git a/Zend/tests/bug72162.phpt b/Zend/tests/bug72162.phpt
index 5902c585d8..493342d838 100644
--- a/Zend/tests/bug72162.phpt
+++ b/Zend/tests/bug72162.phpt
@@ -7,4 +7,4 @@ $var11 = new StdClass();
$var16 = error_reporting($var11);
?>
--EXPECTF--
-Catchable fatal error: Object of class stdClass could not be converted to string in %sbug72162.php on line %d
+Recoverable fatal error: Object of class stdClass could not be converted to string in %sbug72162.php on line %d
diff --git a/Zend/tests/bug72177.phpt b/Zend/tests/bug72177.phpt
new file mode 100644
index 0000000000..b5658d354a
--- /dev/null
+++ b/Zend/tests/bug72177.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
+--FILE--
+<?php
+class Child
+{
+ protected $bar;
+
+ public function __destruct()
+ {
+ $this->bar = null;
+ }
+}
+
+class Parnt
+{
+ protected $child;
+
+ public function doSomething()
+ {
+ $this->child = new Child();
+
+ $prop = new \ReflectionProperty($this, 'child');
+ $prop->setAccessible(true);
+ $prop->setValue($this, null);
+ }
+}
+
+$p = new Parnt();
+$p->doSomething();
+
+echo "OK\n";
+?>
+--EXPECT--
+OK
diff --git a/Zend/tests/bug72177_2.phpt b/Zend/tests/bug72177_2.phpt
new file mode 100644
index 0000000000..718d6c061e
--- /dev/null
+++ b/Zend/tests/bug72177_2.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
+--FILE--
+<?php
+class Foo
+{
+ private $bar = 'bar';
+
+ public function __construct()
+ {
+ unset($this->bar);
+ }
+}
+
+class Bar extends Foo
+{
+ private $baz = 'baz';
+ private static $tab = 'tab';
+
+ public function __get(string $name)
+ {
+ var_dump($this->baz);
+ var_dump(self::$tab);
+ return $name;
+ }
+}
+
+$r = new ReflectionProperty(Foo::class, 'bar');
+
+$r->setAccessible(true);
+echo "OK\n";
+?>
+--EXPECT--
+OK
diff --git a/Zend/tests/bug72188.phpt b/Zend/tests/bug72188.phpt
new file mode 100644
index 0000000000..0deab6b81b
--- /dev/null
+++ b/Zend/tests/bug72188.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #72188 (Nested try/finally blocks losing return value)
+--FILE--
+<?php
+function test() {
+ try {
+ return 5;
+ } finally {
+ try {
+ echo 1;
+ } finally {
+ echo 2;
+ }
+ }
+}
+
+
+
+$a = test();
+if($a !== 5) {
+ echo "FAILED: expected 5, received ", var_export($a), PHP_EOL;
+} else {
+ echo "Passed", PHP_EOL;
+}
+?>
+--EXPECT--
+12Passed
diff --git a/Zend/tests/bug72215.phpt b/Zend/tests/bug72215.phpt
new file mode 100644
index 0000000000..0ff16291ad
--- /dev/null
+++ b/Zend/tests/bug72215.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #72215 (Wrong return value if var modified in finally)
+--FILE--
+<?php
+function test() {
+ $a = 1;
+ try {
+ return $a;
+ } finally {
+ $a = 2;
+ }
+}
+var_dump(test());
+?>
+--EXPECT--
+int(1)
diff --git a/Zend/tests/bug72215_1.phpt b/Zend/tests/bug72215_1.phpt
new file mode 100644
index 0000000000..d56c9f881d
--- /dev/null
+++ b/Zend/tests/bug72215_1.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #72215.1 (Wrong return value if var modified in finally)
+--FILE--
+<?php
+function &test(&$b) {
+ $a =& $b;
+ try {
+ return $a;
+ } finally {
+ $a = 2;
+ }
+}
+$x = 1;
+$y =& test($x);
+var_dump($y);
+$x = 3;
+var_dump($y);
+?>
+--EXPECT--
+int(2)
+int(3)
diff --git a/Zend/tests/bug72215_2.phpt b/Zend/tests/bug72215_2.phpt
new file mode 100644
index 0000000000..cefb6d9632
--- /dev/null
+++ b/Zend/tests/bug72215_2.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #72215.1 (Wrong return value if var modified in finally)
+--FILE--
+<?php
+function &test(&$b) {
+ $a =& $b;
+ try {
+ return $a;
+ } finally {
+ $a =& $c;
+ $a = 2;
+ }
+}
+$x = 1;
+$y =& test($x);
+var_dump($y);
+$x = 3;
+var_dump($y);
+?>
+--EXPECT--
+int(1)
+int(3)
diff --git a/Zend/tests/bug72215_3.phpt b/Zend/tests/bug72215_3.phpt
new file mode 100644
index 0000000000..6f10fd7dee
--- /dev/null
+++ b/Zend/tests/bug72215_3.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #72215.3 (Wrong return value if var modified in finally)
+--FILE--
+<?php
+function &test() {
+ try {
+ return $a;
+ } finally {
+ $a = 2;
+ }
+}
+var_dump(test());
+?>
+--EXPECT--
+int(2)
diff --git a/Zend/tests/bug72216.phpt b/Zend/tests/bug72216.phpt
new file mode 100644
index 0000000000..65b5556c70
--- /dev/null
+++ b/Zend/tests/bug72216.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #72216 (Return by reference with finally is not memory safe)
+--FILE--
+<?php
+function &test() {
+ $a = ["ok"];
+ try {
+ return $a[0];
+ } finally {
+ $a[""] = 42;
+ }
+}
+var_dump(test());
+?>
+--EXPECT--
+string(2) "ok"
diff --git a/Zend/tests/bug72221.phpt b/Zend/tests/bug72221.phpt
new file mode 100644
index 0000000000..8f30099cab
--- /dev/null
+++ b/Zend/tests/bug72221.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #72221 (Segmentation fault in stream_get_line / zend_memnstr_ex)
+--FILE--
+<?php
+$fp = fopen("php://memory", "r+");
+fwrite($fp, str_repeat("baad", 1024*1024));
+rewind($fp);
+stream_get_line($fp, 1024*1024*2, "aaaa");
+echo "Done\n";
+--EXPECT--
+Done
diff --git a/Zend/tests/bug72335.phpt b/Zend/tests/bug72335.phpt
new file mode 100644
index 0000000000..854de34281
--- /dev/null
+++ b/Zend/tests/bug72335.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Misoptimize due to type narrowing
+--FILE--
+<?php
+
+function test() {
+ $b = false;
+ $x = (1<<53)+1;
+ do {
+ $x = 1.0 * ($x - (1<<53));
+ } while ($b);
+ return $x;
+}
+var_dump(test());
+
+?>
+--EXPECT--
+float(1)
diff --git a/Zend/tests/bug72347.phpt b/Zend/tests/bug72347.phpt
new file mode 100644
index 0000000000..b86457207d
--- /dev/null
+++ b/Zend/tests/bug72347.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72347 (VERIFY_RETURN type casts visible in finally)
+--FILE--
+<?php
+function test() : int {
+ $d = 1.5;
+ try {
+ return $d;
+ } finally {
+ var_dump($d);
+ }
+}
+var_dump(test());
+?>
+--EXPECT--
+float(1.5)
+int(1)
diff --git a/Zend/tests/bug72373.phpt b/Zend/tests/bug72373.phpt
new file mode 100644
index 0000000000..67377c5ba7
--- /dev/null
+++ b/Zend/tests/bug72373.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #72373: TypeError after Generator function w/declared return type finishes
+--FILE--
+<?php
+
+function foo() : Generator {
+ yield 1;
+ yield 2;
+ yield 3;
+}
+
+foreach (foo() as $bar) {
+ echo $bar . "\n";
+}
+
+?>
+--EXPECT--
+1
+2
+3
diff --git a/Zend/tests/bug72395.phpt b/Zend/tests/bug72395.phpt
new file mode 100644
index 0000000000..e89ecdd5ad
--- /dev/null
+++ b/Zend/tests/bug72395.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #72395 (list() regression)
+--FILE--
+<?php
+list(,,$a,,$b,) = array(1, 2, 3, 4, 5, 6);
+var_dump($a, $b);
+?>
+--EXPECT--
+int(3)
+int(5)
diff --git a/Zend/tests/bug72441.phpt b/Zend/tests/bug72441.phpt
new file mode 100644
index 0000000000..af57b3adb0
--- /dev/null
+++ b/Zend/tests/bug72441.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #72441 (Segmentation fault: RFC list_keys)
+--FILE--
+<?php
+
+$array = [];
+
+list(
+ '' => $foo,
+ $bar
+) = $array;
+?>
+--EXPECTF--
+Fatal error: Cannot mix keyed and unkeyed array entries in assignments in %sbug72441.php on line %d
diff --git a/Zend/tests/bug72543.phpt b/Zend/tests/bug72543.phpt
new file mode 100644
index 0000000000..4244b8ce41
--- /dev/null
+++ b/Zend/tests/bug72543.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Bug #72543 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+function create_references(&$array) {
+ foreach ($array as $key => $value) {
+ create_references($array[$key]);
+ }
+}
+
+function change_copy($copy) {
+ $copy['b']['z']['z'] = $copy['b'];
+}
+
+$data = [
+ 'a' => [
+ 'b' => [],
+ ],
+];
+
+create_references($data);
+
+$copy = $data['a'];
+var_dump($copy);
+
+change_copy($copy);
+var_dump($copy); //RECURSION
+?>
+--EXPECT--
+array(1) {
+ ["b"]=>
+ array(0) {
+ }
+}
+array(1) {
+ ["b"]=>
+ array(0) {
+ }
+}
diff --git a/Zend/tests/bug72543_1.phpt b/Zend/tests/bug72543_1.phpt
new file mode 100644
index 0000000000..f63ee7f14b
--- /dev/null
+++ b/Zend/tests/bug72543_1.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #72543.1 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [];
+$arr[0] = null;
+$ref =& $arr[0];
+unset($ref);
+$arr[0][0] = $arr[0];
+var_dump($arr);
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ array(1) {
+ [0]=>
+ NULL
+ }
+}
diff --git a/Zend/tests/bug72543_2.phpt b/Zend/tests/bug72543_2.phpt
new file mode 100644
index 0000000000..2070d65bdd
--- /dev/null
+++ b/Zend/tests/bug72543_2.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #72543.2 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [];
+$arr[0] = null;
+$ref =& $arr[0];
+unset($ref);
+$arr[0][$arr[0]] = null;
+var_dump($arr);
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ array(1) {
+ [""]=>
+ NULL
+ }
+}
diff --git a/Zend/tests/bug72543_3.phpt b/Zend/tests/bug72543_3.phpt
new file mode 100644
index 0000000000..3835fafaa3
--- /dev/null
+++ b/Zend/tests/bug72543_3.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Bug #72543.3 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$x = new stdClass;
+$x->a = 1;
+$ref =& $x->a;
+unset($ref);
+var_dump($x->a + ($x->a = 2));
+?>
+--EXPECT--
+int(3)
diff --git a/Zend/tests/bug72543_4.phpt b/Zend/tests/bug72543_4.phpt
new file mode 100644
index 0000000000..3480c1c42c
--- /dev/null
+++ b/Zend/tests/bug72543_4.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #72543.4 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [1];
+$ref =& $arr[0];
+unset($ref);
+var_dump($arr[0] + ($arr[0] = 2));
+?>
+--EXPECT--
+int(3)
diff --git a/Zend/tests/bug72543_5.phpt b/Zend/tests/bug72543_5.phpt
new file mode 100644
index 0000000000..66b3b75f2a
--- /dev/null
+++ b/Zend/tests/bug72543_5.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Bug #72543.5 (different references behavior comparing to PHP 5)
+--FILE--
+<?php
+$arr = [1];
+$ref =& $arr[0];
+var_dump($arr[0] + ($arr[0] = 2));
+?>
+--EXPECT--
+int(4)
diff --git a/Zend/tests/bug72598.phpt b/Zend/tests/bug72598.phpt
new file mode 100644
index 0000000000..dfb09a05b8
--- /dev/null
+++ b/Zend/tests/bug72598.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #72598 (Reference is lost after array_slice())
+--FILE--
+<?php
+function ref(&$ref) {
+ var_dump($ref);
+}
+
+new class {
+ function __construct() {
+ $args = [&$this];
+ for ($i = 0; $i < 2; $i++) {
+ $a = array_slice($args, 0, 1);
+ call_user_func_array('ref', $a);
+ }
+ }
+};
+?>
+--EXPECTF--
+Warning: Parameter 1 to ref() expected to be a reference, value given in %sbug72598.php on line 11
+object(class@anonymous)#1 (0) {
+}
+
+Warning: Parameter 1 to ref() expected to be a reference, value given in %sbug72598.php on line 11
+object(class@anonymous)#1 (0) {
+}
diff --git a/Zend/tests/bug72598_2.phpt b/Zend/tests/bug72598_2.phpt
new file mode 100644
index 0000000000..c3943806ff
--- /dev/null
+++ b/Zend/tests/bug72598_2.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #72598.2 (Reference is lost after array_slice())
+--FILE--
+<?php
+function ref(&$ref) {
+ var_dump($ref);
+ $ref = 1;
+}
+
+new class {
+ function __construct() {
+ $b = 0;
+ $args = [&$b];
+ unset($b);
+ for ($i = 0; $i < 2; $i++) {
+ $a = array_slice($args, 0, 1);
+ call_user_func_array('ref', $a);
+ }
+ }
+};
+?>
+--EXPECTF--
+Warning: Parameter 1 to ref() expected to be a reference, value given in %sbug72598_2.php on line 14
+int(0)
+
+Warning: Parameter 1 to ref() expected to be a reference, value given in %sbug72598_2.php on line 14
+int(0)
diff --git a/Zend/tests/bug72918.phpt b/Zend/tests/bug72918.phpt
new file mode 100644
index 0000000000..f3dc1d2918
--- /dev/null
+++ b/Zend/tests/bug72918.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #72918 (negative offset inside a quoted string leads to parse error)
+--FILE--
+<?php
+$array = [-3 => 'foo'];
+$string = 'abcde';
+
+echo "$array[-3]\n";
+echo "$string[-3]\n";
+echo <<<EOT
+$array[-3]
+$string[-3]
+
+EOT;
+?>
+===DONE===
+--EXPECT--
+foo
+c
+foo
+c
+===DONE===
diff --git a/Zend/tests/bug73288.phpt b/Zend/tests/bug73288.phpt
new file mode 100644
index 0000000000..fefcf3bbcd
--- /dev/null
+++ b/Zend/tests/bug73288.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #73288 (Segfault in __clone > Exception.toString > __get)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+--FILE--
+<?php
+
+class NoClone {
+ public function __clone() {
+ throw new Exception("No Cloneable");
+ }
+}
+
+class C {
+ public function __get($name) {
+ return new NoClone;
+ }
+}
+
+function test_clone() {
+ $c = new C;
+ $b = clone $c->x;
+}
+
+test_clone();
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: No Cloneable in %sbug73288.php:%d
+Stack trace:
+#0 %s(%d): NoClone->__clone()
+#1 %s(%d): test_clone()
+#2 {main}
+ thrown in %sbug73288.php on line %d
diff --git a/Zend/tests/bug74093.phpt b/Zend/tests/bug74093.phpt
new file mode 100644
index 0000000000..7f20285805
--- /dev/null
+++ b/Zend/tests/bug74093.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #74093 (Maximum execution time of n+2 seconds exceed not written in error_log)
+--SKIPIF--
+<?php
+if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
+if (PHP_ZTS) die("skip only for no-zts build");
+if (substr(PHP_OS, 0, 3) == 'WIN') die("skip not for Windows");
+?>
+--INI--
+memory_limit=1G
+max_execution_time=1
+hard_timeout=1
+--FILE--
+<?php
+$a1 = range(1, 1000000);
+$a2 = range(100000, 1999999);
+array_intersect($a1, $a2);
+?>
+--EXPECTF--
+Fatal error: Maximum execution time of 1+1 seconds exceeded %s
diff --git a/Zend/tests/bug74164.phpt b/Zend/tests/bug74164.phpt
new file mode 100644
index 0000000000..354b2f51e0
--- /dev/null
+++ b/Zend/tests/bug74164.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #74164 (PHP hangs when an invalid value is dynamically passed to typehinted by-ref arg)
+--FILE--
+<?php
+
+namespace Foo;
+
+set_error_handler(function ($type, $msg) {
+ throw new \Exception($msg);
+});
+
+call_user_func(function (array &$ref) {var_dump("xxx");}, 'not_an_array_variable');
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: Parameter 1 to Foo\{closure}() expected to be a reference, value given in %sbug74164.php:%d
+Stack trace:
+#0 [internal function]: Foo\{closure}(%s)
+#1 %sbug74164.php(%d): call_user_func(%s)
+#2 {main}
+ thrown in %sbug74164.php on line %d
diff --git a/Zend/tests/bug74340.phpt b/Zend/tests/bug74340.phpt
new file mode 100644
index 0000000000..f266dcc236
--- /dev/null
+++ b/Zend/tests/bug74340.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #74340: Magic function __get has different behavior in php 7.1.x
+--FILE--
+<?php
+class Test
+{
+ public function __get($var)
+ {
+ static $first = true;
+ echo '__get '.$var.PHP_EOL;
+ if ($first) {
+ $first = false;
+ $this->$var;
+ $this->{$var.'2'};
+ $this->$var;
+ }
+ }
+}
+
+$test = new Test;
+$test->test;
+
+?>
+--EXPECTF--
+__get test
+
+Notice: Undefined property: Test::$test in %s on line %d
+__get test2
+
+Notice: Undefined property: Test::$test in %s on line %d
diff --git a/Zend/tests/bug74862.phpt b/Zend/tests/bug74862.phpt
new file mode 100644
index 0000000000..7822575d04
--- /dev/null
+++ b/Zend/tests/bug74862.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #74862 (Unable to clone instance when private __clone defined)
+--FILE--
+<?php
+
+class a {
+ private function __clone()
+ {
+
+ }
+
+ private function __construct()
+ {
+
+ }
+
+ public static function getInstance()
+ {
+ return new static();
+ }
+
+ public function cloneIt()
+ {
+ $a = clone $this;
+
+ return $a;
+ }
+}
+
+class c extends a {
+
+}
+
+// private constructor
+$d = c::getInstance();
+
+// private clone
+$e = $d->cloneIt();
+var_dump($e);
+?>
+--EXPECT--
+object(c)#2 (0) {
+}
diff --git a/Zend/tests/bug74862_2.phpt b/Zend/tests/bug74862_2.phpt
new file mode 100644
index 0000000000..2e544a380e
--- /dev/null
+++ b/Zend/tests/bug74862_2.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Bug #74862 (Unable to clone instance when private __clone defined in a child class)
+--FILE--
+<?php
+
+class main {
+}
+
+class a extends main {
+ private function __clone()
+ {
+
+ }
+
+ private function __construct()
+ {
+
+ }
+
+ public static function getInstance()
+ {
+ return new static();
+ }
+
+ public function cloneIt()
+ {
+ $a = clone $this;
+
+ return $a;
+ }
+}
+
+class c extends a {
+
+}
+
+// private constructor
+$d = c::getInstance();
+
+// private clone
+$e = $d->cloneIt();
+var_dump($e);
+?>
+--EXPECT--
+object(c)#2 (0) {
+}
diff --git a/Zend/tests/bug75079.phpt b/Zend/tests/bug75079.phpt
new file mode 100644
index 0000000000..9bf9c1ddb8
--- /dev/null
+++ b/Zend/tests/bug75079.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Bug #75079: self keyword leads to incorrectly generated TypeError when in closure in trait
+--FILE--
+<?php
+
+trait Foo
+{
+ public function selfDo(self ...$Selfs)
+ {
+ array_map(
+ function (self $Self) : self
+ {
+ return $Self;
+ },
+ $Selfs
+ );
+ }
+}
+
+class Bar
+{
+ use Foo;
+}
+
+class Baz
+{
+ use Foo;
+}
+
+$Bar = new Bar;
+$Baz = new Baz;
+
+$Bar->selfDo($Bar, $Bar);
+$Baz->selfDo($Baz, $Baz);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/bug75079_2.phpt b/Zend/tests/bug75079_2.phpt
new file mode 100644
index 0000000000..6e0b1cd27f
--- /dev/null
+++ b/Zend/tests/bug75079_2.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #75079 variation without traits
+--FILE--
+<?php
+
+class Foo
+{
+ private static $bar = 123;
+
+ static function test(){
+ return function(){
+ return function(){
+ return Foo::$bar;
+ };
+ };
+ }
+}
+
+
+$f = Foo::test();
+
+var_dump($f()());
+
+class A{}
+$a = new A;
+var_dump($f->bindTo($a, A::CLASS)()());
+
+?>
+--EXPECTF--
+int(123)
+
+Fatal error: Uncaught Error: Cannot access private property Foo::$bar in %s:%d
+Stack trace:
+#0 %s(%d): A->{closure}()
+#1 {main}
+ thrown in %s on line %d
diff --git a/Zend/tests/bug75786.phpt b/Zend/tests/bug75786.phpt
new file mode 100644
index 0000000000..b93111b9e3
--- /dev/null
+++ b/Zend/tests/bug75786.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #75786: segfault when using spread operator on generator passed by reference
+--FILE--
+<?php
+
+function &gen($items) {
+ foreach ($items as $key => &$value) {
+ yield $key => $value;
+ }
+}
+
+var_dump(...gen(['a', 'b', 'c']));
+
+?>
+--EXPECT--
+string(1) "a"
+string(1) "b"
+string(1) "c"
diff --git a/Zend/tests/bug76025.phpt b/Zend/tests/bug76025.phpt
new file mode 100644
index 0000000000..2619984d1e
--- /dev/null
+++ b/Zend/tests/bug76025.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #76025 (Segfault while throwing exception in error_handler)
+--FILE--
+<?php
+
+function handleError($errno, $errstr, $errfile, $errline) {
+ $exception = new exception("blah");
+ throw $exception;
+}
+set_error_handler('handleError', E_ALL);
+$c = $b[$a];
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: blah in %sbug76025.php:%d
+Stack trace:
+#0 %sbug76025.php(%d): handleError(8, 'Undefined varia...', '%s', %d, Array)
+#1 {main}
+ thrown in %sbug76025.php on line %d
diff --git a/Zend/tests/bug76383.phpt b/Zend/tests/bug76383.phpt
new file mode 100644
index 0000000000..ae26ba8acd
--- /dev/null
+++ b/Zend/tests/bug76383.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Bug #76383: array_map on $GLOBALS returns IS_INDIRECT
+--FILE--
+<?php
+
+$a = 1;
+array_map(function($x) use (&$lastval) { $lastval = $x; }, $GLOBALS);
+var_dump(gettype($lastval), $lastval); // will contain $a
+
+?>
+--EXPECT--
+string(7) "integer"
+int(1)
diff --git a/Zend/tests/bug76502.phpt b/Zend/tests/bug76502.phpt
new file mode 100644
index 0000000000..caacc99f70
--- /dev/null
+++ b/Zend/tests/bug76502.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #76502: Chain of mixed exceptions and errors does not serialize properly
+--FILE--
+<?php
+
+$examples = [
+ "Exception(Exception())" => new Exception("outer", 0, new Exception("inner")),
+ "Error(Error())" => new Error("outer", 0, new Error("inner")),
+ "Error(Exception())" => new Error("outer", 0, new Exception("inner")),
+ "Exception(Error())" => new Exception("outer", 0, new Error("inner"))
+];
+
+foreach ($examples as $name => $example) {
+ $processed = unserialize(serialize($example));
+ $processedPrev = $processed->getPrevious();
+ echo "---- $name ----\n";
+ echo "before: ", get_class($example), ".previous == ",
+ get_class($example->getPrevious()), "\n";
+ echo "after : ", get_class($processed), ".previous == ",
+ $processedPrev ? get_class($processedPrev) : "null", "\n";
+}
+
+?>
+--EXPECT--
+---- Exception(Exception()) ----
+before: Exception.previous == Exception
+after : Exception.previous == Exception
+---- Error(Error()) ----
+before: Error.previous == Error
+after : Error.previous == Error
+---- Error(Exception()) ----
+before: Error.previous == Exception
+after : Error.previous == Exception
+---- Exception(Error()) ----
+before: Exception.previous == Error
+after : Exception.previous == Error
diff --git a/Zend/tests/bug76534.phpt b/Zend/tests/bug76534.phpt
new file mode 100644
index 0000000000..956a29ba2c
--- /dev/null
+++ b/Zend/tests/bug76534.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #76534 (PHP hangs on 'illegal string offset on string references with an error handler)
+--FILE--
+<?php
+set_error_handler(function ($severity, $message, $file, $line) {
+ throw new \Exception($message);
+});
+
+$x = "foo";
+$y = &$x["bar"];
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: Illegal string offset 'bar' in %sbug76534.php:%d
+Stack trace:
+#0 %sbug76534.php(%d): {closure}(2, 'Illegal string ...', '%s', %d, Array)
+#1 {main}
+ thrown in %sbug76534.php on line %d
diff --git a/Zend/tests/bug76754.phpt b/Zend/tests/bug76754.phpt
new file mode 100644
index 0000000000..424f1fbffc
--- /dev/null
+++ b/Zend/tests/bug76754.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #76754 (parent private constant in extends class memory leak)
+--INI--
+opcache.enable=0
+opcache.enable_cli=0
+--FILE--
+<?php
+
+class FOO
+{
+ private const FOO = 'BAR';
+}
+
+class BAR extends FOO { }
+?>
+okey
+--EXPECT--
+okey
diff --git a/Zend/tests/call_user_func_006.phpt b/Zend/tests/call_user_func_006.phpt
new file mode 100644
index 0000000000..16a59bcf5b
--- /dev/null
+++ b/Zend/tests/call_user_func_006.phpt
@@ -0,0 +1,28 @@
+--TEST--
+call_user_func() should error on reference arguments
+--FILE--
+<?php
+
+namespace Foo;
+
+function bar(&$ref) {
+ $ref = 24;
+}
+
+$x = 42;
+$ref =& $x;
+\call_user_func('Foo\bar', $x);
+var_dump($x);
+
+$y = 42;
+$ref =& $y;
+call_user_func('Foo\bar', $y);
+var_dump($y);
+
+?>
+--EXPECTF--
+Warning: Parameter 1 to Foo\bar() expected to be a reference, value given in %s on line %d
+int(42)
+
+Warning: Parameter 1 to Foo\bar() expected to be a reference, value given in %s on line %d
+int(42)
diff --git a/Zend/tests/call_user_func_008.phpt b/Zend/tests/call_user_func_008.phpt
new file mode 100644
index 0000000000..3e727e7f43
--- /dev/null
+++ b/Zend/tests/call_user_func_008.phpt
@@ -0,0 +1,54 @@
+--TEST--
+call_user_func() behavior with references
+--FILE--
+<?php
+
+function test(&$ref1, &$ref2) {
+ $ref1 += 42;
+ $ref2 -= 42;
+ return true;
+}
+
+$i = $j = 0;
+var_dump(call_user_func('test', $i, $j));
+var_dump($i, $j);
+
+var_dump(call_user_func_array('test', [$i, $j]));
+var_dump($i, $j);
+
+$x =& $i; $y =& $j;
+var_dump(call_user_func('test', $i, $j));
+var_dump($i, $j);
+
+var_dump(call_user_func_array('test', [$i, $j]));
+var_dump($i, $j);
+
+?>
+--EXPECTF--
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
+
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
+
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
+
+Warning: Parameter 1 to test() expected to be a reference, value given in %s on line %d
+
+Warning: Parameter 2 to test() expected to be a reference, value given in %s on line %d
+bool(true)
+int(0)
+int(0)
diff --git a/Zend/tests/call_user_func_009.phpt b/Zend/tests/call_user_func_009.phpt
new file mode 100644
index 0000000000..d45380db15
--- /dev/null
+++ b/Zend/tests/call_user_func_009.phpt
@@ -0,0 +1,17 @@
+--TEST--
+call_user_func() behavior when passing literal to reference parameter
+--FILE--
+<?php
+
+namespace Foo;
+
+var_dump(call_user_func('sort', []));
+var_dump(\call_user_func('sort', []));
+
+?>
+--EXPECTF--
+Warning: Parameter 1 to sort() expected to be a reference, value given in %s on line %d
+bool(true)
+
+Warning: Parameter 1 to sort() expected to be a reference, value given in %s on line %d
+bool(true)
diff --git a/Zend/tests/class_properties_const.phpt b/Zend/tests/class_properties_const.phpt
index ac871b5c2b..8f607bcfe2 100644
--- a/Zend/tests/class_properties_const.phpt
+++ b/Zend/tests/class_properties_const.phpt
@@ -22,4 +22,4 @@ NULL
Notice: Undefined property: A::$1 in %sclass_properties_const.php on line %d
NULL
-Catchable fatal error: Object of class Closure could not be converted to string in %sclass_properties_const.php on line %d
+Recoverable fatal error: Object of class Closure could not be converted to string in %sclass_properties_const.php on line %d
diff --git a/Zend/tests/closure_027.phpt b/Zend/tests/closure_027.phpt
index db42ae9307..76754f9fba 100644
--- a/Zend/tests/closure_027.phpt
+++ b/Zend/tests/closure_027.phpt
@@ -13,7 +13,11 @@ test(function() { return new stdclass; });
test(function() { });
$a = function($x) use ($y) {};
-test($a);
+try {
+ test($a);
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
test(new stdclass);
@@ -24,9 +28,7 @@ object(stdClass)#%d (0) {
NULL
Notice: Undefined variable: y in %s on line %d
-
-Warning: Missing argument 1 for {closure}(), called in %s on line %d and defined in %s on line %d
-NULL
+Exception: Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of Closure, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:
diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt
index 83ad16d2e1..1aa579a409 100644
--- a/Zend/tests/closure_061.phpt
+++ b/Zend/tests/closure_061.phpt
@@ -184,7 +184,7 @@ bindTo(new ClsChild, Cls::class):
Success!
bindTo(new ClsUnrelated, Cls::class):
-Success!
+Cannot bind method Cls::method() to object of class ClsUnrelated
bindTo(new Cls, null):
Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
@@ -205,7 +205,7 @@ bindTo(new SplStack, SplDoublyLinkedList::class):
Success!
bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
-Cannot bind internal method SplDoublyLinkedList::count() to object of class ClsUnrelated
+Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
bindTo(null, null):
Cannot unbind $this of internal method
diff --git a/Zend/tests/closure_use_auto_global.phpt b/Zend/tests/closure_use_auto_global.phpt
new file mode 100644
index 0000000000..9ab0897e12
--- /dev/null
+++ b/Zend/tests/closure_use_auto_global.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Cannot use() auto-global
+--FILE--
+<?php
+
+function test() {
+ $fn = function() use($GLOBALS) {
+ var_dump($GLOBALS);
+ };
+ $fn();
+}
+test();
+
+?>
+--EXPECTF--
+Fatal error: Cannot use auto-global as lexical variable in %s on line %d
diff --git a/Zend/tests/closure_use_parameter_name.phpt b/Zend/tests/closure_use_parameter_name.phpt
new file mode 100644
index 0000000000..7ecc6d8dd1
--- /dev/null
+++ b/Zend/tests/closure_use_parameter_name.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Can't use name of lexical variable for parameter
+--FILE--
+<?php
+
+$a = 1;
+$fn = function ($a) use ($a) {
+ var_dump($a);
+};
+$fn(2);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use lexical variable $a as a parameter name in %s on line %d
diff --git a/Zend/tests/closure_use_variable_twice.phpt b/Zend/tests/closure_use_variable_twice.phpt
new file mode 100644
index 0000000000..06c2645809
--- /dev/null
+++ b/Zend/tests/closure_use_variable_twice.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Closure cannot use one variable twice
+--FILE--
+<?php
+
+$a = 1;
+$fn = function() use ($a, &$a) {
+ $a = 2;
+};
+$fn();
+var_dump($a);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use variable $a twice in %s on line %d
diff --git a/Zend/tests/closures/closure_from_callable.inc b/Zend/tests/closures/closure_from_callable.inc
new file mode 100644
index 0000000000..5f0f220974
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable.inc
@@ -0,0 +1,187 @@
+<?php
+
+function bar($param1)
+{
+ return $param1;
+}
+
+
+$closure = function($param1) {
+ return $param1;
+};
+
+function test($fn)
+{
+ static $count = 0;
+ $input = "foo".$count;
+ $count++;
+
+ $output = $fn($input);
+ return $input === $output;
+}
+
+class Foo
+{
+ public static function publicStaticFunction($param1)
+ {
+ return $param1;
+ }
+
+ private static function privateStaticFunction($param1)
+ {
+ return $param1;
+ }
+
+ protected static function protectedStaticFunction($param1)
+ {
+ return $param1;
+ }
+
+ private function privateInstanceFunc($param1)
+ {
+ return $param1;
+ }
+
+ protected function protectedInstanceFunc($param1)
+ {
+ return $param1;
+ }
+
+
+ public function publicInstanceFunc($param1)
+ {
+ return $param1;
+ }
+
+ public function closePrivateValid()
+ {
+ return Closure::fromCallable([$this, 'privateInstanceFunc']);
+ }
+
+ public function closePrivateStatic()
+ {
+ return Closure::fromCallable([__CLASS__, 'privateStaticFunction']);
+ }
+
+ public function bar($param1)
+ {
+ echo "this is bar\n";
+ }
+
+ public function getCallable()
+ {
+ return Closure::fromCallable([$this, 'publicInstanceFunc']);
+ }
+
+ public function getSelfPublicInstance()
+ {
+ return Closure::fromCallable([$this, 'publicInstanceFunc']);
+ }
+
+ public function getSelfColonPublicInstanceMethod()
+ {
+ return Closure::fromCallable('self::publicInstanceFunc');
+ }
+}
+
+
+
+class SubFoo extends Foo {
+
+ public function closePrivateStaticInvalid()
+ {
+ return Closure::fromCallable([__CLASS__, 'privateStaticFunction']);
+ }
+
+
+ public function closePrivateInvalid()
+ {
+ return Closure::fromCallable([$this, 'privateInstanceFunc']);
+ }
+
+ public function closeProtectedStaticMethod()
+ {
+ return Closure::fromCallable([__CLASS__, 'protectedStaticFunction']);
+ }
+
+ public function closeProtectedValid()
+ {
+ return Closure::fromCallable([$this, 'protectedInstanceFunc']);
+ }
+
+ public function getParentPublicInstanceMethod()
+ {
+ return Closure::fromCallable('parent::publicInstanceFunc');
+ }
+
+ public function getSelfColonParentPublicInstanceMethod()
+ {
+ return Closure::fromCallable('self::publicInstanceFunc');
+ }
+
+
+ public function getSelfColonParentProtectedInstanceMethod()
+ {
+ return Closure::fromCallable('self::protectedInstanceFunc');
+ }
+
+ public function getSelfColonParentPrivateInstanceMethod()
+ {
+ return Closure::fromCallable('self::privateInstanceFunc');
+ }
+}
+
+
+class MagicCall
+{
+ public function __call($name, $arguments)
+ {
+ $info = ['__call'];
+ $info[] = $name;
+ $info = array_merge($info, $arguments);
+ return implode(',', $info);
+ }
+
+ public static function __callStatic($name, $arguments)
+ {
+ $info = ['__callStatic'];
+ $info[] = $name;
+ $info = array_merge($info, $arguments);
+ return implode(',', $info);
+ }
+}
+
+
+
+class PublicInvokable
+{
+ public function __invoke($param1)
+ {
+ return $param1;
+ }
+}
+
+
+function functionAccessProtected()
+{
+ $foo = new Foo;
+
+ return Closure::fromCallable([$foo, 'protectedStaticFunction']);
+}
+
+function functionAccessPrivate()
+{
+ $foo = new Foo;
+
+ return Closure::fromCallable([$foo, 'privateStaticFunction']);
+}
+
+
+function functionAccessMethodDoesntExist()
+{
+ $foo = new Foo;
+
+ return Closure::fromCallable([$foo, 'thisDoesNotExist']);
+}
+
+?>
diff --git a/Zend/tests/closures/closure_from_callable_basic.phpt b/Zend/tests/closures/closure_from_callable_basic.phpt
new file mode 100644
index 0000000000..2561bbfaa6
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable_basic.phpt
@@ -0,0 +1,122 @@
+--TEST--
+Testing Closure::fromCallable() functionality: Basic
+--FILE--
+<?php
+
+include('closure_from_callable.inc');
+
+echo 'Access public static function';
+$fn = Closure::fromCallable(['Foo', 'publicStaticFunction']);
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public static function with different case';
+$fn = Closure::fromCallable(['fOo', 'publicStaticfUNCTION']);
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public static function with colon scheme';
+$fn = Closure::fromCallable('Foo::publicStaticFunction');
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public instance method of object';
+$fn = Closure::fromCallable([new Foo, 'publicInstanceFunc']);
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public instance method of parent object through parent:: ';
+$fn = Closure::fromCallable([new Foo, 'publicInstanceFunc']);
+echo $fn(" OK".PHP_EOL);
+
+echo 'Function that exists';
+$fn = Closure::fromCallable('bar');
+echo $fn(" OK".PHP_EOL);
+
+echo 'Function that exists with different spelling';
+$fn = Closure::fromCallable('BAR');
+echo $fn(" OK".PHP_EOL);
+
+echo 'Closure is already a closure';
+$fn = Closure::fromCallable($closure);
+echo $fn(" OK".PHP_EOL);
+
+echo 'Class with public invokable';
+$fn = Closure::fromCallable(new PublicInvokable);
+echo $fn(" OK".PHP_EOL);
+
+echo "Instance return private method as callable";
+$foo = new Foo;
+$fn = $foo->closePrivateValid();
+echo $fn(" OK".PHP_EOL);
+
+echo "Instance return private static method as callable";
+$foo = new Foo;
+$fn = $foo->closePrivateStatic();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Instance return protected static method as callable';
+$subFoo = new SubFoo;
+$fn = $subFoo->closeProtectedStaticMethod();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Subclass closure over parent class protected method';
+$subFoo = new SubFoo;
+$fn = $subFoo->closeProtectedValid();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Subclass closure over parent class static protected method';
+$subFoo = new SubFoo;
+$fn = $subFoo->closeProtectedStaticMethod();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public instance method of parent object through "parent::" ';
+$subFoo = new SubFoo;
+$fn = $subFoo->getParentPublicInstanceMethod();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public instance method of self object through "self::" ';
+$foo = new Foo;
+$fn = $foo->getSelfColonPublicInstanceMethod();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access public instance method of parent object through "self::" to parent method';
+$foo = new SubFoo;
+$fn = $foo->getSelfColonParentPublicInstanceMethod();
+echo $fn(" OK".PHP_EOL);
+
+echo 'Access proteced instance method of parent object through "self::" to parent method';
+$foo = new SubFoo;
+$fn = $foo->getSelfColonParentProtectedInstanceMethod();
+echo $fn(" OK".PHP_EOL);
+
+echo 'MagicCall __call instance method ';
+$fn = Closure::fromCallable([new MagicCall, 'nonExistentMethod']);
+echo $fn(" OK".PHP_EOL);
+
+echo 'MagicCall __callStatic static method ';
+$fn = Closure::fromCallable(['MagicCall', 'nonExistentMethod']);
+echo $fn(" OK".PHP_EOL);
+
+
+?>
+===DONE===
+--EXPECT--
+
+Access public static function OK
+Access public static function with different case OK
+Access public static function with colon scheme OK
+Access public instance method of object OK
+Access public instance method of parent object through parent:: OK
+Function that exists OK
+Function that exists with different spelling OK
+Closure is already a closure OK
+Class with public invokable OK
+Instance return private method as callable OK
+Instance return private static method as callable OK
+Instance return protected static method as callable OK
+Subclass closure over parent class protected method OK
+Subclass closure over parent class static protected method OK
+Access public instance method of parent object through "parent::" OK
+Access public instance method of self object through "self::" OK
+Access public instance method of parent object through "self::" to parent method OK
+Access proteced instance method of parent object through "self::" to parent method OK
+MagicCall __call instance method __call,nonExistentMethod, OK
+MagicCall __callStatic static method __callStatic,nonExistentMethod, OK
+===DONE===
diff --git a/Zend/tests/closures/closure_from_callable_error.phpt b/Zend/tests/closures/closure_from_callable_error.phpt
new file mode 100644
index 0000000000..d9db90bcad
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable_error.phpt
@@ -0,0 +1,215 @@
+--TEST--
+Testing Closure::fromCallable() functionality: Errors
+--FILE--
+<?php
+
+include('closure_from_callable.inc');
+
+echo 'Cannot access privateInstance method statically'."\n";
+try {
+ $fn = Closure::fromCallable(['Foo', 'privateInstanceFunc']);
+ echo "Test failed to fail and return was : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+
+echo 'Cannot access privateInstance method statically with colon scheme'."\n";
+try {
+ $fn = Closure::fromCallable('Foo::privateInstanceFunc');
+ echo "Test failed to fail and return was : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Cannot access privateInstance method'."\n";
+try {
+ $fn = Closure::fromCallable([new Foo, 'privateInstanceFunc']);
+ echo "Test failed to fail and return was : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'SubClass cannot access private instance method'."\n";
+try {
+ $fn = Closure::fromCallable([new SubFoo, 'privateInstanceFunc']);
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Cannot access private static function of instance'."\n";
+try {
+ $fn = Closure::fromCallable([new Foo, 'privateStaticFunction']);
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Cannot access private static method statically'."\n";
+try {
+ $fn = Closure::fromCallable(['Foo', 'privateStaticFunction']);
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Cannot access private static method statically with colon scheme'."\n";
+try {
+ $fn = Closure::fromCallable('Foo::privateStaticFunction');
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Non-existent method should fail'."\n";
+try {
+ $fn = Closure::fromCallable('Foo::nonExistentFunction');
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Non-existent class should fail'."\n";
+try {
+ $fn = Closure::fromCallable(['NonExistentClass', 'foo']);
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Non-existent function should fail'."\n";
+try {
+ $fn = Closure::fromCallable('thisDoesNotExist');
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+
+echo 'Subclass cannot closure over parent private instance method'."\n";
+try {
+ $subFoo = new SubFoo;
+ $fn = $subFoo->closePrivateInvalid();
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Subclass cannot closure over parant private static method'."\n";
+try {
+ $subFoo = new SubFoo;
+ $fn = $subFoo->closePrivateStaticInvalid();
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Function scope cannot closure over protected instance method'."\n";
+try {
+ $fn = functionAccessProtected();
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Function scope cannot closure over private instance method'."\n";
+try {
+ $fn = functionAccessPrivate();
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo 'Access private instance method of parent object through "self::" to parent method'."\n";
+try {
+ $foo = new SubFoo;
+ $fn = $foo->getSelfColonParentPrivateInstanceMethod();
+ echo "Test failed to fail, closure is : ".var_export($fn, true)."\n";
+}
+catch (\TypeError $te) {
+ //This is the expected outcome.
+}
+catch (\Throwable $t) {
+ echo "Wrong exception type thrown: ".get_class($t)." : ".$t->getMessage()."\n";
+}
+
+echo "OK\n";
+
+?>
+===DONE===
+--EXPECT--
+
+Cannot access privateInstance method statically
+Cannot access privateInstance method statically with colon scheme
+Cannot access privateInstance method
+SubClass cannot access private instance method
+Cannot access private static function of instance
+Cannot access private static method statically
+Cannot access private static method statically with colon scheme
+Non-existent method should fail
+Non-existent class should fail
+Non-existent function should fail
+Subclass cannot closure over parent private instance method
+Subclass cannot closure over parant private static method
+Function scope cannot closure over protected instance method
+Function scope cannot closure over private instance method
+Access private instance method of parent object through "self::" to parent method
+OK
+===DONE===
diff --git a/Zend/tests/closures/closure_from_callable_lsb.phpt b/Zend/tests/closures/closure_from_callable_lsb.phpt
new file mode 100644
index 0000000000..950985bdad
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable_lsb.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Testing Closure::fromCallable() functionality: Late static binding
+--FILE--
+<?php
+
+class A {
+ public static function test() {
+ var_dump(static::class);
+ }
+}
+
+class B extends A {
+}
+
+Closure::fromCallable(['A', 'test'])();
+Closure::fromCallable(['B', 'test'])();
+
+?>
+--EXPECT--
+string(1) "A"
+string(1) "B"
diff --git a/Zend/tests/closures/closure_from_callable_non_static_statically.phpt b/Zend/tests/closures/closure_from_callable_non_static_statically.phpt
new file mode 100644
index 0000000000..17d39c052e
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable_non_static_statically.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Testing Closure::fromCallable() functionality: Getting non-static method statically
+--FILE--
+<?php
+
+class A {
+ public function method() {
+ }
+}
+
+try {
+ $fn = Closure::fromCallable(['A', 'method']);
+ $fn();
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+Failed to create closure from callable: non-static method A::method() should not be called statically
diff --git a/Zend/tests/closures/closure_from_callable_rebinding.phpt b/Zend/tests/closures/closure_from_callable_rebinding.phpt
new file mode 100644
index 0000000000..6fb5c6ffc1
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable_rebinding.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Testing Closure::fromCallable() functionality: Rebinding
+--FILE--
+<?php
+
+class A {
+ public function method() {
+ var_dump($this);
+ }
+}
+
+class B {
+}
+
+$fn = Closure::fromCallable([new A, 'method']);
+$fn->call(new B);
+
+?>
+--EXPECTF--
+Warning: Cannot bind method A::method() to object of class B in %s on line %d
diff --git a/Zend/tests/closures/closure_from_callable_reflection.phpt b/Zend/tests/closures/closure_from_callable_reflection.phpt
new file mode 100644
index 0000000000..af40193fba
--- /dev/null
+++ b/Zend/tests/closures/closure_from_callable_reflection.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Testing Closure::fromCallable() functionality: Reflection
+--FILE--
+<?php
+
+class Bar {
+ public static function staticMethod(Bar $bar, int $int, $none) {}
+ public static function instanceMethod(Bar $bar, int $int, $none) {}
+}
+
+function foo(Bar $bar, int $int, $none) {
+
+}
+
+$fn = function (Bar $bar, int $x, $none) {};
+$bar = new Bar();
+
+$callables = [
+ 'foo',
+ $fn,
+ 'Bar::staticMethod',
+ [$bar, 'instanceMethod']
+];
+
+
+foreach ($callables as $callable) {
+ $closure = Closure::fromCallable($callable);
+ $refl = new ReflectionFunction($closure);
+ foreach ($refl->getParameters() as $param) {
+ if ($param->hasType()) {
+ $type = $param->getType();
+ echo $type->getName() . "\n";
+ }
+ }
+}
+
+?>
+--EXPECTF--
+Bar
+int
+Bar
+int
+Bar
+int
+Bar
+int
diff --git a/Zend/tests/constant_expressions_dynamic.phpt b/Zend/tests/constant_expressions_dynamic.phpt
index d038591036..686dcc1d11 100644
--- a/Zend/tests/constant_expressions_dynamic.phpt
+++ b/Zend/tests/constant_expressions_dynamic.phpt
@@ -44,7 +44,9 @@ var_dump(
);
?>
---EXPECT--
+--EXPECTF--
+
+Warning: A non-numeric value encountered in %s on line %d
int(3)
string(4) "1foo"
bool(false)
diff --git a/Zend/tests/constant_expressions_self_referencing_array.phpt b/Zend/tests/constant_expressions_self_referencing_array.phpt
index 63f2b20ef5..c584b5d503 100644
--- a/Zend/tests/constant_expressions_self_referencing_array.phpt
+++ b/Zend/tests/constant_expressions_self_referencing_array.phpt
@@ -9,7 +9,7 @@ class A {
var_dump(A::FOO);
?>
--EXPECTF--
-Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::FOO' in %s:%d
+Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::BAR' in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
diff --git a/Zend/tests/dynamic_call_005.phpt b/Zend/tests/dynamic_call_005.phpt
new file mode 100644
index 0000000000..840e298b82
--- /dev/null
+++ b/Zend/tests/dynamic_call_005.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Dynamic calls to scope introspection functions are forbidden
+--FILE--
+<?php
+
+function test_calls($func) {
+ $i = 1;
+
+ array_map($func, [['i' => new stdClass]]);
+ var_dump($i);
+
+ $func(['i' => new stdClass]);
+ var_dump($i);
+
+ call_user_func($func, ['i' => new stdClass]);
+ var_dump($i);
+}
+test_calls('extract');
+
+?>
+--EXPECTF--
+Warning: Cannot call extract() dynamically in %s on line %d
+int(1)
+
+Warning: Cannot call extract() dynamically in %s on line %d
+int(1)
+
+Warning: Cannot call extract() dynamically in %s on line %d
+int(1)
diff --git a/Zend/tests/dynamic_call_006.phpt b/Zend/tests/dynamic_call_006.phpt
new file mode 100644
index 0000000000..058e22fda0
--- /dev/null
+++ b/Zend/tests/dynamic_call_006.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Dynamic calls to scope introspection functions are forbidden (function variations)
+--FILE--
+<?php
+function test() {
+ $func = 'extract';
+ $func(['a' => 'b']);
+
+ $func = 'compact';
+ $func(['a']);
+
+ $func = 'parse_str';
+ $func('a=b');
+
+ $func = 'get_defined_vars';
+ $func();
+
+ $func = 'assert';
+ $func('1==2');
+
+ $func = 'func_get_args';
+ $func();
+
+ $func = 'func_get_arg';
+ $func(1);
+
+ $func = 'func_num_args';
+ $func();
+}
+test();
+
+?>
+--EXPECTF--
+Warning: Cannot call extract() dynamically in %s on line %d
+
+Warning: Cannot call compact() dynamically in %s on line %d
+
+Warning: Cannot call parse_str() with a single argument dynamically in %s on line %d
+
+Warning: Cannot call get_defined_vars() dynamically in %s on line %d
+
+Warning: Cannot call assert() with string argument dynamically in %s on line %d
+
+Warning: Cannot call func_get_args() dynamically in %s on line %d
+
+Warning: Cannot call func_get_arg() dynamically in %s on line %d
+
+Warning: Cannot call func_num_args() dynamically in %s on line %d
diff --git a/Zend/tests/dynamic_call_007.phpt b/Zend/tests/dynamic_call_007.phpt
new file mode 100644
index 0000000000..61ae182914
--- /dev/null
+++ b/Zend/tests/dynamic_call_007.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Dynamic calls to scope introspection functions are forbidden (misoptimization)
+--FILE--
+<?php
+
+function test() {
+ $i = 1;
+ array_map('extract', [['i' => new stdClass]]);
+ $i += 1;
+ var_dump($i);
+}
+test();
+
+?>
+--EXPECTF--
+Warning: Cannot call extract() dynamically in %s on line %d
+int(2)
diff --git a/Zend/tests/dynamic_call_008.phpt b/Zend/tests/dynamic_call_008.phpt
new file mode 100644
index 0000000000..24240472d1
--- /dev/null
+++ b/Zend/tests/dynamic_call_008.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Don't optimize dynamic call to non-dynamic one if it drops the warning
+--FILE--
+<?php
+
+function test() {
+ ((string) 'extract')(['a' => 42]);
+}
+test();
+
+?>
+--EXPECTF--
+Warning: Cannot call extract() dynamically in %s on line %d
diff --git a/Zend/tests/dynamic_call_to_ref_returning_function.phpt b/Zend/tests/dynamic_call_to_ref_returning_function.phpt
new file mode 100644
index 0000000000..c4b6a9bcff
--- /dev/null
+++ b/Zend/tests/dynamic_call_to_ref_returning_function.phpt
@@ -0,0 +1,39 @@
+--TEST--
+When performing a dynamic call to a ret-by-ref function, the reference should be unwrapped
+--FILE--
+<?php
+
+namespace Foo;
+
+function &retRef($x) {
+ return $x;
+}
+
+var_dump(call_user_func('Foo\retRef', 42));
+var_dump(call_user_func_array('Foo\retRef', [42]));
+
+$closure = function &($x) {
+ return $x;
+};
+var_dump($closure->call(new class {}, 42));
+
+var_dump((new \ReflectionFunction('Foo\retRef'))->invoke(42));
+var_dump((new \ReflectionFunction('Foo\retRef'))->invokeArgs([42]));
+
+class Bar {
+ function &method($x) {
+ return $x;
+ }
+}
+var_dump((new \ReflectionMethod('Foo\Bar', 'method'))->invoke(new Bar, 42));
+var_dump((new \ReflectionMethod('Foo\Bar', 'method'))->invokeArgs(new Bar, [42]));
+
+?>
+--EXPECT--
+int(42)
+int(42)
+int(42)
+int(42)
+int(42)
+int(42)
+int(42)
diff --git a/Zend/tests/empty_str_offset.phpt b/Zend/tests/empty_str_offset.phpt
index 486c052dc4..49e175dd21 100644
--- a/Zend/tests/empty_str_offset.phpt
+++ b/Zend/tests/empty_str_offset.phpt
@@ -8,6 +8,8 @@ print "- empty ---\n";
$str = "test0123";
var_dump(empty($str[-1]));
+var_dump(empty($str[-10]));
+var_dump(empty($str[-4])); // 0
var_dump(empty($str[0]));
var_dump(empty($str[1]));
var_dump(empty($str[4])); // 0
@@ -17,6 +19,8 @@ var_dump(empty($str[10000]));
// non-numeric offsets
print "- string ---\n";
var_dump(empty($str['-1']));
+var_dump(empty($str['-10']));
+var_dump(empty($str['-4'])); // 0
var_dump(empty($str['0']));
var_dump(empty($str['1']));
var_dump(empty($str['4'])); // 0
@@ -31,6 +35,8 @@ print "- null ---\n";
var_dump(empty($str[null]));
print "- double ---\n";
var_dump(empty($str[-1.1]));
+var_dump(empty($str[-10.5]));
+var_dump(empty($str[-4.1]));
var_dump(empty($str[-0.8]));
var_dump(empty($str[-0.1]));
var_dump(empty($str[0.2]));
@@ -50,6 +56,8 @@ print "done\n";
?>
--EXPECTF--
- empty ---
+bool(false)
+bool(true)
bool(true)
bool(false)
bool(false)
@@ -58,6 +66,8 @@ bool(false)
bool(true)
bool(true)
- string ---
+bool(false)
+bool(true)
bool(true)
bool(false)
bool(false)
@@ -72,6 +82,8 @@ bool(true)
- null ---
bool(false)
- double ---
+bool(false)
+bool(true)
bool(true)
bool(false)
bool(false)
diff --git a/Zend/tests/entry_block_with_predecessors.phpt b/Zend/tests/entry_block_with_predecessors.phpt
new file mode 100644
index 0000000000..ffc3147f1c
--- /dev/null
+++ b/Zend/tests/entry_block_with_predecessors.phpt
@@ -0,0 +1,33 @@
+--TEST--
+For SSA form the entry block should have no predecessors
+--FILE--
+<?php
+
+function test() {
+ while (true) {
+ var_dump($a + 1);
+ $a = 1;
+ if (@$i++) {
+ break;
+ }
+ }
+}
+
+function test2() {
+ while (true) {
+ $a = 42;
+ if (@$i++ > 1) {
+ break;
+ }
+ $a = new stdClass;
+ }
+}
+
+test();
+test2();
+
+?>
+--EXPECTF--
+Notice: Undefined variable: a in %s on line %d
+int(1)
+int(2)
diff --git a/Zend/tests/error_reporting06.phpt b/Zend/tests/error_reporting06.phpt
index 285a623f2b..175ea37e80 100644
--- a/Zend/tests/error_reporting06.phpt
+++ b/Zend/tests/error_reporting06.phpt
@@ -11,7 +11,7 @@ function foo1($arg) {
function foo2($arg) {
}
-function foo3($arg) {
+function foo3() {
echo $undef3;
throw new Exception("test");
}
diff --git a/Zend/tests/error_reporting07.phpt b/Zend/tests/error_reporting07.phpt
index c63efae604..09b7690d3c 100644
--- a/Zend/tests/error_reporting07.phpt
+++ b/Zend/tests/error_reporting07.phpt
@@ -11,7 +11,7 @@ function foo1($arg) {
function foo2($arg) {
}
-function foo3($arg) {
+function foo3() {
echo $undef3;
throw new Exception("test");
}
diff --git a/Zend/tests/error_reporting08.phpt b/Zend/tests/error_reporting08.phpt
index edf3292779..c9945046ee 100644
--- a/Zend/tests/error_reporting08.phpt
+++ b/Zend/tests/error_reporting08.phpt
@@ -11,7 +11,7 @@ function foo1($arg) {
function foo2($arg) {
}
-function foo3($arg) {
+function foo3() {
error_reporting(E_ALL|E_STRICT);
echo $undef3;
throw new Exception("test");
diff --git a/Zend/tests/exception_009.phpt b/Zend/tests/exception_009.phpt
index b22b3aa66e..32b048c40b 100644
--- a/Zend/tests/exception_009.phpt
+++ b/Zend/tests/exception_009.phpt
@@ -25,4 +25,4 @@ throw new my_exception;
?>
--EXPECT--
-Catchable fatal error: Object of class stdClass could not be converted to string in Unknown on line 0
+Recoverable fatal error: Object of class stdClass could not be converted to string in Unknown on line 0
diff --git a/Zend/tests/foreach_list_keyed.phpt b/Zend/tests/foreach_list_keyed.phpt
new file mode 100644
index 0000000000..f5fab4e342
--- /dev/null
+++ b/Zend/tests/foreach_list_keyed.phpt
@@ -0,0 +1,36 @@
+--TEST--
+foreach with list syntax, keyed
+--FILE--
+<?php
+
+$points = [
+ ["x" => 1, "y" => 2],
+ ["x" => 2, "y" => 1]
+];
+
+foreach ($points as list("x" => $x, "y" => $y)) {
+ var_dump($x, $y);
+}
+
+echo PHP_EOL;
+
+$invertedPoints = [
+ "x" => [1, 2],
+ "y" => [2, 1]
+];
+
+foreach ($invertedPoints as list(0 => $row1, 1 => $row2)) {
+ var_dump($row1, $row2);
+}
+
+?>
+--EXPECT--
+int(1)
+int(2)
+int(2)
+int(1)
+
+int(1)
+int(2)
+int(2)
+int(1)
diff --git a/Zend/tests/fr47160.phpt b/Zend/tests/fr47160.phpt
index ed2f15f990..786183c0c1 100644
--- a/Zend/tests/fr47160.phpt
+++ b/Zend/tests/fr47160.phpt
@@ -5,7 +5,7 @@ Calling method from array
class Hello {
public function world($x) {
- echo "Hello, $x\n"; return $this;
+ echo "Hello, $x\n";return $this;
}
}
@@ -37,8 +37,16 @@ class Magic3 {
}
$f = array('Hello','world');
-var_dump($f('you'));
-var_dump(call_user_func($f, 'you'));
+try {
+ var_dump($f('you'));
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
+try {
+ var_dump(call_user_func($f, 'you'));
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
printf("-----\n");
@@ -101,35 +109,31 @@ var_dump(call_user_func($f, 'you'));
--EXPECTF--
Deprecated: Non-static method Hello::world() should not be called statically in %s on line %d
Hello, you
-
-Notice: Undefined variable: this in %s on line %d
-NULL
+Exception: Using $this when not in object context
Deprecated: %son-static method Hello::world() should not be called statically in %s on line %d
Hello, you
-
-Notice: Undefined variable: this in %s on line %d
-NULL
+Exception: Using $this when not in object context
-----
Hello, again
-object(Hello)#1 (0) {
+object(Hello)#%d (0) {
}
Hello, again
-object(Hello)#1 (0) {
+object(Hello)#%d (0) {
}
-----
Hello, there
-object(Hello)#2 (0) {
+object(Hello)#%d (0) {
}
Hello, there
-object(Hello)#2 (0) {
+object(Hello)#%d (0) {
}
-----
Hello, devs
-object(Hello)#4 (0) {
+object(Hello)#%d (0) {
}
Hello, devs
-object(Hello)#4 (0) {
+object(Hello)#%d (0) {
}
-----
Magic::__call called (foo)!
diff --git a/Zend/tests/func_get_args.phpt b/Zend/tests/func_get_args.phpt
new file mode 100644
index 0000000000..eea8ae4354
--- /dev/null
+++ b/Zend/tests/func_get_args.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Testing func_get_args()
+--FILE--
+<?php
+
+func_get_args();
+
+?>
+--EXPECTF--
+Warning: func_get_args(): Called from the global scope - no function context in %s on line 3
diff --git a/Zend/tests/function_arguments/argument_count_correct.phpt b/Zend/tests/function_arguments/argument_count_correct.phpt
new file mode 100644
index 0000000000..44a87b8ba8
--- /dev/null
+++ b/Zend/tests/function_arguments/argument_count_correct.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Call function with correct number of arguments
+--FILE--
+<?php
+function foo() { }
+foo();
+
+function bar($foo, $bar) { }
+bar(1, 2);
+
+function bat(int $foo, string $bar) { }
+bat(123, "foo");
+bat("123", "foo");
+
+$fp = fopen(__FILE__, "r");
+fclose($fp);
+
+echo "done";
+--EXPECT--
+done \ No newline at end of file
diff --git a/Zend/tests/function_arguments/argument_count_correct_strict.phpt b/Zend/tests/function_arguments/argument_count_correct_strict.phpt
new file mode 100644
index 0000000000..bfce61f0c9
--- /dev/null
+++ b/Zend/tests/function_arguments/argument_count_correct_strict.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Call function with correct number of arguments with strict types
+--FILE--
+<?php
+declare(strict_types=1);
+function foo() { }
+foo();
+
+function bar($foo, $bar) { }
+bar(1, 2);
+
+function bat(int $foo, string $bar) { }
+bat(123, "foo");
+
+$fp = fopen(__FILE__, "r");
+fclose($fp);
+
+echo "done";
+--EXPECT--
+done \ No newline at end of file
diff --git a/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt b/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt
new file mode 100644
index 0000000000..9d8d8bb7db
--- /dev/null
+++ b/Zend/tests/function_arguments/argument_count_incorrect_internal.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Call internal function with incorrect number of arguments
+--FILE--
+<?php
+substr("foo");
+array_diff([]);
+--EXPECTF--
+Warning: substr() expects at least 2 parameters, 1 given in %s
+
+Warning: array_diff(): at least 2 parameters are required, 1 given in %s \ No newline at end of file
diff --git a/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt b/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt
new file mode 100644
index 0000000000..33748649da
--- /dev/null
+++ b/Zend/tests/function_arguments/argument_count_incorrect_internal_strict.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Call internal function with incorrect number of arguments with strict types
+--FILE--
+<?php
+declare(strict_types=1);
+try {
+ substr("foo");
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+array_diff([]);
+--EXPECTF--
+ArgumentCountError
+substr() expects at least 2 parameters, 1 given
+
+Warning: array_diff(): at least 2 parameters are required, 1 given in %s \ No newline at end of file
diff --git a/Zend/tests/function_arguments/argument_count_incorrect_userland.phpt b/Zend/tests/function_arguments/argument_count_incorrect_userland.phpt
new file mode 100644
index 0000000000..97faa4eb5c
--- /dev/null
+++ b/Zend/tests/function_arguments/argument_count_incorrect_userland.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Call userland function with incorrect number of arguments
+--FILE--
+<?php
+try {
+ function foo($bar) { }
+ foo();
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ function bar($foo, $bar) { }
+ bar(1);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+function bat(int $foo, string $bar) { }
+
+try {
+ bat(123);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ bat("123");
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+--EXPECTF--
+ArgumentCountError
+Too few arguments to function foo(), 0 passed in %s and exactly 1 expected
+ArgumentCountError
+Too few arguments to function bar(), 1 passed in %s and exactly 2 expected
+ArgumentCountError
+Too few arguments to function bat(), 1 passed in %s and exactly 2 expected
+ArgumentCountError
+Too few arguments to function bat(), 1 passed in %s and exactly 2 expected \ No newline at end of file
diff --git a/Zend/tests/function_arguments/argument_count_incorrect_userland_strict.phpt b/Zend/tests/function_arguments/argument_count_incorrect_userland_strict.phpt
new file mode 100644
index 0000000000..9029dc2625
--- /dev/null
+++ b/Zend/tests/function_arguments/argument_count_incorrect_userland_strict.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Call userland function with incorrect number of arguments with strict types
+--FILE--
+<?php
+declare(strict_types=1);
+try {
+ function foo($bar) { }
+ foo();
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ function bar($foo, $bar) { }
+ bar(1);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+function bat(int $foo, string $bar) { }
+
+try {
+ bat(123);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ bat("123");
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ bat(123, 456);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+--EXPECTF--
+ArgumentCountError
+Too few arguments to function foo(), 0 passed in %s and exactly 1 expected
+ArgumentCountError
+Too few arguments to function bar(), 1 passed in %s and exactly 2 expected
+ArgumentCountError
+Too few arguments to function bat(), 1 passed in %s and exactly 2 expected
+TypeError
+Argument 1 passed to bat() must be of the type integer, string given, called in %s
+TypeError
+Argument 2 passed to bat() must be of the type string, integer given, called in %s \ No newline at end of file
diff --git a/Zend/tests/gc_013.phpt b/Zend/tests/gc_013.phpt
index 9209ca2b40..0c5424086a 100644
--- a/Zend/tests/gc_013.phpt
+++ b/Zend/tests/gc_013.phpt
@@ -10,9 +10,9 @@ for ($i = 0; $i < 10001; $i++) {
}
$a[] = "xxx";
unset($a);
-var_dump(gc_collect_cycles());
+var_dump(gc_collect_cycles() > 0);
echo "ok\n";
?>
--EXPECT--
-int(2)
+bool(true)
ok
diff --git a/Zend/tests/gc_014.phpt b/Zend/tests/gc_014.phpt
index cd5a15e681..4fd8948af5 100644
--- a/Zend/tests/gc_014.phpt
+++ b/Zend/tests/gc_014.phpt
@@ -12,9 +12,9 @@ for ($i = 0; $i < 10001; $i++) {
unset($b);
$a->b = "xxx";
unset($a);
-var_dump(gc_collect_cycles());
+var_dump(gc_collect_cycles() > 0);
echo "ok\n";
?>
--EXPECT--
-int(2)
+bool(true)
ok
diff --git a/Zend/tests/gc_015.phpt b/Zend/tests/gc_015.phpt
index df85836ed8..24acddeae1 100644
--- a/Zend/tests/gc_015.phpt
+++ b/Zend/tests/gc_015.phpt
@@ -12,9 +12,9 @@ $a->b = "xxx";
unset($c);
unset($a);
unset($b);
-var_dump(gc_collect_cycles());
+var_dump(gc_collect_cycles() > 0);
echo "ok\n";
?>
--EXPECT--
-int(2)
+bool(true)
ok
diff --git a/Zend/tests/gc_017.phpt b/Zend/tests/gc_017.phpt
index 50be61025f..a1a8c3eaf6 100644
--- a/Zend/tests/gc_017.phpt
+++ b/Zend/tests/gc_017.phpt
@@ -10,7 +10,6 @@ class Node {
public $parent;
function __construct($name) {
$this->name = $name;
- $this->children = array();
$this->parent = null;
}
function insert($node) {
@@ -32,12 +31,12 @@ $a->insert($c);
unset($a);
unset($b);
unset($c);
-var_dump(gc_collect_cycles());
+var_dump(gc_collect_cycles() >= 7);
echo "ok\n"
?>
--EXPECTF--
string(1) "%s"
string(1) "%s"
string(1) "%s"
-int(10)
+bool(true)
ok
diff --git a/Zend/tests/gc_033.phpt b/Zend/tests/gc_033.phpt
index bcd1541254..2db10196ad 100644
--- a/Zend/tests/gc_033.phpt
+++ b/Zend/tests/gc_033.phpt
@@ -1,5 +1,7 @@
--TEST--
GC 033: Crash in GC while run with phpspec
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
$a = new stdClass();
diff --git a/Zend/tests/gc_035.phpt b/Zend/tests/gc_035.phpt
index 985264c770..177c3101f9 100644
--- a/Zend/tests/gc_035.phpt
+++ b/Zend/tests/gc_035.phpt
@@ -1,5 +1,7 @@
--TEST--
GC 035: Lost inner-cycles garbage
+--INI--
+zend.enable_gc = 1
--FILE--
<?php
class A {
diff --git a/Zend/tests/generators/bug72523.phpt b/Zend/tests/generators/bug72523.phpt
new file mode 100644
index 0000000000..74dc583974
--- /dev/null
+++ b/Zend/tests/generators/bug72523.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #72523 (dtrace issue with reflection (failed test))
+--FILE--
+<?php
+
+$gen = (new class() {
+ function a() {
+ yield "okey";
+ }
+})->a();
+
+var_dump($gen->current());
+?>
+--EXPECT--
+string(4) "okey"
diff --git a/Zend/tests/generators/bug74157.phpt b/Zend/tests/generators/bug74157.phpt
new file mode 100644
index 0000000000..d5f0233aec
--- /dev/null
+++ b/Zend/tests/generators/bug74157.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #74157 (Segfault with nested generators)
+--FILE--
+<?php
+
+function a() {
+ $a = $b = $c = 2;
+ foreach(range(1, 5) as $v) {
+ yield $v;
+ }
+ return;
+}
+
+foreach (a(range(1, 3)) as $a) {
+ var_dump($a);
+}
+?>
+--EXPECTF--
+int(1)
+int(2)
+int(3)
+int(4)
+int(5)
diff --git a/Zend/tests/generators/bug74606.phpt b/Zend/tests/generators/bug74606.phpt
new file mode 100644
index 0000000000..cfb7f7f8cd
--- /dev/null
+++ b/Zend/tests/generators/bug74606.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #74606 (Segfault within try/catch/finally nesting in Generators)
+--FILE--
+<?php
+
+function gen() {
+ $array = ["foo"];
+ $array[] = "bar";
+
+ foreach ($array as $item) {
+ try {
+ try {
+ yield;
+ } finally {
+ echo "fin $item\n";
+ }
+ } catch (\Exception $e) {
+ echo "catch\n";
+ continue;
+ }
+ }
+}
+gen()->throw(new Exception);
+
+?>
+--EXPECT--
+fin foo
+catch
+fin bar
diff --git a/Zend/tests/generators/bug75396.phpt b/Zend/tests/generators/bug75396.phpt
new file mode 100644
index 0000000000..6d5abf518f
--- /dev/null
+++ b/Zend/tests/generators/bug75396.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #75396: Exit inside generator finally results in fatal error
+--FILE--
+<?php
+
+$gen = (function () {
+ yield 42;
+
+ try {
+ echo "Try\n";
+ exit("Exit\n");
+ } finally {
+ echo "Finally\n";
+ }
+})();
+
+$gen->send("x");
+
+?>
+--EXPECT--
+Try
+Exit
diff --git a/Zend/tests/generators/gc_with_root_parent_mismatch.phpt b/Zend/tests/generators/gc_with_root_parent_mismatch.phpt
new file mode 100644
index 0000000000..ee388b1c76
--- /dev/null
+++ b/Zend/tests/generators/gc_with_root_parent_mismatch.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Generator GC when the yield from parent chain does not reach the root
+--FILE--
+<?php
+
+function root() {
+ yield 1;
+ yield 2;
+}
+
+function delegate($gen) {
+ yield from $gen;
+}
+
+$gen = delegate(delegate(root()));
+$gen1 = delegate(delegate($gen));
+$gen2 = delegate(delegate($gen));
+var_dump($gen1->current());
+var_dump($gen2->current());
+$gen1->next();
+$gen1->next();
+gc_collect_cycles();
+
+?>
+--EXPECT--
+int(1)
+int(1)
diff --git a/Zend/tests/generators/gc_with_yield_from.phpt b/Zend/tests/generators/gc_with_yield_from.phpt
new file mode 100644
index 0000000000..952352c853
--- /dev/null
+++ b/Zend/tests/generators/gc_with_yield_from.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Verify yield from on generators being properly cycle collected
+--INI--
+zend.enable_gc = 1
+--FILE--
+<?php
+
+function root() {
+ global $gens; // create cyclic reference to root
+ try {
+ yield 1;
+ } finally {
+ var_dump($gens);
+ }
+}
+
+function gen($x) {
+ global $gens;
+ yield from $gens[] = $x ? gen(--$x) : root();
+}
+
+$gen = $gens[] = gen(2);
+var_dump($gen->current());
+unset($gen, $gens);
+print "collect\n";
+gc_collect_cycles();
+print "end\n";
+
+?>
+--EXPECT--
+int(1)
+collect
+array(4) {
+ [0]=>
+ object(Generator)#1 (0) {
+ }
+ [1]=>
+ object(Generator)#2 (0) {
+ }
+ [2]=>
+ object(Generator)#3 (0) {
+ }
+ [3]=>
+ object(Generator)#4 (0) {
+ }
+}
+end
diff --git a/Zend/tests/generators/generator_with_arg_unpacking.phpt b/Zend/tests/generators/generator_with_arg_unpacking.phpt
new file mode 100644
index 0000000000..edf0bafd31
--- /dev/null
+++ b/Zend/tests/generators/generator_with_arg_unpacking.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Generators with arguments unpacking
+--FILE--
+<?php
+(function() { yield; })(...range(1, 16384));
+call_user_func_array(function() { yield; }, range(1, 16384));
+$g = (function() { yield; })(...range(1, 16384));
+$g = call_user_func_array(function() { yield; }, range(1, 16384));
+echo "OK\n";
+?>
+--EXPECT--
+OK \ No newline at end of file
diff --git a/Zend/tests/generators/generator_with_type_check.phpt b/Zend/tests/generators/generator_with_type_check.phpt
new file mode 100644
index 0000000000..2aa16532dc
--- /dev/null
+++ b/Zend/tests/generators/generator_with_type_check.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Generator wit type check
+--FILE--
+<?php
+function gen(array $a) { yield; }
+gen(42);
+?>
+--EXPECTF--
+Fatal error: Uncaught TypeError: Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check.php on line 3 and defined in %sgenerator_with_type_check.php:2
+Stack trace:
+#0 %sgenerator_with_type_check.php(3): gen(42)
+#1 {main}
+ thrown in %sgenerator_with_type_check.php on line 2
diff --git a/Zend/tests/generators/generator_with_type_check_2.phpt b/Zend/tests/generators/generator_with_type_check_2.phpt
new file mode 100644
index 0000000000..d8ea4fbf0d
--- /dev/null
+++ b/Zend/tests/generators/generator_with_type_check_2.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Generator wit type check
+--FILE--
+<?php
+function gen(array $a) { yield; }
+try {
+ gen(42);
+} catch (TypeError $e) {
+ echo $e->getMessage()."\n";
+}
+
+try {
+ foreach (gen(42) as $val) {
+ var_dump($val);
+ }
+} catch (TypeError $e) {
+ echo $e->getMessage()."\n";
+}
+?>
+--EXPECTF--
+Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check_2.php on line 4
+Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check_2.php on line 10
diff --git a/Zend/tests/generators/return_from_by_ref_generator.phpt b/Zend/tests/generators/return_from_by_ref_generator.phpt
new file mode 100644
index 0000000000..32bebfbbde
--- /dev/null
+++ b/Zend/tests/generators/return_from_by_ref_generator.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Return from by-ref generator
+--FILE--
+<?php
+
+function &gen() {
+ yield;
+ $arr = [42];
+ return $arr[0];
+}
+
+function gen2() {
+ var_dump(yield from gen());
+}
+
+gen2()->next();
+
+?>
+--EXPECT--
+int(42)
diff --git a/Zend/tests/generators/yield_from_iterator_agregate.phpt b/Zend/tests/generators/yield_from_iterator_agregate.phpt
new file mode 100644
index 0000000000..3bd61e0b5a
--- /dev/null
+++ b/Zend/tests/generators/yield_from_iterator_agregate.phpt
@@ -0,0 +1,17 @@
+--TEST--
+yield from with an IteratorAggregate
+--FILE--
+<?php
+class foo implements \IteratorAggregate {
+ public $prop = 1;
+ function getIterator() {
+ var_dump($this->prop);
+ yield;
+ }
+}
+(function(){
+ yield from new foo;
+})()->next();
+?>
+--EXPECT--
+int(1)
diff --git a/Zend/tests/global_with_side_effect_name.phpt b/Zend/tests/global_with_side_effect_name.phpt
new file mode 100644
index 0000000000..a1ee240c48
--- /dev/null
+++ b/Zend/tests/global_with_side_effect_name.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Global variable import using a name with side effects
+--FILE--
+<?php
+
+function sf($arg) {
+ echo "called\n";
+ return $arg;
+}
+
+function test() {
+ global ${sf("a")};
+ var_dump($a);
+}
+
+$a = 42;
+test();
+
+?>
+--EXPECT--
+called
+int(42)
diff --git a/Zend/tests/incompat_ctx_user.phpt b/Zend/tests/incompat_ctx_user.phpt
index f05268cee9..25c95ba219 100644
--- a/Zend/tests/incompat_ctx_user.phpt
+++ b/Zend/tests/incompat_ctx_user.phpt
@@ -10,11 +10,12 @@ class B {
function bar() { A::foo(); }
}
$b = new B;
-$b->bar();
-
+try {
+ $b->bar();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
?>
--EXPECTF--
Deprecated: Non-static method A::foo() should not be called statically in %s on line %d
-
-Notice: Undefined variable: this in %s on line %d
-string(1) "A"
+Exception: Using $this when not in object context
diff --git a/Zend/tests/indexing_001.phpt b/Zend/tests/indexing_001.phpt
index 0e466ab8ce..f247a420b5 100644
--- a/Zend/tests/indexing_001.phpt
+++ b/Zend/tests/indexing_001.phpt
@@ -12,7 +12,7 @@ foreach ($testvalues as $testvalue) {
}
echo "\n*** Indexing - Testing reference assignment with key ***\n";
-$testvalues=array(null, 0, 1, true, false,'',0.1,array());
+$testvalues=array(null, 0, 1, true, false,0.1,array());
foreach ($testvalues as $testvalue) {
$testvalue['foo']=&$array;
@@ -20,7 +20,7 @@ foreach ($testvalues as $testvalue) {
}
echo "*** Indexing - Testing value assignment no key ***\n";
$array=array(1);
-$testvalues=array(null, 0, 1, true, false,'',0.1,array());
+$testvalues=array(null, 0, 1, true, false,0.1,array());
foreach ($testvalues as $testvalue) {
$testvalue[]=$array;
@@ -28,7 +28,7 @@ foreach ($testvalues as $testvalue) {
}
echo "\n*** Indexing - Testing reference assignment no key ***\n";
-$testvalues=array(null, 0, 1, true, false,'',0.1,array());
+$testvalues=array(null, 0, 1, true, false,0.1,array());
foreach ($testvalues as $testvalue) {
$testvalue[]=&$array;
@@ -63,13 +63,11 @@ array(1) {
int(1)
}
}
-array(1) {
- ["foo"]=>
- array(1) {
- [0]=>
- int(1)
- }
-}
+
+Warning: Illegal string offset 'foo' in %s on line %d
+
+Notice: Array to string conversion in %s on line %d
+string(1) "A"
Warning: Illegal string offset 'foo' in %s on line %d
@@ -110,13 +108,6 @@ array(1) {
int(1)
}
}
-array(1) {
- ["foo"]=>
- &array(1) {
- [0]=>
- int(1)
- }
-}
Warning: Cannot use a scalar value as an array in %s on line %d
float(0.1)
@@ -151,13 +142,6 @@ array(1) {
int(1)
}
}
-array(1) {
- [0]=>
- array(1) {
- [0]=>
- int(1)
- }
-}
Warning: Cannot use a scalar value as an array in %s on line %d
float(0.1)
@@ -193,13 +177,6 @@ array(1) {
int(1)
}
}
-array(1) {
- [0]=>
- &array(1) {
- [0]=>
- int(1)
- }
-}
Warning: Cannot use a scalar value as an array in %s on line %d
float(0.1)
@@ -211,4 +188,4 @@ array(1) {
}
}
-Done \ No newline at end of file
+Done
diff --git a/Zend/tests/indirect_call_array_003.phpt b/Zend/tests/indirect_call_array_003.phpt
index 498c580c48..f1dde491f6 100644
--- a/Zend/tests/indirect_call_array_003.phpt
+++ b/Zend/tests/indirect_call_array_003.phpt
@@ -17,8 +17,11 @@ class foo {
}
$arr = array('foo', 'abc');
-$arr();
-
+try {
+ $arr();
+} catch (Throwable $e) {
+ echo "Exception: " . $e->getMessage() . "\n";
+}
$foo = new foo;
$arr = array($foo, 'abc');
$arr();
@@ -28,9 +31,7 @@ $arr();
--EXPECTF--
From foo::__callStatic:
string(3) "abc"
-
-Notice: Undefined variable: this in %s on line %d
-NULL
+Exception: Using $this when not in object context
From foo::__call:
string(3) "abc"
object(foo)#%d (0) {
diff --git a/Zend/tests/inference_infinite_loop.phpt b/Zend/tests/inference_infinite_loop.phpt
new file mode 100644
index 0000000000..1e94ea8040
--- /dev/null
+++ b/Zend/tests/inference_infinite_loop.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Type inference should not result in infinite loop
+--FILE--
+<?php
+
+function test() {
+ $b = false;
+ do {
+ $a = $a + PHP_INT_MAX + 2;
+ $a = 0;
+ } while ($b);
+}
+test();
+
+?>
+--EXPECTF--
+Notice: Undefined variable: a in %s on line %d
diff --git a/Zend/tests/instanceof_001.phpt b/Zend/tests/instanceof_001.phpt
index b88e174c16..95e43ba506 100644
--- a/Zend/tests/instanceof_001.phpt
+++ b/Zend/tests/instanceof_001.phpt
@@ -26,4 +26,4 @@ bool(true)
bool(true)
bool(false)
-Catchable fatal error: Object of class stdClass could not be converted to string in %s on line %d
+Recoverable fatal error: Object of class stdClass could not be converted to string in %s on line %d
diff --git a/Zend/tests/int_conversion_exponents.phpt b/Zend/tests/int_conversion_exponents.phpt
new file mode 100644
index 0000000000..d924cb7b81
--- /dev/null
+++ b/Zend/tests/int_conversion_exponents.phpt
@@ -0,0 +1,52 @@
+--TEST--
+Integer conversion from scientific notation
+--FILE--
+<?php
+
+var_dump((int)"1.2345e9");
+var_dump((int)"-1.2345e9");
+var_dump(intval("1.2345e9"));
+var_dump(intval("-1.2345e9"));
+var_dump("1.2345e9" % PHP_INT_MAX);
+var_dump("-1.2345e9" % PHP_INT_MIN);
+var_dump("1.2345e9" | 0);
+var_dump("-1.2345e9" | 0);
+
+echo PHP_EOL;
+
+var_dump((int)" 1.2345e9 abc");
+var_dump((int)" -1.2345e9 abc");
+var_dump(intval(" 1.2345e9 abc"));
+var_dump(intval(" -1.2345e9 abc"));
+var_dump(" 1.2345e9 abc" % PHP_INT_MAX);
+var_dump(" -1.2345e9 abc" % PHP_INT_MIN);
+var_dump(" 1.2345e9 abc" | 0);
+var_dump(" -1.2345e9 abc" | 0);
+
+?>
+--EXPECTF--
+int(1234500000)
+int(-1234500000)
+int(1234500000)
+int(-1234500000)
+int(1234500000)
+int(-1234500000)
+int(1234500000)
+int(-1234500000)
+
+int(1234500000)
+int(-1234500000)
+int(1234500000)
+int(-1234500000)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(1234500000)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(-1234500000)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(1234500000)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(-1234500000)
diff --git a/Zend/tests/isset_str_offset.phpt b/Zend/tests/isset_str_offset.phpt
index 7a9164a381..d693f80a52 100644
--- a/Zend/tests/isset_str_offset.phpt
+++ b/Zend/tests/isset_str_offset.phpt
@@ -8,6 +8,7 @@ print "- isset ---\n";
$str = "test0123";
var_dump(isset($str[-1]));
+var_dump(isset($str[-10]));
var_dump(isset($str[0]));
var_dump(isset($str[1]));
var_dump(isset($str[4])); // 0
@@ -17,6 +18,7 @@ var_dump(isset($str[10000]));
// non-numeric offsets
print "- string ---\n";
var_dump(isset($str['-1']));
+var_dump(isset($str['-10']));
var_dump(isset($str['0']));
var_dump(isset($str['1']));
var_dump(isset($str['4'])); // 0
@@ -31,6 +33,7 @@ print "- null ---\n";
var_dump(isset($str[null]));
print "- double ---\n";
var_dump(isset($str[-1.1]));
+var_dump(isset($str[-10.5]));
var_dump(isset($str[-0.8]));
var_dump(isset($str[-0.1]));
var_dump(isset($str[0.2]));
@@ -50,6 +53,7 @@ print "done\n";
?>
--EXPECTF--
- isset ---
+bool(true)
bool(false)
bool(true)
bool(true)
@@ -58,6 +62,7 @@ bool(true)
bool(false)
bool(false)
- string ---
+bool(true)
bool(false)
bool(true)
bool(true)
@@ -72,6 +77,7 @@ bool(false)
- null ---
bool(true)
- double ---
+bool(true)
bool(false)
bool(true)
bool(true)
diff --git a/Zend/tests/jump16.phpt b/Zend/tests/jump16.phpt
new file mode 100644
index 0000000000..cc820c4a6c
--- /dev/null
+++ b/Zend/tests/jump16.phpt
@@ -0,0 +1,27 @@
+--TEST--
+jump 16: goto into try/catch
+--FILE--
+<?php
+goto a;
+try {
+ echo "1";
+a:
+ echo "2";
+ throw new Exception();
+} catch (Exception $e) {
+ echo "3";
+}
+echo "4";
+goto b;
+try {
+ echo "5";
+ throw new Exception();
+} catch (Exception $e) {
+ echo "6";
+b:
+ echo "7";
+}
+echo "8\n";
+?>
+--EXPECT--
+23478
diff --git a/Zend/tests/jump17.phpt b/Zend/tests/jump17.phpt
new file mode 100644
index 0000000000..92d3be511b
--- /dev/null
+++ b/Zend/tests/jump17.phpt
@@ -0,0 +1,22 @@
+--TEST--
+jump 17: goto into try/catch with finally
+--FILE--
+<?php
+goto b;
+try {
+ echo "1";
+a:
+ echo "2";
+ throw new Exception();
+} catch (Exception $e) {
+ echo "3";
+b:
+ echo "4";
+} finally {
+ echo "5";
+c:
+ echo "6";
+}
+echo "7\n";
+--EXPECT--
+4567
diff --git a/Zend/tests/list_001.phpt b/Zend/tests/list_001.phpt
index a9fff55004..4e0053edee 100644
--- a/Zend/tests/list_001.phpt
+++ b/Zend/tests/list_001.phpt
@@ -5,6 +5,8 @@
list($a, list($b)) = array(new stdclass, array(new stdclass));
var_dump($a, $b);
+[$a, [$b]] = array(new stdclass, array(new stdclass));
+var_dump($a, $b);
?>
--EXPECT--
@@ -12,3 +14,7 @@ object(stdClass)#1 (0) {
}
object(stdClass)#2 (0) {
}
+object(stdClass)#3 (0) {
+}
+object(stdClass)#4 (0) {
+}
diff --git a/Zend/tests/list_008.phpt b/Zend/tests/list_008.phpt
new file mode 100644
index 0000000000..de8160c77e
--- /dev/null
+++ b/Zend/tests/list_008.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Assignment to invalid list() value
+--FILE--
+<?php
+
+[42] = [1];
+
+?>
+--EXPECTF--
+Fatal error: Assignments can only happen to writable values in %s on line %d
diff --git a/Zend/tests/list_009.phpt b/Zend/tests/list_009.phpt
new file mode 100644
index 0000000000..c28ca8000a
--- /dev/null
+++ b/Zend/tests/list_009.phpt
@@ -0,0 +1,14 @@
+--TEST--
+list with by-reference assignment should fail
+--FILE--
+<?php
+
+$a = [1];
+[&$foo] = $a;
+$foo = 2;
+
+var_dump($a);
+
+?>
+--EXPECTF--
+Fatal error: [] and list() assignments cannot be by reference in %s on line %d
diff --git a/Zend/tests/list_010.phpt b/Zend/tests/list_010.phpt
new file mode 100644
index 0000000000..a89ffda5cd
--- /dev/null
+++ b/Zend/tests/list_010.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Do not allow mixing [] and list()
+--FILE--
+<?php
+
+list([$a]) = [[1]];
+var_dump($a);
+
+?>
+--EXPECTF--
+Fatal error: Cannot mix [] and list() in %s on line %d
diff --git a/Zend/tests/list_011.phpt b/Zend/tests/list_011.phpt
new file mode 100644
index 0000000000..316498c411
--- /dev/null
+++ b/Zend/tests/list_011.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Disallow list() usage as if it were an array
+--FILE--
+<?php
+
+var_dump(list(1, 2, 3));
+
+?>
+--EXPECTF--
+Parse error: syntax error, unexpected ')', expecting '=' in %s on line %d
diff --git a/Zend/tests/list_012.phpt b/Zend/tests/list_012.phpt
new file mode 100644
index 0000000000..072d28c01d
--- /dev/null
+++ b/Zend/tests/list_012.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Disallow empty elements in normal arrays
+--FILE--
+<?php
+
+var_dump([, 1, 2]);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use empty array elements in arrays in %s on line %d
diff --git a/Zend/tests/list_013.phpt b/Zend/tests/list_013.phpt
new file mode 100644
index 0000000000..2869f5f423
--- /dev/null
+++ b/Zend/tests/list_013.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Disallow tail empty elements in normal arrays
+--FILE--
+<?php
+
+var_dump([1, 2, ,]);
+
+?>
+--EXPECTF--
+Fatal error: Cannot use empty array elements in arrays in %s on line %d
diff --git a/Zend/tests/list_014.phpt b/Zend/tests/list_014.phpt
new file mode 100644
index 0000000000..7b77825f39
--- /dev/null
+++ b/Zend/tests/list_014.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Cannot destructure using array(), even if nested
+--FILE--
+<?php
+
+[array($a)] = [array(42)];
+var_dump($a);
+
+?>
+--EXPECTF--
+Fatal error: Cannot assign to array(), use [] instead in %s on line %d
diff --git a/Zend/tests/list_empty_error_keyed.phpt b/Zend/tests/list_empty_error_keyed.phpt
new file mode 100644
index 0000000000..f363d244f9
--- /dev/null
+++ b/Zend/tests/list_empty_error_keyed.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Cannot use empty elements in keyed array destructuring
+--FILE--
+<?php
+
+$array = ['a' => 1, 'b' => 2];
+['a' => $a, , 'b' => $b] = $array;
+
+?>
+--EXPECTF--
+Fatal error: Cannot use empty array entries in keyed array assignment in %s on line %d
diff --git a/Zend/tests/list_keyed.phpt b/Zend/tests/list_keyed.phpt
new file mode 100644
index 0000000000..b549ed9bf5
--- /dev/null
+++ b/Zend/tests/list_keyed.phpt
@@ -0,0 +1,71 @@
+--TEST--
+list() with keys
+--FILE--
+<?php
+
+$antonyms = [
+ "good" => "bad",
+ "happy" => "sad",
+];
+
+list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms;
+var_dump($good_antonym, $happy_antonym);
+
+echo PHP_EOL;
+
+$powersOfTwo = [
+ 1 => 2,
+ 2 => 4,
+ 3 => 8
+];
+
+list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo;
+var_dump($two_1, $two_2, $two_3);
+
+echo PHP_EOL;
+
+$contrivedMixedKeyTypesExample = [
+ 7 => "the best PHP version",
+ "elePHPant" => "the cutest mascot"
+];
+
+list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample;
+var_dump($seven, $elePHPant);
+
+echo PHP_EOL;
+
+$allTogetherNow = [
+ "antonyms" => $antonyms,
+ "powersOfTwo" => $powersOfTwo,
+ "contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample
+];
+
+list(
+ "antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym),
+ "powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3),
+ "contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant)
+) = $allTogetherNow;
+
+var_dump($good_antonym, $happy_antonym);
+var_dump($two_1, $two_2, $two_3);
+var_dump($seven, $elePHPant);
+
+?>
+--EXPECT--
+string(3) "bad"
+string(3) "sad"
+
+int(2)
+int(4)
+int(8)
+
+string(20) "the best PHP version"
+string(17) "the cutest mascot"
+
+string(3) "bad"
+string(3) "sad"
+int(2)
+int(4)
+int(8)
+string(20) "the best PHP version"
+string(17) "the cutest mascot"
diff --git a/Zend/tests/list_keyed_ArrayAccess.phpt b/Zend/tests/list_keyed_ArrayAccess.phpt
new file mode 100644
index 0000000000..1bb2013036
--- /dev/null
+++ b/Zend/tests/list_keyed_ArrayAccess.phpt
@@ -0,0 +1,54 @@
+--TEST--
+list() with keys and ArrayAccess
+--FILE--
+<?php
+
+$antonymObject = new ArrayObject;
+$antonymObject["good"] = "bad";
+$antonymObject["happy"] = "sad";
+
+list("good" => $good, "happy" => $happy) = $antonymObject;
+var_dump($good, $happy);
+
+echo PHP_EOL;
+
+$stdClassCollection = new SplObjectStorage;
+$foo = new StdClass;
+$stdClassCollection[$foo] = "foo";
+$bar = new StdClass;
+$stdClassCollection[$bar] = "bar";
+
+list($foo => $fooStr, $bar => $barStr) = $stdClassCollection;
+var_dump($fooStr, $barStr);
+
+echo PHP_EOL;
+
+class IndexPrinter implements ArrayAccess
+{
+ public function offsetGet($offset) {
+ echo "GET ";
+ var_dump($offset);
+ }
+ public function offsetSet($offset, $value) {
+ }
+ public function offsetExists($offset) {
+ }
+ public function offsetUnset($offset) {
+ }
+}
+
+$op = new IndexPrinter;
+list(123 => $x) = $op;
+// PHP shouldn't convert this to an integer offset, because it's ArrayAccess
+list("123" => $x) = $op;
+
+?>
+--EXPECT--
+string(3) "bad"
+string(3) "sad"
+
+string(3) "foo"
+string(3) "bar"
+
+GET int(123)
+GET string(3) "123"
diff --git a/Zend/tests/list_keyed_conversions.phpt b/Zend/tests/list_keyed_conversions.phpt
new file mode 100644
index 0000000000..bf0349b327
--- /dev/null
+++ b/Zend/tests/list_keyed_conversions.phpt
@@ -0,0 +1,34 @@
+--TEST--
+list() with non-integer-or-string keys
+--FILE--
+<?php
+
+$results = [
+ 0 => 0,
+ 1 => 1,
+ "" => ""
+];
+
+list(NULL => $NULL, 1.5 => $float, FALSE => $FALSE, TRUE => $TRUE) = $results;
+var_dump($NULL, $float, $FALSE, $TRUE);
+
+echo PHP_EOL;
+
+list("0" => $zeroString, "1" => $oneString) = $results;
+var_dump($zeroString, $oneString);
+
+list(STDIN => $resource) = [];
+
+?>
+--EXPECTF--
+string(0) ""
+int(1)
+int(0)
+int(1)
+
+int(0)
+int(1)
+
+Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
+
+Notice: Undefined offset: 1 in %s on line %d
diff --git a/Zend/tests/list_keyed_evaluation_order.inc b/Zend/tests/list_keyed_evaluation_order.inc
new file mode 100644
index 0000000000..490a6d84fe
--- /dev/null
+++ b/Zend/tests/list_keyed_evaluation_order.inc
@@ -0,0 +1,60 @@
+<?php declare(strict_types=1);
+
+// Observer objects for the Zend/tests/list_keyed_evaluation_order.* tests
+
+class Stringable
+{
+ private $name;
+ public function __construct(string $name) {
+ $this->name = $name;
+ }
+
+ public function __toString(): string {
+ echo "$this->name evaluated.", PHP_EOL;
+ return $this->name;
+ }
+}
+
+class Indexable implements ArrayAccess
+{
+ private $array;
+ public function __construct(array $array) {
+ $this->array = $array;
+ }
+
+ public function offsetExists($offset): bool {
+ echo "Existence of offset $offset checked for.", PHP_EOL;
+ return isset($this->array[$offset]);
+ }
+
+ public function offsetUnset($offset): void {
+ unset($this->array[$offset]);
+ echo "Offset $offset removed.", PHP_EOL;
+ }
+
+ public function offsetGet($offset) {
+ echo "Offset $offset retrieved.", PHP_EOL;
+ return $this->array[$offset];
+ }
+
+ public function offsetSet($offset, $value): void {
+ $this->array[$offset] = $value;
+ echo "Offset $offset set to $value.", PHP_EOL;
+ }
+}
+
+class IndexableRetrievable
+{
+ private $label;
+ private $indexable;
+
+ public function __construct(string $label, Indexable $indexable) {
+ $this->label = $label;
+ $this->indexable = $indexable;
+ }
+
+ public function getIndexable(): Indexable {
+ echo "Indexable $this->label retrieved.", PHP_EOL;
+ return $this->indexable;
+ }
+}
diff --git a/Zend/tests/list_keyed_evaluation_order.phpt b/Zend/tests/list_keyed_evaluation_order.phpt
new file mode 100644
index 0000000000..0f0652b6a9
--- /dev/null
+++ b/Zend/tests/list_keyed_evaluation_order.phpt
@@ -0,0 +1,35 @@
+--TEST--
+list() with keys, evaluation order
+--FILE--
+<?php
+
+require_once "list_keyed_evaluation_order.inc";
+
+$a = new Stringable("A");
+$c = new Stringable("C");
+
+$e = new IndexableRetrievable("E", new Indexable(["A" => "value for offset A", "C" => "value for offset C"]));
+
+$store = new Indexable([]);
+
+// list($a => $b, $c => $d) = $e;
+// Should be evaluated in the order:
+// 1. Evaluate $e
+// 2. Evaluate $a
+// 3. Evaluate $e[$a]
+// 4. Assign $b from $e[$a]
+// 5. Evaluate $c
+// 6. Evaluate $e[$c]
+// 7. Assign $c from $e[$a]
+
+list((string)$a => $store["B"], (string)$c => $store["D"]) = $e->getIndexable();
+
+?>
+--EXPECT--
+Indexable E retrieved.
+A evaluated.
+Offset A retrieved.
+Offset B set to value for offset A.
+C evaluated.
+Offset C retrieved.
+Offset D set to value for offset C.
diff --git a/Zend/tests/list_keyed_evaluation_order_2.phpt b/Zend/tests/list_keyed_evaluation_order_2.phpt
new file mode 100644
index 0000000000..ddfba68c46
--- /dev/null
+++ b/Zend/tests/list_keyed_evaluation_order_2.phpt
@@ -0,0 +1,77 @@
+--TEST--
+list() with keys, evaluation order #2
+--FILE--
+<?php
+
+// All the following should print 'a' then 'b'
+
+list($a, $b) = ['a', 'b'];
+var_dump($a);
+var_dump($b);
+
+list(0 => $a, 1 => $b) = ['a', 'b'];
+var_dump($a);
+var_dump($b);
+
+list(1 => $b, 0 => $a) = ['a', 'b'];
+var_dump($a);
+var_dump($b);
+
+$arr = [];
+list($arr[], $arr[]) = ['a', 'b'];
+var_dump($arr[0]);
+var_dump($arr[1]);
+
+$arr = [];
+list(0 => $arr[], 1 => $arr[]) = ['a', 'b'];
+var_dump($arr[0]);
+var_dump($arr[1]);
+
+$arr = [];
+list(1 => $arr[], 0 => $arr[]) = ['b', 'a'];
+var_dump($arr[0]);
+var_dump($arr[1]);
+
+$arr = [];
+list(list(1 => $arr[], 0 => $arr[])) = [['b', 'a']];
+var_dump($arr[0]);
+var_dump($arr[1]);
+
+$arr = [];
+list('key1' => $arr[], 'key2' => $arr[]) = ['key2' => 'b', 'key1' => 'a'];
+var_dump($arr[0]);
+var_dump($arr[1]);
+
+// This should print 'foo'
+$a = 0;
+list($a => $a) = ['foo', 'bar'];
+var_dump($a);
+
+// This should print 'bar' then 'foo'
+$a = 0;
+$b = 1;
+list($b => $a, $a => $c) = ['bar' => 'foo', 1 => 'bar'];
+var_dump($a);
+var_dump($c);
+
+?>
+--EXPECT--
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(1) "a"
+string(1) "b"
+string(3) "foo"
+string(3) "bar"
+string(3) "foo"
diff --git a/Zend/tests/list_keyed_evaluation_order_3.phpt b/Zend/tests/list_keyed_evaluation_order_3.phpt
new file mode 100644
index 0000000000..7850834c3b
--- /dev/null
+++ b/Zend/tests/list_keyed_evaluation_order_3.phpt
@@ -0,0 +1,24 @@
+--TEST--
+list() with keys, evaluation order #3
+--FILE--
+<?php
+
+$i = 0;
+$a = [
+ 0 => [
+ 'b' => 'bar',
+ 'a' => 'foo',
+ ],
+ 1 => 'a',
+ 3 => 'b',
+];
+list($a[$i++] => $a[$i++], $a[$i++] => $a[$i++]) = $a[$i++];
+var_dump($i); // should be 5
+var_dump($a[2]); // should be 'foo'
+var_dump($a[4]); // should be 'bar'
+
+?>
+--EXPECT--
+int(5)
+string(3) "foo"
+string(3) "bar"
diff --git a/Zend/tests/list_keyed_evaluation_order_nested.phpt b/Zend/tests/list_keyed_evaluation_order_nested.phpt
new file mode 100644
index 0000000000..8a7725d4ea
--- /dev/null
+++ b/Zend/tests/list_keyed_evaluation_order_nested.phpt
@@ -0,0 +1,77 @@
+--TEST--
+list() with keys, evaluation order: nested
+--FILE--
+<?php
+
+require_once "list_keyed_evaluation_order.inc";
+
+$a = new Stringable("A");
+$c = new Stringable("C");
+$f = new Stringable("F");
+$g = new Stringable("G");
+$i = new Stringable("I");
+
+$k = new IndexableRetrievable("K", new Indexable([
+ "A" => "offset value for A",
+ "C" => new Indexable([
+ 0 => "offset value for 0",
+ 1 => "offset value for 1"
+ ]),
+ "F" => new Indexable([
+ "G" => "offset value for G",
+ "I" => "offset value for I"
+ ])
+]));
+
+$store = new Indexable([]);
+
+// list($a => $b, $c => list($d, $e), $f => list($g => $h, $i => $j)) = $k;
+// Should be evaluated in the order:
+// 1. Evaluate $k
+// 2. Evaluate $a
+// 3. Evaluate $k[$a]
+// 4. Assign $b from $k[$a]
+// 5. Evaluate $c
+// 6. Evaluate $k[$c]
+// 7. Evaluate $k[$c][0]
+// 8. Assign $d from $k[$c][0]
+// 9. Evaluate $k[$c][1]
+// 10. Assign $e from $k[$c][1]
+// 11. Evaluate $f
+// 12. Evaluate $k[$f]
+// 13. Evaluate $g
+// 14. Evaluate $k[$f][$g]
+// 15. Assign $h from $k[$f][$g]
+// 16. Evaluate $i
+// 17. Evaluate $k[$f][$i]
+// 18. Assign $j from $k[$f][$i]
+
+list(
+ (string)$a => $store["B"],
+ (string)$c => list($store["D"], $store["E"]),
+ (string)$f => list(
+ (string)$g => $store["H"],
+ (string)$i => $store["J"]
+ )
+) = $k->getIndexable();
+
+?>
+--EXPECT--
+Indexable K retrieved.
+A evaluated.
+Offset A retrieved.
+Offset B set to offset value for A.
+C evaluated.
+Offset C retrieved.
+Offset 0 retrieved.
+Offset D set to offset value for 0.
+Offset 1 retrieved.
+Offset E set to offset value for 1.
+F evaluated.
+Offset F retrieved.
+G evaluated.
+Offset G retrieved.
+Offset H set to offset value for G.
+I evaluated.
+Offset I retrieved.
+Offset J set to offset value for I.
diff --git a/Zend/tests/list_keyed_non_literals.phpt b/Zend/tests/list_keyed_non_literals.phpt
new file mode 100644
index 0000000000..80f22eda22
--- /dev/null
+++ b/Zend/tests/list_keyed_non_literals.phpt
@@ -0,0 +1,30 @@
+--TEST--
+list() with constant keys
+--FILE--
+<?php
+
+$arr = [
+ 1 => "one",
+ 2 => "two",
+ 3 => "three"
+];
+
+const COMPILE_TIME_RESOLVABLE = 1;
+
+define('PROBABLY_NOT_COMPILE_TIME_RESOLVABLE', file_get_contents("data:text/plain,2"));
+
+$probablyNotCompileTimeResolvable3 = cos(0) * 3;
+
+list(
+ COMPILE_TIME_RESOLVABLE => $one,
+ PROBABLY_NOT_COMPILE_TIME_RESOLVABLE => $two,
+ $probablyNotCompileTimeResolvable3 => $three
+) = $arr;
+
+var_dump($one, $two, $three);
+
+?>
+--EXPECTF--
+string(3) "one"
+string(3) "two"
+string(5) "three"
diff --git a/Zend/tests/list_keyed_trailing_comma.phpt b/Zend/tests/list_keyed_trailing_comma.phpt
new file mode 100644
index 0000000000..e0af0aed21
--- /dev/null
+++ b/Zend/tests/list_keyed_trailing_comma.phpt
@@ -0,0 +1,38 @@
+--TEST--
+list() with keys and a trailing comma
+--FILE--
+<?php
+
+$antonyms = [
+ "good" => "bad",
+ "happy" => "sad",
+];
+
+list(
+ "good" => $good,
+ "happy" => $happy
+) = $antonyms;
+
+var_dump($good, $happy);
+
+echo PHP_EOL;
+
+$antonyms = [
+ "good" => "bad",
+ "happy" => "sad",
+];
+
+list(
+ "good" => $good,
+ "happy" => $happy,
+) = $antonyms;
+
+var_dump($good, $happy);
+
+?>
+--EXPECT--
+string(3) "bad"
+string(3) "sad"
+
+string(3) "bad"
+string(3) "sad"
diff --git a/Zend/tests/list_keyed_undefined.phpt b/Zend/tests/list_keyed_undefined.phpt
new file mode 100644
index 0000000000..a18e3b4d20
--- /dev/null
+++ b/Zend/tests/list_keyed_undefined.phpt
@@ -0,0 +1,22 @@
+--TEST--
+list() with undefined keys
+--FILE--
+<?php
+
+$contrivedMixedKeyTypesExample = [
+ 7 => "the best PHP version",
+ "elePHPant" => "the cutest mascot"
+];
+
+list(5 => $five, "duke" => $duke) = $contrivedMixedKeyTypesExample;
+
+var_dump($five, $duke);
+
+?>
+--EXPECTF--
+
+Notice: Undefined offset: 5 in %s on line %d
+
+Notice: Undefined index: duke in %s on line %d
+NULL
+NULL
diff --git a/Zend/tests/list_mixed_keyed_unkeyed.phpt b/Zend/tests/list_mixed_keyed_unkeyed.phpt
new file mode 100644
index 0000000000..245d20f31f
--- /dev/null
+++ b/Zend/tests/list_mixed_keyed_unkeyed.phpt
@@ -0,0 +1,16 @@
+--TEST--
+list() with both keyed and unkeyed elements
+--FILE--
+<?php
+
+$contrivedKeyedAndUnkeyedArrayExample = [
+ 0,
+ 1 => 1,
+ "foo" => "bar"
+];
+
+list($zero, 1 => $one, "foo" => $foo) = $contrivedKeyedAndUnkeyedArrayExample;
+
+?>
+--EXPECTF--
+Fatal error: Cannot mix keyed and unkeyed array entries in assignments in %s on line %d
diff --git a/Zend/tests/list_mixed_nested_keyed_unkeyed.phpt b/Zend/tests/list_mixed_nested_keyed_unkeyed.phpt
new file mode 100644
index 0000000000..3087775b76
--- /dev/null
+++ b/Zend/tests/list_mixed_nested_keyed_unkeyed.phpt
@@ -0,0 +1,34 @@
+--TEST--
+list() with nested unkeyed and keyed list()
+--FILE--
+<?php
+
+$points = [
+ ["x" => 1, "y" => 2],
+ ["x" => 2, "y" => 1]
+];
+
+list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points;
+var_dump($x1, $y1, $x2, $y2);
+
+echo PHP_EOL;
+
+$invertedPoints = [
+ "x" => [1, 2],
+ "y" => [2, 1]
+];
+
+list("x" => list($x1, $x2), "y" => list($y1, $y2)) = $invertedPoints;
+var_dump($x1, $y1, $x2, $y2);
+
+?>
+--EXPECT--
+int(1)
+int(2)
+int(2)
+int(1)
+
+int(1)
+int(2)
+int(2)
+int(1)
diff --git a/Zend/tests/method_argument_binding.phpt b/Zend/tests/method_argument_binding.phpt
new file mode 100644
index 0000000000..dea12621a3
--- /dev/null
+++ b/Zend/tests/method_argument_binding.phpt
@@ -0,0 +1,46 @@
+--TEST--
+Edge cases in compile-time method argument binding
+--FILE--
+<?php
+
+class A {
+ private function method($x) {}
+}
+
+class B extends A {
+ public function test() {
+ $x = 1;
+ $this->method($x);
+ var_dump($x);
+ }
+}
+
+class C extends B {
+ public function method(&$x) {
+ ++$x;
+ }
+}
+
+(new C)->test();
+
+class D {
+ private final function method(&$x) {
+ ++$x;
+ }
+}
+
+class E extends D {
+ public function __call($name, $args) { }
+
+ public function test() {
+ $this->method($x);
+ }
+}
+
+(new E)->test();
+
+?>
+--EXPECTF--
+int(2)
+
+Notice: Undefined variable: x in %s on line %d
diff --git a/Zend/tests/neg_num_string.phpt b/Zend/tests/neg_num_string.phpt
new file mode 100644
index 0000000000..018568adea
--- /dev/null
+++ b/Zend/tests/neg_num_string.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Test edge-cases for negative num strings in interpolated string offsets
+--FILE--
+<?php
+
+$a = [
+ "0" => 1,
+ "-0" => 2,
+ "1" => 3,
+ "-1" => 4,
+ "0x0" => 5,
+ "-0x0" => 6,
+ "00" => 7,
+ "-00" => 8,
+ "9223372036854775808" => 9,
+ "-9223372036854775808" => 10,
+ "2147483648" => 11,
+ "-2147483648" => 12,
+];
+
+var_dump("$a[0]");
+var_dump("$a[-0]");
+var_dump("$a[1]");
+var_dump("$a[-1]");
+var_dump("$a[0x0]");
+var_dump("$a[-0x0]");
+var_dump("$a[00]");
+var_dump("$a[-00]");
+var_dump("$a[9223372036854775808]");
+var_dump("$a[-9223372036854775808]");
+var_dump("$a[2147483648]");
+var_dump("$a[-2147483648]");
+
+?>
+--EXPECT--
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(2) "10"
+string(2) "11"
+string(2) "12"
diff --git a/Zend/tests/new_args_without_ctor.phpt b/Zend/tests/new_args_without_ctor.phpt
new file mode 100644
index 0000000000..91456890d2
--- /dev/null
+++ b/Zend/tests/new_args_without_ctor.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Argument of new on class without constructor are evaluated
+--FILE--
+<?php
+
+new stdClass(print 'a', print 'b');
+
+?>
+--EXPECT--
+ab
diff --git a/Zend/tests/ns_071.phpt b/Zend/tests/ns_071.phpt
index 2f2fcfad1a..d7f1592b38 100644
--- a/Zend/tests/ns_071.phpt
+++ b/Zend/tests/ns_071.phpt
@@ -18,7 +18,7 @@ new bar(new \stdclass);
--EXPECTF--
NULL
-Fatal error: Uncaught TypeError: Argument 1 passed to foo\bar::__construct() must be of the type array, object given, called in %s on line %d and defined in %s:%d
+Fatal error: Uncaught TypeError: Argument 1 passed to foo\bar::__construct() must be of the type array or null, object given, called in %s on line %d and defined in %s:%d
Stack trace:
#0 %s(%d): foo\bar->__construct(Object(stdClass))
#1 {main}
diff --git a/Zend/tests/ns_072.phpt b/Zend/tests/ns_072.phpt
index 6375682890..34a9bbf6ad 100644
--- a/Zend/tests/ns_072.phpt
+++ b/Zend/tests/ns_072.phpt
@@ -30,7 +30,7 @@ object(foo\test)#%d (0) {
}
NULL
-Fatal error: Uncaught TypeError: Argument 1 passed to foo\bar::__construct() must implement interface foo\foo, instance of stdClass given, called in %s on line %d and defined in %s:%d
+Fatal error: Uncaught TypeError: Argument 1 passed to foo\bar::__construct() must implement interface foo\foo or be null, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:
#0 %s(%d): foo\bar->__construct(Object(stdClass))
#1 {main}
diff --git a/Zend/tests/nullable_types/array.phpt b/Zend/tests/nullable_types/array.phpt
new file mode 100644
index 0000000000..7b0a2ed4d5
--- /dev/null
+++ b/Zend/tests/nullable_types/array.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Explicitly nullable array type
+--FILE--
+<?php
+
+function _array_(?array $v): ?array {
+ return $v;
+}
+
+var_dump(_array_(null));
+var_dump(_array_([]));
+
+--EXPECT--
+NULL
+array(0) {
+}
+
diff --git a/Zend/tests/nullable_types/contravariant_nullable_param_succeeds.phpt b/Zend/tests/nullable_types/contravariant_nullable_param_succeeds.phpt
new file mode 100644
index 0000000000..f4d1e315fc
--- /dev/null
+++ b/Zend/tests/nullable_types/contravariant_nullable_param_succeeds.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Subtype can add nullability to a parameter (contravariance)
+
+--FILE--
+<?php
+
+interface A {
+ function method(int $p);
+}
+
+class B implements A {
+ function method(?int $p) { }
+}
+
+$b = new B();
+$b->method(null);
+
+--EXPECT--
+
diff --git a/Zend/tests/nullable_types/contravariant_nullable_return_fails.phpt b/Zend/tests/nullable_types/contravariant_nullable_return_fails.phpt
new file mode 100644
index 0000000000..c9be479ead
--- /dev/null
+++ b/Zend/tests/nullable_types/contravariant_nullable_return_fails.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Return type cannot add nullability (contravariance)
+
+--FILE--
+<?php
+
+interface A {
+ function method(): int;
+}
+
+interface B extends A {
+ function method(): ?int;
+}
+
+--EXPECTF--
+Fatal error: Declaration of B::method(): ?int must be compatible with A::method(): int in %s on line %d
+
diff --git a/Zend/tests/nullable_types/covariant_nullable_param_fails.phpt b/Zend/tests/nullable_types/covariant_nullable_param_fails.phpt
new file mode 100644
index 0000000000..65b2858e6b
--- /dev/null
+++ b/Zend/tests/nullable_types/covariant_nullable_param_fails.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Subtype cannot remove nullable parameter (covariance)
+
+--FILE--
+<?php
+
+interface A {
+ function method(?int $p);
+}
+
+class B implements A {
+ function method(int $p) { }
+}
+
+--EXPECTF--
+Fatal error: Declaration of B::method(int $p) must be compatible with A::method(?int $p) in %s on line %d
+
diff --git a/Zend/tests/nullable_types/covariant_nullable_return_succeds.phpt b/Zend/tests/nullable_types/covariant_nullable_return_succeds.phpt
new file mode 100644
index 0000000000..5776f9b99d
--- /dev/null
+++ b/Zend/tests/nullable_types/covariant_nullable_return_succeds.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Nullable covariant return types
+
+--FILE--
+<?php
+
+interface A {
+ function method(): ?int;
+}
+
+interface B extends A {
+ function method(): int;
+}
+
+--EXPECT--
+
diff --git a/Zend/tests/nullable_types/float.phpt b/Zend/tests/nullable_types/float.phpt
new file mode 100644
index 0000000000..8e44524cf0
--- /dev/null
+++ b/Zend/tests/nullable_types/float.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Explicitly nullable float type
+--FILE--
+<?php
+
+function _float_(?float $v): ?float {
+ return $v;
+}
+
+var_dump(_float_(null));
+var_dump(_float_(1.3));
+
+--EXPECT--
+NULL
+float(1.3)
+
diff --git a/Zend/tests/nullable_types/int.phpt b/Zend/tests/nullable_types/int.phpt
new file mode 100644
index 0000000000..ec75132edb
--- /dev/null
+++ b/Zend/tests/nullable_types/int.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Explicitly nullable int type
+--FILE--
+<?php
+
+function _int_(?int $v): ?int {
+ return $v;
+}
+
+var_dump(_int_(null));
+var_dump(_int_(1));
+
+--EXPECT--
+NULL
+int(1)
+
diff --git a/Zend/tests/nullable_types/invariant_param_and_return_succeeds.phpt b/Zend/tests/nullable_types/invariant_param_and_return_succeeds.phpt
new file mode 100644
index 0000000000..0542e52c0f
--- /dev/null
+++ b/Zend/tests/nullable_types/invariant_param_and_return_succeeds.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Invariant parameter and return types work with nullable types
+
+--FILE--
+<?php
+
+interface A {
+ function method(?int $i): ?int;
+}
+
+class B implements A {
+ function method(?int $i): ?int {
+ return $i;
+ }
+}
+
+$b = new B();
+var_dump($b->method(null));
+var_dump($b->method(1));
+
+--EXPECT--
+NULL
+int(1)
+
diff --git a/Zend/tests/nullable_types/nullable_type_parameters_do_not_have_default_value.phpt b/Zend/tests/nullable_types/nullable_type_parameters_do_not_have_default_value.phpt
new file mode 100644
index 0000000000..3050feed53
--- /dev/null
+++ b/Zend/tests/nullable_types/nullable_type_parameters_do_not_have_default_value.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Explicit nullable types do not imply a default value
+
+--FILE--
+<?php
+
+function f(?callable $p) {}
+
+f();
+
+--EXPECTF--
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function f(), 0 passed in %snullable_type_parameters_do_not_have_default_value.php on line %d and exactly 1 expected in %s:%d
+Stack trace:
+#%d %s
+#%d %s
+ thrown in %s on line %d
+
diff --git a/Zend/tests/nullable_types/string.phpt b/Zend/tests/nullable_types/string.phpt
new file mode 100644
index 0000000000..ffc6591b6b
--- /dev/null
+++ b/Zend/tests/nullable_types/string.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Explicitly nullable string type
+--FILE--
+<?php
+
+function _string_(?string $v): ?string {
+ return $v;
+}
+
+var_dump(_string_(null));
+var_dump(_string_("php"));
+
+--EXPECT--
+NULL
+string(3) "php"
+
diff --git a/Zend/tests/numeric_string_errors.phpt b/Zend/tests/numeric_string_errors.phpt
new file mode 100644
index 0000000000..e98c58dda7
--- /dev/null
+++ b/Zend/tests/numeric_string_errors.phpt
@@ -0,0 +1,195 @@
+--TEST--
+Invalid numeric string E_WARNINGs and E_NOTICEs
+--FILE--
+<?php
+
+var_dump("2 Lorem" + "3 ipsum");
+var_dump("dolor" + "sit");
+echo "---", PHP_EOL;
+var_dump("5 amet," - "7 consectetur");
+var_dump("adipiscing" - "elit,");
+echo "---", PHP_EOL;
+var_dump("11 sed" * "13 do");
+var_dump("eiusmod" * "tempor");
+echo "---", PHP_EOL;
+var_dump("17 incididunt" / "19 ut");
+var_dump("labore" / "et");
+echo "---", PHP_EOL;
+var_dump("23 dolore" ** "29 magna");
+var_dump("aliqua." ** "Ut");
+echo "---", PHP_EOL;
+var_dump("31 enim" % "37 ad");
+try {
+ var_dump("minim" % "veniam,");
+} catch (DivisionByZeroError $e) {
+}
+echo "---", PHP_EOL;
+var_dump("41 minim" << "43 veniam,");
+var_dump("quis" << "nostrud");
+echo "---", PHP_EOL;
+var_dump("47 exercitation" >> "53 ullamco");
+var_dump("laboris" >> "nisi");
+echo "---", PHP_EOL;
+var_dump("59 ut" | 61);
+var_dump(67 | "71 aliquip");
+var_dump("ex" | 73);
+var_dump(79 | "ea");
+echo "---", PHP_EOL;
+var_dump("83 commodo" & 89);
+var_dump(97 & "101 consequat.");
+var_dump("Duis" & 103);
+var_dump(107 & "aute");
+echo "---", PHP_EOL;
+var_dump("109 irure" ^ 113);
+var_dump(127 ^ "131 dolor");
+var_dump("in" ^ 137);
+var_dump(139 ^ "reprehenderit");
+echo "---", PHP_EOL;
+var_dump(+"149 in");
+var_dump(+"voluptate");
+echo "---", PHP_EOL;
+var_dump(-"151 velit");
+var_dump(-"esse");
+?>
+--EXPECTF--
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(5)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(-2)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(143)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+float(0.89473684210526)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: Division by zero in %s on line %d
+float(NAN)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+float(3.0910586430935E+39)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(1)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(31)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(%d)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(0)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(63)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(71)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(73)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(79)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(81)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(97)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(28)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(252)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(137)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(139)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(149)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(-151)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
diff --git a/Zend/tests/numeric_string_errors_assign.phpt b/Zend/tests/numeric_string_errors_assign.phpt
new file mode 100644
index 0000000000..8d882aadcc
--- /dev/null
+++ b/Zend/tests/numeric_string_errors_assign.phpt
@@ -0,0 +1,236 @@
+--TEST--
+Invalid numeric string E_WARNINGs and E_NOTICEs, combined assignment operations
+--FILE--
+<?php
+
+// prevents CT eval
+function foxcache($val) {
+ return [$val][0];
+}
+
+$a = foxcache("2 Lorem");
+$a += "3 ipsum";
+var_dump($a);
+$a = foxcache("dolor");
+$a += "sit";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("5 amet,");
+$a -= "7 consectetur";
+var_dump($a);
+$a = foxcache("adipiscing");
+$a -= "elit,";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("11 sed");
+$a *= "13 do";
+var_dump($a);
+$a = foxcache("eiusmod");
+$a *= "tempor";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("17 incididunt");
+$a /= "19 ut";
+var_dump($a);
+$a = foxcache("labore");
+$a /= "et";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("23 dolore");
+$a **= "29 magna";
+var_dump($a);
+$a = foxcache("aliqua.");
+$a **= "Ut";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("31 enim");
+$a %= "37 ad";
+var_dump($a);
+try {
+ $a = foxcache("minim");
+ $a %= "veniam,";
+ var_dump($a);
+} catch (DivisionByZeroError $e) {
+}
+echo "---", PHP_EOL;
+$a = foxcache("41 minim");
+$a <<= "43 veniam,";
+var_dump($a);
+$a = foxcache("quis");
+$a <<= "nostrud";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("47 exercitation");
+$a >>= "53 ullamco";
+var_dump($a);
+$a = foxcache("laboris");
+$a >>= "nisi";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("59 ut");
+$a |= 61;
+var_dump($a);
+$a = foxcache(67);
+$a |= "71 aliquip";
+var_dump($a);
+$a = foxcache("ex");
+$a |= 73;
+var_dump($a);
+$a = foxcache(79);
+$a |= "ea";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("83 commodo");
+$a &= 89;
+var_dump($a);
+$a = foxcache(97);
+$a &= "101 consequat.";
+var_dump($a);
+$a = foxcache("Duis");
+$a &= 103;
+var_dump($a);
+$a = foxcache(107);
+$a &= "aute";
+var_dump($a);
+echo "---", PHP_EOL;
+$a = foxcache("109 irure");
+$a ^= 113;
+var_dump($a);
+$a = foxcache(127);
+$a ^= "131 dolor";
+var_dump($a);
+$a = foxcache("in");
+$a ^= 137;
+var_dump($a);
+$a = foxcache(139);
+$a ^= "reprehenderit";
+var_dump($a);
+?>
+--EXPECTF--
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(5)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(-2)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(143)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+float(0.89473684210526)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: Division by zero in %s on line %d
+float(NAN)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+float(3.0910586430935E+39)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(1)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(31)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(%d)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(0)
+
+Warning: A non-numeric value encountered in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(63)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(71)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(73)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(79)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(81)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(97)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(0)
+---
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(28)
+
+Notice: A non well formed numeric value encountered in %s on line %d
+int(252)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(137)
+
+Warning: A non-numeric value encountered in %s on line %d
+int(139)
diff --git a/Zend/tests/objects_022.phpt b/Zend/tests/objects_022.phpt
index 01f961bae1..5f537feaf4 100644
--- a/Zend/tests/objects_022.phpt
+++ b/Zend/tests/objects_022.phpt
@@ -25,7 +25,7 @@ $foo = new foo;
$foo->testFoo(new foo);
$foo->testBar(new bar);
$foo->testBaz(new baz);
-$foo->testFoo(new stdClass); // Catchable fatal error
+$foo->testFoo(new stdClass); // Recoverable fatal error
?>
--EXPECTF--
diff --git a/Zend/tests/oct_overflow_char.phpt b/Zend/tests/oct_overflow_char.phpt
new file mode 100644
index 0000000000..32060d8593
--- /dev/null
+++ b/Zend/tests/oct_overflow_char.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Octal overflow in string interpolation
+--FILE--
+<?php
+
+// "abc", ordinarily 'b' would be \142, but we'll deliberately overflow the value by \400
+echo "\141\542\143\n";
+--EXPECTF--
+Warning: Octal escape sequence overflow \542 is greater than \377 in %s%eoct_overflow_char.php on line 4
+abc
diff --git a/Zend/tests/overloaded_func_001.phpt b/Zend/tests/overloaded_func_001.phpt
new file mode 100644
index 0000000000..2702772a46
--- /dev/null
+++ b/Zend/tests/overloaded_func_001.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Overloaded function 001
+--SKIPIF--
+<?php
+if (!PHP_DEBUG) die("skip only run in debug version");
+?>
+--FILE--
+<?php
+var_dump(_ZendTestClass::test());
+?>
+--EXPECTF--
+Fatal error: Uncaught Error: Cannot call overloaded function for non-object in %soverloaded_func_001.php:%d
+Stack trace:
+#0 {main}
+ thrown in %soverloaded_func_001.php on line %d
diff --git a/Zend/tests/overloaded_func_002.phpt b/Zend/tests/overloaded_func_002.phpt
new file mode 100644
index 0000000000..6c16965919
--- /dev/null
+++ b/Zend/tests/overloaded_func_002.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Overloaded function 002
+--SKIPIF--
+<?php
+if (!PHP_DEBUG) die("skip only run in debug version");
+?>
+--FILE--
+<?php
+$a = new _ZendTestClass();
+var_dump($a->{trim(" test")}());
+?>
+--EXPECT--
+string(4) "test"
diff --git a/Zend/tests/parse_str_with_unpack.phpt b/Zend/tests/parse_str_with_unpack.phpt
new file mode 100644
index 0000000000..50b296d710
--- /dev/null
+++ b/Zend/tests/parse_str_with_unpack.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Calling parse_str through argument unpacking
+--FILE--
+<?php
+
+function test() {
+ $i = 0;
+ parse_str(...["i=41"]);
+ var_dump($i + 1);
+}
+test();
+
+?>
+--EXPECT--
+int(42)
diff --git a/Zend/tests/php_errormsg_misoptimization.phpt b/Zend/tests/php_errormsg_misoptimization.phpt
new file mode 100644
index 0000000000..c121c1021a
--- /dev/null
+++ b/Zend/tests/php_errormsg_misoptimization.phpt
@@ -0,0 +1,20 @@
+--TEST--
+The variable $php_errormsg shouldn't be optimized as it may be unpredictably modified
+--INI--
+track_errors=1
+--FILE--
+<?php
+
+function test() {
+ $php_errormsg = 1;
+ echo $undef;
+ var_dump($php_errormsg + 1);
+}
+test();
+
+?>
+--EXPECTF--
+Notice: Undefined variable: undef in %s on line %d
+
+Warning: A non-numeric value encountered in %s on line %d
+int(1)
diff --git a/Zend/tests/return_types/029.phpt b/Zend/tests/return_types/029.phpt
index 011182df37..adc07cde7f 100644
--- a/Zend/tests/return_types/029.phpt
+++ b/Zend/tests/return_types/029.phpt
@@ -9,14 +9,19 @@ function foo() : array {
try {
throw new Exception("xxxx");
} finally {
- return ;
+ return null;
}
}
foo();
?>
--EXPECTF--
-Fatal error: Uncaught TypeError: Return value of foo() must be of the type array, none returned in %s29.php:%d
+Fatal error: Uncaught Exception: xxxx in %s:%d
+Stack trace:
+#0 %s(%d): foo()
+#1 {main}
+
+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/030.phpt b/Zend/tests/return_types/030.phpt
new file mode 100644
index 0000000000..288137f05c
--- /dev/null
+++ b/Zend/tests/return_types/030.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Nullable return value
+--FILE--
+<?php
+function foo($x) : ?array {
+ return $x;
+}
+
+foo([]);
+echo "ok\n";
+foo(null);
+echo "ok\n";
+foo(0);
+?>
+--EXPECTF--
+ok
+ok
+
+Fatal error: Uncaught TypeError: Return value of foo() must be of the type array or null, integer returned in %s030.php:3
+Stack trace:
+#0 %s030.php(10): foo(0)
+#1 {main}
+ thrown in %s030.php on line 3
diff --git a/Zend/tests/return_types/031.phpt b/Zend/tests/return_types/031.phpt
new file mode 100644
index 0000000000..91ee2f8ce4
--- /dev/null
+++ b/Zend/tests/return_types/031.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Nullable return type inheritance rules (non-nullable and nullable)
+--FILE--
+<?php
+class A {
+ function foo(): int {}
+}
+class B extends A {
+ function foo(): ?int {}
+}
+?>
+DONE
+--EXPECTF--
+Fatal error: Declaration of B::foo(): ?int must be compatible with A::foo(): int in %s031.php on line 7 \ No newline at end of file
diff --git a/Zend/tests/return_types/032.phpt b/Zend/tests/return_types/032.phpt
new file mode 100644
index 0000000000..00790b5d60
--- /dev/null
+++ b/Zend/tests/return_types/032.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Nullable return type inheritance rules (nullable and non-nullable)
+--FILE--
+<?php
+class A {
+ function foo(): ?int {}
+}
+class B extends A {
+ function foo(): int {}
+}
+?>
+DONE
+--EXPECT--
+DONE
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/return_types/generators002.phpt b/Zend/tests/return_types/generators002.phpt
index f7dbfda69b..519c97a962 100644
--- a/Zend/tests/return_types/generators002.phpt
+++ b/Zend/tests/return_types/generators002.phpt
@@ -8,4 +8,4 @@ function test1() : StdClass {
}
--EXPECTF--
-Fatal error: Generators may only declare a return type of Generator, Iterator or Traversable, StdClass is not permitted in %s on line %d
+Fatal error: Generators may only declare a return type of Generator, Iterator, Traversable, or iterable, StdClass is not permitted in %s on line %d
diff --git a/Zend/tests/return_types/void_allowed.phpt b/Zend/tests/return_types/void_allowed.phpt
new file mode 100644
index 0000000000..8f07c7392e
--- /dev/null
+++ b/Zend/tests/return_types/void_allowed.phpt
@@ -0,0 +1,20 @@
+--TEST--
+void return type: acceptable cases
+--FILE--
+<?php
+
+function foo(): void {
+ // okay
+}
+
+foo();
+
+function bar(): void {
+ return; // okay
+}
+
+bar();
+
+echo "OK!", PHP_EOL;
+--EXPECT--
+OK!
diff --git a/Zend/tests/return_types/void_disallowed1.phpt b/Zend/tests/return_types/void_disallowed1.phpt
new file mode 100644
index 0000000000..365e2060bf
--- /dev/null
+++ b/Zend/tests/return_types/void_disallowed1.phpt
@@ -0,0 +1,12 @@
+--TEST--
+void return type: unacceptable cases: explicit NULL return
+--FILE--
+<?php
+
+function foo(): void {
+ return NULL; // not permitted in a void function
+}
+
+// Note the lack of function call: function validated at compile-time
+--EXPECTF--
+Fatal error: A void function must not return a value (did you mean "return;" instead of "return null;"?) in %s on line %d
diff --git a/Zend/tests/return_types/void_disallowed2.phpt b/Zend/tests/return_types/void_disallowed2.phpt
new file mode 100644
index 0000000000..7bbc3ac24f
--- /dev/null
+++ b/Zend/tests/return_types/void_disallowed2.phpt
@@ -0,0 +1,12 @@
+--TEST--
+void return type: unacceptable cases: explicit return of some other value
+--FILE--
+<?php
+
+function foo(): void {
+ return -1; // not permitted in a void function
+}
+
+// Note the lack of function call: function validated at compile-time
+--EXPECTF--
+Fatal error: A void function must not return a value in %s on line %d
diff --git a/Zend/tests/return_types/void_parameter.phpt b/Zend/tests/return_types/void_parameter.phpt
new file mode 100644
index 0000000000..4c6e918406
--- /dev/null
+++ b/Zend/tests/return_types/void_parameter.phpt
@@ -0,0 +1,8 @@
+--TEST--
+void return type: not valid as a parameter type
+--FILE--
+<?php
+
+function foobar(void $a) {}
+--EXPECTF--
+Fatal error: void cannot be used as a parameter type in %s on line %d
diff --git a/Zend/tests/self_and.phpt b/Zend/tests/self_and.phpt
index e9ddc849eb..071eb509cb 100644
--- a/Zend/tests/self_and.phpt
+++ b/Zend/tests/self_and.phpt
@@ -28,7 +28,11 @@ echo "Done\n";
?>
--EXPECTF--
int(18)
+
+Warning: A non-numeric value encountered in %s on line %d
int(0)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(33)
string(1) " "
string(2) " "
diff --git a/Zend/tests/self_instanceof_outside_class.phpt b/Zend/tests/self_instanceof_outside_class.phpt
new file mode 100644
index 0000000000..4caef37883
--- /dev/null
+++ b/Zend/tests/self_instanceof_outside_class.phpt
@@ -0,0 +1,17 @@
+--TEST--
+instanceof self outside a class
+--FILE--
+<?php
+
+$fn = function() {
+ try {
+ new stdClass instanceof self;
+ } catch (Error $e) {
+ echo $e->getMessage(), "\n";
+ }
+};
+$fn();
+
+?>
+--EXPECT--
+Cannot access self:: when no class scope is active
diff --git a/Zend/tests/self_method_or_prop_outside_class.phpt b/Zend/tests/self_method_or_prop_outside_class.phpt
new file mode 100644
index 0000000000..e4a499def8
--- /dev/null
+++ b/Zend/tests/self_method_or_prop_outside_class.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Accessing self:: properties or methods outside a class
+--FILE--
+<?php
+
+$fn = function() {
+ $str = "foo";
+ try {
+ self::${$str . "bar"};
+ } catch (Error $e) {
+ echo $e->getMessage(), "\n";
+ }
+ try {
+ unset(self::${$str . "bar"});
+ } catch (Error $e) {
+ echo $e->getMessage(), "\n";
+ }
+ try {
+ isset(self::${$str . "bar"});
+ } catch (Error $e) {
+ echo $e->getMessage(), "\n";
+ }
+ try {
+ self::{$str . "bar"}();
+ } catch (Error $e) {
+ echo $e->getMessage(), "\n";
+ }
+};
+$fn();
+
+?>
+--EXPECT--
+Cannot access self:: when no class scope is active
+Cannot access self:: when no class scope is active
+Cannot access self:: when no class scope is active
+Cannot access self:: when no class scope is active
diff --git a/Zend/tests/self_mod.phpt b/Zend/tests/self_mod.phpt
index 19e45d88fc..0b10987aeb 100644
--- a/Zend/tests/self_mod.phpt
+++ b/Zend/tests/self_mod.phpt
@@ -20,6 +20,10 @@ echo "Done\n";
?>
--EXPECTF--
int(13)
+
+Warning: A non-numeric value encountered in %s on line %d
int(0)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(3)
Done
diff --git a/Zend/tests/self_or.phpt b/Zend/tests/self_or.phpt
index 991aafa980..cecf70d795 100644
--- a/Zend/tests/self_or.phpt
+++ b/Zend/tests/self_or.phpt
@@ -28,7 +28,11 @@ echo "Done\n";
?>
--EXPECTF--
int(127)
+
+Warning: A non-numeric value encountered in %s on line %d
int(11)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(45345)
string(1) "f"
string(2) "ff"
diff --git a/Zend/tests/self_xor.phpt b/Zend/tests/self_xor.phpt
index f306a9cd69..e36a315b10 100644
--- a/Zend/tests/self_xor.phpt
+++ b/Zend/tests/self_xor.phpt
@@ -28,7 +28,11 @@ echo "Done\n";
?>
--EXPECTF--
int(109)
+
+Warning: A non-numeric value encountered in %s on line %d
int(11)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(45312)
string(1) "F"
string(2) "FF"
diff --git a/Zend/tests/shift_001.phpt b/Zend/tests/shift_001.phpt
index aeb399452d..7546f1a6d8 100644
--- a/Zend/tests/shift_001.phpt
+++ b/Zend/tests/shift_001.phpt
@@ -20,6 +20,10 @@ echo "Done\n";
?>
--EXPECTF--
int(492)
+
+Warning: A non-numeric value encountered in %s on line %d
int(0)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(362760)
Done
diff --git a/Zend/tests/shift_002.phpt b/Zend/tests/shift_002.phpt
index 4d8421a566..6288152585 100644
--- a/Zend/tests/shift_002.phpt
+++ b/Zend/tests/shift_002.phpt
@@ -20,6 +20,10 @@ echo "Done\n";
?>
--EXPECTF--
int(30)
+
+Warning: A non-numeric value encountered in %s on line %d
int(0)
+
+Notice: A non well formed numeric value encountered in %s on line %d
int(5668)
Done
diff --git a/Zend/tests/str_offset_001.phpt b/Zend/tests/str_offset_001.phpt
index 8a6b91b49a..3317674857 100644
--- a/Zend/tests/str_offset_001.phpt
+++ b/Zend/tests/str_offset_001.phpt
@@ -1,51 +1,46 @@
---TEST--
-string offset 001
---FILE--
-<?php
-function foo($x) {
- var_dump($x);
-}
-
-$str = "abc";
-var_dump($str[-1]);
-var_dump($str[0]);
-var_dump($str[1]);
-var_dump($str[2]);
-var_dump($str[3]);
-var_dump($str[1][0]);
-var_dump($str[2][1]);
-
-foo($str[-1]);
-foo($str[0]);
-foo($str[1]);
-foo($str[2]);
-foo($str[3]);
-foo($str[1][0]);
-foo($str[2][1]);
-?>
---EXPECTF--
-Notice: Uninitialized string offset: -1 in %sstr_offset_001.php on line %d
-string(0) ""
-string(1) "a"
-string(1) "b"
-string(1) "c"
-
-Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d
-string(0) ""
-string(1) "b"
-
-Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d
-string(0) ""
-
-Notice: Uninitialized string offset: -1 in %sstr_offset_001.php on line %d
-string(0) ""
-string(1) "a"
-string(1) "b"
-string(1) "c"
-
-Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d
-string(0) ""
-string(1) "b"
-
-Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d
-string(0) ""
+--TEST--
+string offset 001
+--FILE--
+<?php
+// Test positive or null string offsets
+
+function foo($x) {
+ var_dump($x);
+}
+
+$str = "abc";
+var_dump($str[0]);
+var_dump($str[1]);
+var_dump($str[2]);
+var_dump($str[3]);
+var_dump($str[1][0]);
+var_dump($str[2][1]);
+
+foo($str[0]);
+foo($str[1]);
+foo($str[2]);
+foo($str[3]);
+foo($str[1][0]);
+foo($str[2][1]);
+?>
+--EXPECTF--
+string(1) "a"
+string(1) "b"
+string(1) "c"
+
+Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "b"
+
+Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "a"
+string(1) "b"
+string(1) "c"
+
+Notice: Uninitialized string offset: 3 in %sstr_offset_001.php on line %d
+string(0) ""
+string(1) "b"
+
+Notice: Uninitialized string offset: 1 in %sstr_offset_001.php on line %d
+string(0) ""
diff --git a/Zend/tests/str_offset_003.phpt b/Zend/tests/str_offset_003.phpt
new file mode 100644
index 0000000000..e357ac0c01
--- /dev/null
+++ b/Zend/tests/str_offset_003.phpt
@@ -0,0 +1,37 @@
+--TEST--
+string offset 003
+--FILE--
+<?php
+// Test negative string offsets
+
+function foo($x) {
+ var_dump($x);
+}
+
+$str = "abcdef";
+var_dump($str[-10]);
+var_dump($str[-3]);
+var_dump($str[2][-2]);
+var_dump($str[2][-1]);
+
+foo($str[-10]);
+foo($str[-3]);
+foo($str[2][-2]);
+foo($str[2][-1]);
+?>
+--EXPECTF--
+Notice: Uninitialized string offset: -10 in %sstr_offset_003.php on line %d
+string(0) ""
+string(1) "d"
+
+Notice: Uninitialized string offset: -2 in %sstr_offset_003.php on line %d
+string(0) ""
+string(1) "c"
+
+Notice: Uninitialized string offset: -10 in %sstr_offset_003.php on line %d
+string(0) ""
+string(1) "d"
+
+Notice: Uninitialized string offset: -2 in %sstr_offset_003.php on line %d
+string(0) ""
+string(1) "c"
diff --git a/Zend/tests/str_offset_004.phpt b/Zend/tests/str_offset_004.phpt
new file mode 100644
index 0000000000..c8ce607535
--- /dev/null
+++ b/Zend/tests/str_offset_004.phpt
@@ -0,0 +1,49 @@
+--TEST--
+string offset 004
+--FILE--
+<?php
+// Test assignments using (positive and negative) string offsets
+
+$str = "abcdefghijklmno";
+$i = 3;
+$j = -4;
+
+$str{2} = 'C';
+var_dump($str);
+
+$str{$i} = 'Z';
+var_dump($str);
+
+$str{-5} = 'P';
+var_dump($str);
+
+$str{$j} = 'Q';
+var_dump($str);
+
+$str{-20} = 'Y';
+var_dump($str);
+
+$str{-strlen($str)} = strtoupper($str{0}); /* An exotic ucfirst() ;) */
+var_dump($str);
+
+$str{20} = 'N';
+var_dump($str);
+
+$str{-2} = 'UFO';
+var_dump($str);
+
+$str{-$i} = $str{$j*2};
+var_dump($str);
+?>
+--EXPECTF--
+string(15) "abCdefghijklmno"
+string(15) "abCZefghijklmno"
+string(15) "abCZefghijPlmno"
+string(15) "abCZefghijPQmno"
+
+Warning: Illegal string offset: -20 in %sstr_offset_004.php on line %d
+string(15) "abCZefghijPQmno"
+string(15) "AbCZefghijPQmno"
+string(21) "AbCZefghijPQmno N"
+string(21) "AbCZefghijPQmno UN"
+string(21) "AbCZefghijPQmno nUN"
diff --git a/Zend/tests/string_offset_errors.phpt b/Zend/tests/string_offset_errors.phpt
new file mode 100644
index 0000000000..b709408c35
--- /dev/null
+++ b/Zend/tests/string_offset_errors.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Some string offset errors
+--FILE--
+<?php
+
+function &test() : string {
+ $str = "foo";
+ return $str[0];
+}
+
+try {
+ test();
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+
+try {
+ $str = "foo";
+ $str[0] =& $str[1];
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+Cannot return string offsets by reference
+Cannot create references to/from string offsets
diff --git a/Zend/tests/temporary_cleaning_001.phpt b/Zend/tests/temporary_cleaning_001.phpt
index 40340bc3da..f2ccbb35b8 100644
--- a/Zend/tests/temporary_cleaning_001.phpt
+++ b/Zend/tests/temporary_cleaning_001.phpt
@@ -1,7 +1,5 @@
--TEST--
Temporary leak on exception
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_003.phpt b/Zend/tests/temporary_cleaning_003.phpt
index 0f7d9450eb..acff8c85f0 100644
--- a/Zend/tests/temporary_cleaning_003.phpt
+++ b/Zend/tests/temporary_cleaning_003.phpt
@@ -1,7 +1,5 @@
--TEST--
Fundamental memory leak test on temporaries
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_004.phpt b/Zend/tests/temporary_cleaning_004.phpt
index e2b093654f..b8a02516b0 100644
--- a/Zend/tests/temporary_cleaning_004.phpt
+++ b/Zend/tests/temporary_cleaning_004.phpt
@@ -1,7 +1,5 @@
--TEST--
Temporary leak with switch
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_005.phpt b/Zend/tests/temporary_cleaning_005.phpt
index f671c32543..e8c7febe0b 100644
--- a/Zend/tests/temporary_cleaning_005.phpt
+++ b/Zend/tests/temporary_cleaning_005.phpt
@@ -1,7 +1,5 @@
--TEST--
Temporary leak with foreach
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_006.phpt b/Zend/tests/temporary_cleaning_006.phpt
index 435e7b12dd..a7936d3915 100644
--- a/Zend/tests/temporary_cleaning_006.phpt
+++ b/Zend/tests/temporary_cleaning_006.phpt
@@ -1,7 +1,5 @@
--TEST--
Exception after separation during indirect write to fcall result
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_008.phpt b/Zend/tests/temporary_cleaning_008.phpt
new file mode 100644
index 0000000000..fabd3b4b38
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_008.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Optimization of constant switch expression
+--FILE--
+<?php
+try {
+ switch ("1" . (int)2) {
+ case 12:
+ throw new Exception();
+ }
+} catch (Exception $e) {
+ echo "exception\n";
+}
+?>
+--EXPECT--
+exception
diff --git a/Zend/tests/temporary_cleaning_009.phpt b/Zend/tests/temporary_cleaning_009.phpt
new file mode 100644
index 0000000000..32a84a6ffd
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_009.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Live range & free on return
+--FILE--
+<?php
+class bar {
+ public $foo = 1;
+ public $bar = 1;
+
+ function __destruct() {
+ throw $this->foo;
+ }
+}
+foreach (new bar as &$foo) {
+ try {
+ $foo = new Exception;
+ return; // frees the loop variable
+ } catch (Exception $e) {
+ echo "exception\n";
+ }
+}
+echo "end\n";
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception in %stemporary_cleaning_009.php:12
+Stack trace:
+#0 {main}
+ thrown in %stemporary_cleaning_009.php on line 12
diff --git a/Zend/tests/temporary_cleaning_010.phpt b/Zend/tests/temporary_cleaning_010.phpt
new file mode 100644
index 0000000000..e4456041b2
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_010.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Live range & throw from finally
+--FILE--
+<?php
+function test() {
+ try {
+ $a = [1, 2, 3];
+ return $a + [];
+ } finally {
+ throw new Exception;
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo "exception\n";
+}
+?>
+--EXPECT--
+exception
diff --git a/Zend/tests/temporary_cleaning_011.phpt b/Zend/tests/temporary_cleaning_011.phpt
new file mode 100644
index 0000000000..e4a6af3ab9
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_011.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Live range & lists
+--FILE--
+<?php
+class A {
+ function __destruct() {
+ throw new Exception();
+ }
+}
+$b = new A();
+$x = 0;
+$c = [[$x,$x]];
+try {
+ list($a, $b) = $c[0];
+} catch (Exception $e) {
+ echo "exception\n";
+}
+?>
+--EXPECT--
+exception
diff --git a/Zend/tests/temporary_cleaning_012.phpt b/Zend/tests/temporary_cleaning_012.phpt
new file mode 100644
index 0000000000..fdbea6d41d
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_012.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Live range of ZEND_NEW must be assigned to correct variable
+--FILE--
+<?php
+
+class Foo {
+ public static function test() {
+ self::$property = new self;
+ }
+}
+
+try {
+ Foo::test();
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+Access to undeclared static property: Foo::$property
diff --git a/Zend/tests/this_as_global.phpt b/Zend/tests/this_as_global.phpt
new file mode 100644
index 0000000000..0ba9ade1b9
--- /dev/null
+++ b/Zend/tests/this_as_global.phpt
@@ -0,0 +1,12 @@
+--TEST--
+$this as global variable
+--FILE--
+<?php
+function foo() {
+ global $this;
+ var_dump($this);
+}
+foo();
+?>
+--EXPECTF--
+Fatal error: Cannot use $this as global variable in %sthis_as_global.php on line 3
diff --git a/Zend/tests/this_as_parameter.phpt b/Zend/tests/this_as_parameter.phpt
new file mode 100644
index 0000000000..93101969a7
--- /dev/null
+++ b/Zend/tests/this_as_parameter.phpt
@@ -0,0 +1,11 @@
+--TEST--
+$this as parameter
+--FILE--
+<?php
+function foo($this) {
+ var_dump($this);
+}
+foo(5);
+?>
+--EXPECTF--
+Fatal error: Cannot use $this as parameter in %sthis_as_parameter.php on line 2
diff --git a/Zend/tests/this_as_static.phpt b/Zend/tests/this_as_static.phpt
new file mode 100644
index 0000000000..f094449c12
--- /dev/null
+++ b/Zend/tests/this_as_static.phpt
@@ -0,0 +1,12 @@
+--TEST--
+$this as static variable
+--FILE--
+<?php
+function foo() {
+ static $this;
+ var_dump($this);
+}
+foo();
+?>
+--EXPECTF--
+Fatal error: Cannot use $this as static variable in %sthis_as_static.php on line 3
diff --git a/Zend/tests/this_in_catch.phpt b/Zend/tests/this_in_catch.phpt
new file mode 100644
index 0000000000..d621bb18ea
--- /dev/null
+++ b/Zend/tests/this_in_catch.phpt
@@ -0,0 +1,18 @@
+--TEST--
+$this in catch
+--FILE--
+<?php
+class C {
+ function foo() {
+ try {
+ throw new Exception();
+ } catch (Exception $this) {
+ }
+ var_dump($this);
+ }
+}
+$obj = new C;
+$obj->foo();
+?>
+--EXPECTF--
+Fatal error: Cannot re-assign $this in %sthis_in_catch.php on line 6
diff --git a/Zend/tests/this_in_extract.phpt b/Zend/tests/this_in_extract.phpt
new file mode 100644
index 0000000000..de8da3d0a5
--- /dev/null
+++ b/Zend/tests/this_in_extract.phpt
@@ -0,0 +1,17 @@
+--TEST--
+$this re-assign in extract()
+--FILE--
+<?php
+function foo() {
+ extract(["this"=>42]);
+ var_dump($this);
+}
+foo();
+?>
+--EXPECTF--
+Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_extract.php:3
+Stack trace:
+#0 %sthis_in_extract.php(3): extract(Array)
+#1 %sthis_in_extract.php(6): foo()
+#2 {main}
+ thrown in %sthis_in_extract.php on line 3
diff --git a/Zend/tests/this_in_foreach_001.phpt b/Zend/tests/this_in_foreach_001.phpt
new file mode 100644
index 0000000000..a724338b90
--- /dev/null
+++ b/Zend/tests/this_in_foreach_001.phpt
@@ -0,0 +1,11 @@
+--TEST--
+$this in foreach
+--FILE--
+<?php
+$a = [1];
+foreach ($a as $this) {
+ var_dump($this);
+}
+?>
+--EXPECTF--
+Fatal error: Cannot re-assign $this in %sthis_in_foreach_001.php on line 3
diff --git a/Zend/tests/this_in_foreach_002.phpt b/Zend/tests/this_in_foreach_002.phpt
new file mode 100644
index 0000000000..511ea36a24
--- /dev/null
+++ b/Zend/tests/this_in_foreach_002.phpt
@@ -0,0 +1,11 @@
+--TEST--
+$this in foreach
+--FILE--
+<?php
+$a = [1];
+foreach ($a as $this => $dummy) {
+ var_dump($this);
+}
+?>
+--EXPECTF--
+Fatal error: Cannot re-assign $this in %sthis_in_foreach_002.php on line 3
diff --git a/Zend/tests/this_in_foreach_003.phpt b/Zend/tests/this_in_foreach_003.phpt
new file mode 100644
index 0000000000..5f5b5ae0d8
--- /dev/null
+++ b/Zend/tests/this_in_foreach_003.phpt
@@ -0,0 +1,11 @@
+--TEST--
+$this in foreach
+--FILE--
+<?php
+$a = [1];
+foreach ($a as &$this) {
+ var_dump($this);
+}
+?>
+--EXPECTF--
+Fatal error: Cannot re-assign $this in %sthis_in_foreach_003.php on line 3
diff --git a/Zend/tests/this_in_foreach_004.phpt b/Zend/tests/this_in_foreach_004.phpt
new file mode 100644
index 0000000000..13bfbf18b4
--- /dev/null
+++ b/Zend/tests/this_in_foreach_004.phpt
@@ -0,0 +1,11 @@
+--TEST--
+$this in foreach
+--FILE--
+<?php
+$a = [[1]];
+foreach ($a as list($this)) {
+ var_dump($this);
+}
+?>
+--EXPECTF--
+Fatal error: Cannot re-assign $this in %sthis_in_foreach_004.php on line 3
diff --git a/Zend/tests/this_in_isset.phpt b/Zend/tests/this_in_isset.phpt
new file mode 100644
index 0000000000..2ae335df93
--- /dev/null
+++ b/Zend/tests/this_in_isset.phpt
@@ -0,0 +1,41 @@
+--TEST--
+$this in isset
+--FILE--
+<?php
+var_dump(isset($this));
+try {
+ var_dump(isset($this->foo));
+} catch (Throwable $e) {
+ echo "exception\n";
+}
+try {
+ var_dump(isset($this->foo->bar));
+} catch (Throwable $e) {
+ echo "exception\n";
+}
+try {
+ var_dump(isset($this[0]));
+} catch (Throwable $e) {
+ echo "exception\n";
+}
+
+class A extends ArrayObject {
+ public $foo = 5;
+ function foo() {
+ $this[0] = 5;
+ var_dump(isset($this));
+ var_dump(isset($this->foo));
+ var_dump(isset($this[0]));
+ }
+}
+$a = new A();
+$a->foo();
+?>
+--EXPECT--
+bool(false)
+exception
+exception
+exception
+bool(true)
+bool(true)
+bool(true)
diff --git a/Zend/tests/this_in_mb_parse_str.phpt b/Zend/tests/this_in_mb_parse_str.phpt
new file mode 100644
index 0000000000..8dfac94722
--- /dev/null
+++ b/Zend/tests/this_in_mb_parse_str.phpt
@@ -0,0 +1,19 @@
+--TEST--
+$this re-assign in mb_parse_str()
+--SKIPIF--
+<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FILE--
+<?php
+function foo() {
+ mb_parse_str("this=42");
+ var_dump($this);
+}
+foo();
+?>
+--EXPECTF--
+Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_mb_parse_str.php:3
+Stack trace:
+#0 %sthis_in_mb_parse_str.php(3): mb_parse_str('this=42')
+#1 %sthis_in_mb_parse_str.php(6): foo()
+#2 {main}
+ thrown in %sthis_in_mb_parse_str.php on line 3
diff --git a/Zend/tests/this_in_parse_str.phpt b/Zend/tests/this_in_parse_str.phpt
new file mode 100644
index 0000000000..4540d282cc
--- /dev/null
+++ b/Zend/tests/this_in_parse_str.phpt
@@ -0,0 +1,17 @@
+--TEST--
+$this re-assign in parse_str()
+--FILE--
+<?php
+function foo() {
+ parse_str("this=42");
+ var_dump($this);
+}
+foo();
+?>
+--EXPECTF--
+Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_in_parse_str.php:3
+Stack trace:
+#0 %sthis_in_parse_str.php(3): parse_str('this=42')
+#1 %sthis_in_parse_str.php(6): foo()
+#2 {main}
+ thrown in %sthis_in_parse_str.php on line 3
diff --git a/Zend/tests/this_in_unset.phpt b/Zend/tests/this_in_unset.phpt
new file mode 100644
index 0000000000..bc815049f9
--- /dev/null
+++ b/Zend/tests/this_in_unset.phpt
@@ -0,0 +1,8 @@
+--TEST--
+$this in unset
+--FILE--
+<?php
+unset($this);
+?>
+--EXPECTF--
+Fatal error: Cannot unset $this in %sthis_in_unset.php on line 2
diff --git a/Zend/tests/this_reassign.phpt b/Zend/tests/this_reassign.phpt
new file mode 100644
index 0000000000..d965ef4701
--- /dev/null
+++ b/Zend/tests/this_reassign.phpt
@@ -0,0 +1,17 @@
+--TEST--
+$this re-assign
+--FILE--
+<?php
+function foo() {
+ $a = "this";
+ $$a = 0;
+ var_dump($$a);
+}
+foo();
+?>
+--EXPECTF--
+Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_reassign.php:4
+Stack trace:
+#0 %sthis_reassign.php(7): foo()
+#1 {main}
+ thrown in %sthis_reassign.php on line 4
diff --git a/Zend/tests/traits/no_static_arg_binding.phpt b/Zend/tests/traits/no_static_arg_binding.phpt
new file mode 100644
index 0000000000..3134cf621b
--- /dev/null
+++ b/Zend/tests/traits/no_static_arg_binding.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Don't statically bind arguments for self:: calls in traits
+--FILE--
+<?php
+
+trait T {
+ public static function method($arg) {
+ }
+ public static function call() {
+ $i = 0;
+ self::method($i);
+ var_dump($i);
+ }
+}
+
+class C {
+ use T;
+
+ public static function method(&$arg) {
+ $arg++;
+ }
+}
+
+C::call();
+
+?>
+--EXPECT--
+int(1)
diff --git a/Zend/tests/try/bug70228.phpt b/Zend/tests/try/bug70228.phpt
index 23f5864740..8b812517a3 100644
--- a/Zend/tests/try/bug70228.phpt
+++ b/Zend/tests/try/bug70228.phpt
@@ -1,16 +1,14 @@
--TEST--
Bug #70228 (memleak if return in finally block)
---XFAIL--
-See https://bugs.php.net/bug.php?id=70228
--FILE--
<?php
function foo() {
try { return str_repeat("a", 2); }
- finally { return true; }
+ finally { return str_repeat("b", 2); }
}
var_dump(foo());
?>
--EXPECT--
-string(3) "bar"
+string(2) "bb"
diff --git a/Zend/tests/try/bug70228_2.phpt b/Zend/tests/try/bug70228_2.phpt
new file mode 100644
index 0000000000..c988e706ce
--- /dev/null
+++ b/Zend/tests/try/bug70228_2.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #70228 (memleak if return in finally block)
+--FILE--
+<?php
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ throw new Exception(2);
+ } finally {
+ return 42;
+ }
+ }
+}
+
+var_dump(test());
+?>
+--EXPECT--
+int(42)
diff --git a/Zend/tests/try/bug70228_3.phpt b/Zend/tests/try/bug70228_3.phpt
new file mode 100644
index 0000000000..55dbe4f891
--- /dev/null
+++ b/Zend/tests/try/bug70228_3.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Bug #70228 (memleak if return in finally block)
+--FILE--
+<?php
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ try {
+ } finally {
+ return 42;
+ }
+ } finally {
+ throw new Exception(2);
+ }
+ }
+}
+
+try {
+ var_dump(test());
+} catch (Exception $e) {
+ do {
+ echo $e->getMessage() . "\n";
+ $e = $e->getPrevious();
+ } while ($e);
+}
+?>
+--EXPECT--
+2
+1
diff --git a/Zend/tests/try/bug70228_4.phpt b/Zend/tests/try/bug70228_4.phpt
new file mode 100644
index 0000000000..f0ab3b0c2c
--- /dev/null
+++ b/Zend/tests/try/bug70228_4.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #70228 (memleak if return in finally block)
+--FILE--
+<?php
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ try {
+ try {
+ } finally {
+ return 42;
+ }
+ } finally {
+ throw new Exception(3);
+ }
+ } catch (Exception $e) {}
+ }
+}
+
+try {
+ var_dump(test());
+} catch (Exception $e) {
+ do {
+ echo $e->getMessage() . "\n";
+ $e = $e->getPrevious();
+ } while ($e);
+}
+?>
+--EXPECT--
+1
diff --git a/Zend/tests/try/bug70228_5.phpt b/Zend/tests/try/bug70228_5.phpt
new file mode 100644
index 0000000000..29cbf4910d
--- /dev/null
+++ b/Zend/tests/try/bug70228_5.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #70228 (memleak if return hidden by throw in finally block)
+--FILE--
+<?php
+function test() {
+ try {
+ return str_repeat("a", 2);
+ } finally {
+ throw new Exception("ops");
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+?>
+--EXPECT--
+ops
diff --git a/Zend/tests/try/bug70228_6.phpt b/Zend/tests/try/bug70228_6.phpt
new file mode 100644
index 0000000000..fc68657f4c
--- /dev/null
+++ b/Zend/tests/try/bug70228_6.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #70228 (memleak if return in finally block)
+--FILE--
+<?php
+function test($x) {
+ foreach ($x as $v) {
+ try {
+ return str_repeat("a", 2);
+ } finally {
+ return 42;
+ }
+ }
+}
+
+var_dump(test([1]));
+?>
+--EXPECT--
+int(42)
diff --git a/Zend/tests/try/bug70228_7.phpt b/Zend/tests/try/bug70228_7.phpt
new file mode 100644
index 0000000000..4b8a80351c
--- /dev/null
+++ b/Zend/tests/try/bug70228_7.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Bug #70228 (memleak if return in finally block)
+--FILE--
+<?php
+
+function foo() {
+ $array = [1, 2, $n = 3];
+ foreach ($array as $value) {
+ var_dump($value);
+ try {
+ try {
+ foreach ($array as $_) {
+ return str_repeat("a", 2);
+ }
+ } finally {
+ throw new Exception;
+ }
+ } catch (Exception $e) { }
+ }
+}
+
+foo();
+?>
+===DONE===
+--EXPECT--
+int(1)
+int(2)
+int(3)
+===DONE===
diff --git a/Zend/tests/try/bug70228_8.phpt b/Zend/tests/try/bug70228_8.phpt
new file mode 100644
index 0000000000..ad13113c71
--- /dev/null
+++ b/Zend/tests/try/bug70228_8.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #70228 (memleak if return in finally block)
+--FILE--
+<?php
+
+function foo() {
+ $array = [1, 2, $n = 3];
+ foreach ($array as $value) {
+ var_dump($value);
+ try {
+ try {
+ switch (str_repeat("b", 2)) {
+ case "bb":
+ return str_repeat("a", 2);
+ }
+ } finally {
+ throw new Exception;
+ }
+ } catch (Exception $e) { }
+ }
+}
+
+foo();
+?>
+===DONE===
+--EXPECT--
+int(1)
+int(2)
+int(3)
+===DONE===
diff --git a/Zend/tests/try/bug71604.phpt b/Zend/tests/try/bug71604.phpt
new file mode 100644
index 0000000000..79803b93ea
--- /dev/null
+++ b/Zend/tests/try/bug71604.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #71604: Aborted Generators continue after nested finally
+--FILE--
+<?php
+function gen() {
+ try {
+ try {
+ yield;
+ } finally {
+ print "INNER\n";
+ }
+ } catch (Exception $e) {
+ print "EX\n";
+ } finally {
+ print "OUTER\n";
+ }
+ print "NOTREACHED\n";
+}
+
+gen()->current();
+
+?>
+--EXPECT--
+INNER
+OUTER
diff --git a/Zend/tests/try/bug71604_2.phpt b/Zend/tests/try/bug71604_2.phpt
new file mode 100644
index 0000000000..8736cd8347
--- /dev/null
+++ b/Zend/tests/try/bug71604_2.phpt
@@ -0,0 +1,39 @@
+--TEST--
+Bug #71604: Aborted Generators continue after nested finally (2)
+--FILE--
+<?php
+
+function gen() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ throw new Exception(2);
+ } finally {
+ try {
+ yield;
+ } finally {
+ }
+ }
+ }
+}
+
+try {
+ gen()->rewind();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: 1 in %s:%d
+Stack trace:
+#0 [internal function]: gen()
+#1 %s(%d): Generator->rewind()
+#2 {main}
+
+Next Exception: 2 in %s:%d
+Stack trace:
+#0 [internal function]: gen()
+#1 %s(%d): Generator->rewind()
+#2 {main}
diff --git a/Zend/tests/try/bug71604_3.phpt b/Zend/tests/try/bug71604_3.phpt
new file mode 100644
index 0000000000..058c9a70a8
--- /dev/null
+++ b/Zend/tests/try/bug71604_3.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #71604: Aborted Generators continue after nested finally (3)
+--FILE--
+<?php
+
+function gen() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ yield;
+ } finally {
+ try {
+ throw new Exception(2);
+ } finally {
+ }
+ }
+ }
+}
+
+try {
+ gen()->rewind();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: 1 in %s:%d
+Stack trace:
+#0 [internal function]: gen()
+#1 %s(%d): Generator->rewind()
+#2 {main}
+
+Next Exception: 2 in %s:%d
+Stack trace:
+#0 %s(%d): gen()
+#1 {main}
diff --git a/Zend/tests/try/bug72213.phpt b/Zend/tests/try/bug72213.phpt
new file mode 100644
index 0000000000..624050295e
--- /dev/null
+++ b/Zend/tests/try/bug72213.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #72213 (Finally leaks on nested exceptions)
+--FILE--
+<?php
+function test() {
+ try {
+ throw new Exception('a');
+ } finally {
+ try {
+ throw new Exception('b');
+ } finally {
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ var_dump($e->getMessage());
+ var_dump($e->getPrevious()->getMessage());
+}
+?>
+--EXPECT--
+string(1) "b"
+string(1) "a"
diff --git a/Zend/tests/try/bug72213_2.phpt b/Zend/tests/try/bug72213_2.phpt
new file mode 100644
index 0000000000..790abe125d
--- /dev/null
+++ b/Zend/tests/try/bug72213_2.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #72213 (Finally leaks on nested exceptions)
+--FILE--
+<?php
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ try {
+ throw new Exception(2);
+ } finally {
+ }
+ } catch (Exception $e) {
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo "caught {$e->getMessage()}\n";
+}
+--EXPECT--
+caught 1
diff --git a/Zend/tests/try/bug74444.phpt b/Zend/tests/try/bug74444.phpt
new file mode 100644
index 0000000000..838d12ef03
--- /dev/null
+++ b/Zend/tests/try/bug74444.phpt
@@ -0,0 +1,77 @@
+--TEST--
+Bug #74444 (multiple catch freezes in some cases)
+--FILE--
+<?php
+function foo()
+{
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ echo '';
+ try {
+ throw new \RuntimeException();
+ } catch (\FooEx | \RuntimeException $e) {
+ echo 1;
+ }
+ echo 2;
+}
+
+foo();
+
+--EXPECT--
+12
diff --git a/Zend/tests/try/exceptions.inc b/Zend/tests/try/exceptions.inc
new file mode 100644
index 0000000000..68cb1c62f7
--- /dev/null
+++ b/Zend/tests/try/exceptions.inc
@@ -0,0 +1,6 @@
+<?php
+
+class Exception1 extends Exception {}
+class Exception2 extends Exception {}
+class Exception3 extends Exception {}
+class Exception4 extends Exception {}
diff --git a/Zend/tests/try/try_finally_021.phpt b/Zend/tests/try/try_finally_021.phpt
new file mode 100644
index 0000000000..ed162f40d0
--- /dev/null
+++ b/Zend/tests/try/try_finally_021.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Live range & return from finally
+--FILE--
+<?php
+$array = [1];
+foreach ([0] as $_) {
+ foreach ($array as $v) {
+ try {
+ echo "ok\n";
+ return;
+ } finally {
+ echo "ok\n";
+ return;
+ }
+ }
+}
+?>
+--EXPECT--
+ok
+ok
diff --git a/Zend/tests/try/try_finally_022.phpt b/Zend/tests/try/try_finally_022.phpt
new file mode 100644
index 0000000000..51f6a26419
--- /dev/null
+++ b/Zend/tests/try/try_finally_022.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Try finally (exception in "return" statement)
+--FILE--
+<?php
+class A {
+ public $x = 1;
+ public $y = 2;
+ function __destruct() {
+ throw new Exception();
+ }
+}
+try{
+ $a = 0;
+ switch ($a) {
+ case 0:
+ }
+ switch ($a) {
+ case 0:
+ }
+ switch ($a) {
+ case 0:
+ }
+ foreach([new stdClass()] as $x) {
+ foreach(new A() as $a) {
+ foreach([new stdClass()] as $y) {
+ try {
+ if (0) { echo "0" . (int)5; }
+ return $a;
+ } catch (Exception $e) {
+ echo "exception1\n";
+ }
+ }
+ }
+ }
+} catch (Exception $e) {
+ echo "exception2\n";
+}
+?>
+--EXPECT--
+exception2
+
diff --git a/Zend/tests/try/try_finally_023.phpt b/Zend/tests/try/try_finally_023.phpt
new file mode 100644
index 0000000000..e88eddb3b2
--- /dev/null
+++ b/Zend/tests/try/try_finally_023.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Loop var dtor throwing exception during return inside try/catch inside finally
+--FILE--
+<?php
+
+class Dtor {
+ public function __destruct() {
+ throw new Exception(2);
+ }
+}
+
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ foreach ([new Dtor] as $v) {
+ unset($v);
+ return 42;
+ }
+ } catch (Exception $e) {
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: 1 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
diff --git a/Zend/tests/try/try_finally_024.phpt b/Zend/tests/try/try_finally_024.phpt
new file mode 100644
index 0000000000..eb0b26acbf
--- /dev/null
+++ b/Zend/tests/try/try_finally_024.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Exception in finally inside finally following try/catch containing throwing try/finally
+--FILE--
+<?php
+
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ try {
+ } finally {
+ throw new Exception(2);
+ }
+ } catch (Exception $e) {}
+ try {
+ } finally {
+ throw new Exception(3);
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+?>
+--EXPECTF--
+Exception: 1 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
+
+Next Exception: 3 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
diff --git a/Zend/tests/try/try_finally_025.phpt b/Zend/tests/try/try_finally_025.phpt
new file mode 100644
index 0000000000..7ca535bcf6
--- /dev/null
+++ b/Zend/tests/try/try_finally_025.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Throw in try of try/finally inside catch
+--FILE--
+<?php
+
+function test() {
+ try {
+ throw new Exception(1);
+ } catch (Exception $e) {
+ try {
+ throw new Exception(2);
+ } finally {
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: 2 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
diff --git a/Zend/tests/try/try_finally_026.phpt b/Zend/tests/try/try_finally_026.phpt
new file mode 100644
index 0000000000..29a5de3b3a
--- /dev/null
+++ b/Zend/tests/try/try_finally_026.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Throw in finally inside catch inside finally
+--FILE--
+<?php
+
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ throw new Exception(2);
+ } catch (Exception $e) {
+ try {
+ } finally {
+ throw new Exception(3);
+ }
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: 1 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
+
+Next Exception: 3 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
diff --git a/Zend/tests/try/try_finally_027.phpt b/Zend/tests/try/try_finally_027.phpt
new file mode 100644
index 0000000000..1e66479eb0
--- /dev/null
+++ b/Zend/tests/try/try_finally_027.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Return in try with throw in finally, inside other finally
+--FILE--
+<?php
+
+function test() {
+ try {
+ throw new Exception(1);
+ } finally {
+ try {
+ return 42;
+ } finally {
+ throw new Exception(2);
+ }
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo $e, "\n";
+}
+
+?>
+--EXPECTF--
+Exception: 1 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
+
+Next Exception: 2 in %s:%d
+Stack trace:
+#0 %s(%d): test()
+#1 {main}
diff --git a/Zend/tests/try/try_multicatch_001.phpt b/Zend/tests/try/try_multicatch_001.phpt
new file mode 100644
index 0000000000..0dffd32c72
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_001.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Parsing test
+--FILE--
+<?php
+
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ echo 'TRY' . PHP_EOL;
+} catch(Exception1 | Exception2 $e) {
+ echo 'Exception';
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+
+?>
+--EXPECT--
+TRY
+FINALLY
diff --git a/Zend/tests/try/try_multicatch_002.phpt b/Zend/tests/try/try_multicatch_002.phpt
new file mode 100644
index 0000000000..0e70fec7eb
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_002.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Catch first exception in the multicatch
+--FILE--
+<?php
+
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ echo 'TRY' . PHP_EOL;
+ throw new Exception1;
+} catch(Exception1 | Exception2 | Exception3 $e) {
+ echo get_class($e) . PHP_EOL;
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+
+?>
+--EXPECT--
+TRY
+Exception1
+FINALLY
diff --git a/Zend/tests/try/try_multicatch_003.phpt b/Zend/tests/try/try_multicatch_003.phpt
new file mode 100644
index 0000000000..6aed1a2b09
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_003.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Catch second exception in the multicatch
+--FILE--
+<?php
+
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ echo 'TRY' . PHP_EOL;
+ throw new Exception2;
+} catch(Exception1 | Exception2 | Exception3 $e) {
+ echo get_class($e) . PHP_EOL;
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+
+?>
+--EXPECT--
+TRY
+Exception2
+FINALLY
diff --git a/Zend/tests/try/try_multicatch_004.phpt b/Zend/tests/try/try_multicatch_004.phpt
new file mode 100644
index 0000000000..d8b245a767
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_004.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Catch last exception in the multicatch
+--FILE--
+<?php
+
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ echo 'TRY' . PHP_EOL;
+ throw new Exception3;
+} catch(Exception1 | Exception2 | Exception3 $e) {
+ echo get_class($e) . PHP_EOL;
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+
+?>
+--EXPECT--
+TRY
+Exception3
+FINALLY
diff --git a/Zend/tests/try/try_multicatch_005.phpt b/Zend/tests/try/try_multicatch_005.phpt
new file mode 100644
index 0000000000..cc3fc890fa
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_005.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Catch exception in the nested multicatch
+--FILE--
+<?php
+
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ try {
+ echo 'TRY' . PHP_EOL;
+ throw new Exception3;
+ } catch (Exception1 | Exception3 $e) {
+ echo get_class($e) . PHP_EOL;
+ }
+} catch(Exception2 | Exception3 $e) {
+ echo 'Should never be executed';
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+
+?>
+--EXPECT--
+TRY
+Exception3
+FINALLY
diff --git a/Zend/tests/try/try_multicatch_006.phpt b/Zend/tests/try/try_multicatch_006.phpt
new file mode 100644
index 0000000000..e4505f1b24
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_006.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Catch first exception in the second multicatch
+--FILE--
+<?php
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ echo 'TRY' . PHP_EOL;
+ throw new Exception3;
+} catch(Exception1 | Exception2 $e) {
+ echo get_class($e) . PHP_EOL;
+} catch(Exception3 | Exception4 $e) {
+ echo get_class($e) . PHP_EOL;
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+?>
+--EXPECT--
+TRY
+Exception3
+FINALLY
+
diff --git a/Zend/tests/try/try_multicatch_007.phpt b/Zend/tests/try/try_multicatch_007.phpt
new file mode 100644
index 0000000000..aa073b0592
--- /dev/null
+++ b/Zend/tests/try/try_multicatch_007.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Catch second exception in the second multicatch
+--FILE--
+<?php
+require_once __DIR__ . '/exceptions.inc';
+
+try {
+ echo 'TRY' . PHP_EOL;
+ throw new Exception4;
+} catch(Exception1 | Exception2 $e) {
+ echo get_class($e) . PHP_EOL;
+} catch(Exception3 | Exception4 $e) {
+ echo get_class($e) . PHP_EOL;
+} finally {
+ echo 'FINALLY' . PHP_EOL;
+}
+?>
+--EXPECT--
+TRY
+Exception4
+FINALLY
+
diff --git a/Zend/tests/type_declarations/iterable_001.phpt b/Zend/tests/type_declarations/iterable_001.phpt
new file mode 100644
index 0000000000..f0c8bba610
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable_001.phpt
@@ -0,0 +1,48 @@
+--TEST--
+iterable type#001
+--FILE--
+<?php
+
+function test(iterable $iterable) {
+ var_dump($iterable);
+}
+
+function gen() {
+ yield 1;
+ yield 2;
+ yield 3;
+};
+
+test([1, 2, 3]);
+test(gen());
+test(new ArrayIterator([1, 2, 3]));
+
+try {
+ test(1);
+} catch (Throwable $e) {
+ echo $e->getMessage();
+}
+
+--EXPECTF--
+array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+}
+object(Generator)#1 (0) {
+}
+object(ArrayIterator)#1 (1) {
+ ["storage":"ArrayIterator":private]=>
+ array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+ }
+}
+Argument 1 passed to test() must be iterable, integer given, called in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable_002.phpt b/Zend/tests/type_declarations/iterable_002.phpt
new file mode 100644
index 0000000000..74f6d83f1e
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable_002.phpt
@@ -0,0 +1,21 @@
+--TEST--
+iterable type#002 - Default values
+--FILE--
+<?php
+
+function foo(iterable $iterable = null) {
+ // Null should be allowed as a default value
+}
+
+function bar(iterable $iterable = []) {
+ // Array should be allowed as a default value
+}
+
+function baz(iterable $iterable = 1) {
+ // No other values should be allowed as defaults
+}
+
+?>
+--EXPECTF--
+
+Fatal error: Default value for parameters with iterable type can only be an array or NULL in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable_003.phpt b/Zend/tests/type_declarations/iterable_003.phpt
new file mode 100644
index 0000000000..8c91c993d0
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable_003.phpt
@@ -0,0 +1,32 @@
+--TEST--
+iterable type#003 - Return types
+--FILE--
+<?php
+
+function foo(): iterable {
+ return [];
+}
+function bar(): iterable {
+ return (function () { yield; })();
+}
+
+function baz(): iterable {
+ return 1;
+}
+
+var_dump(foo());
+var_dump(bar());
+
+try {
+ baz();
+} catch (Throwable $e) {
+ echo $e->getMessage();
+}
+
+?>
+--EXPECT--
+array(0) {
+}
+object(Generator)#2 (0) {
+}
+Return value of baz() must be iterable, integer returned
diff --git a/Zend/tests/type_declarations/iterable_004.phpt b/Zend/tests/type_declarations/iterable_004.phpt
new file mode 100644
index 0000000000..47e79fa6b3
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable_004.phpt
@@ -0,0 +1,25 @@
+--TEST--
+iterable type#004 - Parameter covariance
+--FILE--
+<?php
+
+class Foo {
+ function testArray(array $array) {}
+
+ function testTraversable(Traversable $traversable) {}
+
+ function testScalar(int $int) {}
+}
+
+class Bar extends Foo {
+ function testArray(iterable $iterable) {}
+
+ function testTraversable(iterable $iterable) {}
+
+ function testScalar(iterable $iterable) {}
+}
+
+?>
+--EXPECTF--
+
+Warning: Declaration of Bar::testScalar(iterable $iterable) should be compatible with Foo::testScalar(int $int) in %s on line %d
diff --git a/Zend/tests/type_declarations/iterable_005.phpt b/Zend/tests/type_declarations/iterable_005.phpt
new file mode 100644
index 0000000000..9c0584b51a
--- /dev/null
+++ b/Zend/tests/type_declarations/iterable_005.phpt
@@ -0,0 +1,33 @@
+--TEST--
+iterable type#005 - Return type covariance
+--FILE--
+<?php
+
+class Test {
+ function method(): iterable {
+ return [];
+ }
+}
+
+class TestArray extends Test {
+ function method(): array {
+ return [];
+ }
+}
+
+class TestTraversable extends Test {
+ function method(): Traversable {
+ return new ArrayIterator([]);
+ }
+}
+
+class TestScalar extends Test {
+ function method(): int {
+ return 1;
+ }
+}
+
+?>
+--EXPECTF--
+
+Fatal error: Declaration of TestScalar::method(): int must be compatible with Test::method(): iterable in %s on line %d
diff --git a/Zend/tests/type_declarations/nullable_typed_return_without_value.phpt b/Zend/tests/type_declarations/nullable_typed_return_without_value.phpt
new file mode 100644
index 0000000000..b16e7c6434
--- /dev/null
+++ b/Zend/tests/type_declarations/nullable_typed_return_without_value.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Nullable typed return without value generates friendlier error message
+--FILE--
+<?php
+
+function test() : ?int {
+ return;
+}
+
+test();
+
+?>
+--EXPECTF--
+Fatal error: A function with return type must return a value (did you mean "return null;" instead of "return;"?) in %s on line %d
diff --git a/Zend/tests/type_declarations/nullable_void.phpt b/Zend/tests/type_declarations/nullable_void.phpt
new file mode 100644
index 0000000000..4ff0edb0d8
--- /dev/null
+++ b/Zend/tests/type_declarations/nullable_void.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Void cannot be nullable
+--FILE--
+<?php
+
+function test() : ?void {
+}
+
+?>
+--EXPECTF--
+Fatal error: Void type cannot be nullable in %s on line %d
diff --git a/Zend/tests/type_declarations/scalar_none.phpt b/Zend/tests/type_declarations/scalar_none.phpt
index 3bec609599..025276adef 100644
--- a/Zend/tests/type_declarations/scalar_none.phpt
+++ b/Zend/tests/type_declarations/scalar_none.phpt
@@ -28,20 +28,20 @@ foreach ($functions as $type => $function) {
echo "Testing $type:", PHP_EOL;
try {
var_dump($function());
- } catch (TypeError $e) {
+ } catch (Throwable $e) {
echo "*** Caught " . $e->getMessage() . PHP_EOL;
}
}
echo PHP_EOL . "Done";
--EXPECTF--
Testing int:
-*** Caught Argument 1 passed to {closure}() must be of the type integer, none given, called in %s on line %d
+*** Caught Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
Testing float:
-*** Caught Argument 1 passed to {closure}() must be of the type float, none given, called in %s on line %d
+*** Caught Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
Testing string:
-*** Caught Argument 1 passed to {closure}() must be of the type string, none given, called in %s on line %d
+*** Caught Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
Testing bool:
-*** Caught Argument 1 passed to {closure}() must be of the type boolean, none given, called in %s on line %d
+*** Caught Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
Testing int nullable:
NULL
Testing float nullable:
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/tests/typehints/fq_nullable.phpt b/Zend/tests/typehints/fq_nullable.phpt
new file mode 100644
index 0000000000..24ba2ffa62
--- /dev/null
+++ b/Zend/tests/typehints/fq_nullable.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Fully-qualified nullable parameter type
+--FILE--
+<?php
+
+namespace Foo;
+function test(?\stdClass $param) {}
+test(new \stdClass);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/typehints/or_null.phpt b/Zend/tests/typehints/or_null.phpt
new file mode 100644
index 0000000000..8c20052165
--- /dev/null
+++ b/Zend/tests/typehints/or_null.phpt
@@ -0,0 +1,317 @@
+--TEST--
+Test "or null"/"or be null" in type-checking errors for userland functions
+--FILE--
+<?php
+
+// This should test every branch in zend_execute.c's `zend_verify_arg_type`, `zend_verify_return_type` and `zend_verify_missing_return_type` functions which produces an "or null"/"or be null" part in its error message
+
+function unloadedClass(?I\Dont\Exist $param) {}
+
+try {
+ unloadedClass(new \StdClass);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+class RealClass {}
+interface RealInterface {}
+
+function loadedClass(?RealClass $param) {}
+function loadedInterface(?RealInterface $param) {}
+
+try {
+ loadedClass(new \StdClass);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+try {
+ loadedInterface(new \StdClass);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+try {
+ unloadedClass(1);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+try {
+ loadedClass(1);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+try {
+ loadedInterface(1);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function callableF(?callable $param) {}
+
+try {
+ callableF(1);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function iterableF(?iterable $param) {}
+
+try {
+ iterableF(1);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function intF(?int $param) {}
+
+try {
+ intF(new StdClass);
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnUnloadedClass(): ?I\Dont\Exist {
+ return new \StdClass;
+}
+
+try {
+ returnUnloadedClass();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnLoadedClass(): ?RealClass {
+ return new \StdClass;
+}
+
+try {
+ returnLoadedClass();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnLoadedInterface(): ?RealInterface {
+ return new \StdClass;
+}
+
+try {
+ returnLoadedInterface();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnUnloadedClassScalar(): ?I\Dont\Exist {
+ return 1;
+}
+
+try {
+ returnUnloadedClassScalar();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnLoadedClassScalar(): ?RealClass {
+ return 1;
+}
+
+try {
+ returnLoadedClassScalar();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnLoadedInterfaceScalar(): ?RealInterface {
+ return 1;
+}
+
+try {
+ returnLoadedInterfaceScalar();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnCallable(): ?callable {
+ return 1;
+}
+
+try {
+ returnCallable();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnIterable(): ?iterable {
+ return 1;
+}
+
+try {
+ returnIterable();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnInt(): ?int {
+ return new \StdClass;
+}
+
+try {
+ returnInt();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnMissingUnloadedClass(): ?I\Dont\Exist {
+}
+
+try {
+ returnMissingUnloadedClass();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnMissingLoadedClass(): ?RealClass {
+}
+
+try {
+ returnMissingLoadedClass();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnMissingLoadedInterface(): ?RealInterface {
+}
+
+try {
+ returnMissingLoadedInterface();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnMissingCallable(): ?callable {
+}
+
+try {
+ returnMissingCallable();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnMissingIterable(): ?iterable {
+}
+
+try {
+ returnMissingIterable();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+function returnMissingInt(): ?int {
+}
+
+try {
+ returnMissingInt();
+} catch (\TypeError $e) {
+ echo $e, PHP_EOL;
+}
+
+?>
+--EXPECTF--
+TypeError: Argument 1 passed to unloadedClass() must be an instance of I\Dont\Exist or null, instance of stdClass given, called in %s on line 8 and defined in %s:5
+Stack trace:
+#0 %s(8): unloadedClass(Object(stdClass))
+#1 {main}
+TypeError: Argument 1 passed to loadedClass() must be an instance of RealClass or null, instance of stdClass given, called in %s on line 20 and defined in %s:16
+Stack trace:
+#0 %s(20): loadedClass(Object(stdClass))
+#1 {main}
+TypeError: Argument 1 passed to loadedInterface() must implement interface RealInterface or be null, instance of stdClass given, called in %s on line 26 and defined in %s:17
+Stack trace:
+#0 %s(26): loadedInterface(Object(stdClass))
+#1 {main}
+TypeError: Argument 1 passed to unloadedClass() must be an instance of I\Dont\Exist or null, integer given, called in %s on line 32 and defined in %s:5
+Stack trace:
+#0 %s(32): unloadedClass(1)
+#1 {main}
+TypeError: Argument 1 passed to loadedClass() must be an instance of RealClass or null, integer given, called in %s on line 38 and defined in %s:16
+Stack trace:
+#0 %s(38): loadedClass(1)
+#1 {main}
+TypeError: Argument 1 passed to loadedInterface() must implement interface RealInterface or be null, integer given, called in %s on line 44 and defined in %s:17
+Stack trace:
+#0 %s(44): loadedInterface(1)
+#1 {main}
+TypeError: Argument 1 passed to callableF() must be callable or null, integer given, called in %s on line 52 and defined in %s:49
+Stack trace:
+#0 %s(52): callableF(1)
+#1 {main}
+TypeError: Argument 1 passed to iterableF() must be iterable or null, integer given, called in %s on line 60 and defined in %s:57
+Stack trace:
+#0 %s(60): iterableF(1)
+#1 {main}
+TypeError: Argument 1 passed to intF() must be of the type integer or null, object given, called in %s on line 68 and defined in %s:65
+Stack trace:
+#0 %s(68): intF(Object(stdClass))
+#1 {main}
+TypeError: Return value of returnUnloadedClass() must be an instance of I\Dont\Exist or null, instance of stdClass returned in %s:74
+Stack trace:
+#0 %s(78): returnUnloadedClass()
+#1 {main}
+TypeError: Return value of returnLoadedClass() must be an instance of RealClass or null, instance of stdClass returned in %s:84
+Stack trace:
+#0 %s(88): returnLoadedClass()
+#1 {main}
+TypeError: Return value of returnLoadedInterface() must implement interface RealInterface or be null, instance of stdClass returned in %s:94
+Stack trace:
+#0 %s(98): returnLoadedInterface()
+#1 {main}
+TypeError: Return value of returnUnloadedClassScalar() must be an instance of I\Dont\Exist or null, integer returned in %s:104
+Stack trace:
+#0 %s(108): returnUnloadedClassScalar()
+#1 {main}
+TypeError: Return value of returnLoadedClassScalar() must be an instance of RealClass or null, integer returned in %s:114
+Stack trace:
+#0 %s(118): returnLoadedClassScalar()
+#1 {main}
+TypeError: Return value of returnLoadedInterfaceScalar() must implement interface RealInterface or be null, integer returned in %s:124
+Stack trace:
+#0 %s(128): returnLoadedInterfaceScalar()
+#1 {main}
+TypeError: Return value of returnCallable() must be callable or null, integer returned in %s:134
+Stack trace:
+#0 %s(138): returnCallable()
+#1 {main}
+TypeError: Return value of returnIterable() must be iterable or null, integer returned in %s:144
+Stack trace:
+#0 %s(148): returnIterable()
+#1 {main}
+TypeError: Return value of returnInt() must be of the type integer or null, object returned in %s:154
+Stack trace:
+#0 %s(158): returnInt()
+#1 {main}
+TypeError: Return value of returnMissingUnloadedClass() must be an instance of I\Dont\Exist or null, none returned in %s:164
+Stack trace:
+#0 %s(167): returnMissingUnloadedClass()
+#1 {main}
+TypeError: Return value of returnMissingLoadedClass() must be an instance of RealClass or null, none returned in %s:173
+Stack trace:
+#0 %s(176): returnMissingLoadedClass()
+#1 {main}
+TypeError: Return value of returnMissingLoadedInterface() must implement interface RealInterface or be null, none returned in %s:182
+Stack trace:
+#0 %s(185): returnMissingLoadedInterface()
+#1 {main}
+TypeError: Return value of returnMissingCallable() must be callable or null, none returned in %s:191
+Stack trace:
+#0 %s(194): returnMissingCallable()
+#1 {main}
+TypeError: Return value of returnMissingIterable() must be iterable or null, none returned in %s:200
+Stack trace:
+#0 %s(203): returnMissingIterable()
+#1 {main}
+TypeError: Return value of returnMissingInt() must be of the type integer or null, none returned in %s:209
+Stack trace:
+#0 %s(212): returnMissingInt()
+#1 {main}
diff --git a/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt b/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt
index da96264609..4c6f36f10b 100644
--- a/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt
+++ b/Zend/tests/variadic/adding_additional_optional_parameter_error.phpt
@@ -13,4 +13,4 @@ class MySQL implements DB {
?>
--EXPECTF--
-Fatal error: Declaration of MySQL::query($query, int $extraParam = NULL, string ...$params) must be compatible with DB::query($query, string ...$params) in %s on line %d
+Fatal error: Declaration of MySQL::query($query, ?int $extraParam = NULL, string ...$params) must be compatible with DB::query($query, string ...$params) in %s on line %d