diff options
-rw-r--r-- | Zend/tests/constant_expressions_coalesce.phpt | 10 | ||||
-rw-r--r-- | Zend/tests/constant_expressions_coalesce_empty_dim.phpt | 11 | ||||
-rw-r--r-- | Zend/tests/constant_expressions_dynamic.phpt | 5 | ||||
-rw-r--r-- | Zend/zend_compile.c | 32 | ||||
-rw-r--r-- | Zend/zend_execute.c | 2 |
5 files changed, 49 insertions, 11 deletions
diff --git a/Zend/tests/constant_expressions_coalesce.phpt b/Zend/tests/constant_expressions_coalesce.phpt index aa40bd68e2..425aba69c4 100644 --- a/Zend/tests/constant_expressions_coalesce.phpt +++ b/Zend/tests/constant_expressions_coalesce.phpt @@ -9,11 +9,15 @@ const T_1 = null ?? A[1]['undefined']['index'] ?? 1; const T_2 = null ?? A['undefined']['index'] ?? 2; const T_3 = null ?? A[1][0][2] ?? 3; const T_4 = A[1][0][2] ?? 4; +const T_5 = null ?? __LINE__; +const T_6 = __LINE__ ?? "bar"; var_dump(T_1); var_dump(T_2); var_dump(T_3); var_dump(T_4); +var_dump(T_5); +var_dump(T_6); var_dump((function(){ static $var = null ?? A[1]['undefined']['index'] ?? 1; return $var; })()); var_dump((function(){ static $var = null ?? A['undefined']['index'] ?? 2; return $var; })()); @@ -25,14 +29,14 @@ var_dump((new class { public $var = null ?? A['undefined']['index'] ?? 2; })->va var_dump((new class { public $var = null ?? A[1][0][2] ?? 3; })->var); var_dump((new class { public $var = A[1][0][2] ?? 4; })->var); -const D = [][] ?? 1; - ?> --EXPECTF-- int(1) int(2) int(3) int(4) +int(%d) +int(%d) int(1) int(2) int(3) @@ -41,5 +45,3 @@ int(1) int(2) int(3) int(4) - -Fatal error: Cannot use [] for reading in %s.php on line 25 diff --git a/Zend/tests/constant_expressions_coalesce_empty_dim.phpt b/Zend/tests/constant_expressions_coalesce_empty_dim.phpt new file mode 100644 index 0000000000..56ee43b789 --- /dev/null +++ b/Zend/tests/constant_expressions_coalesce_empty_dim.phpt @@ -0,0 +1,11 @@ +--TEST-- +Constant expressions with empty dimension fetch on coalesce +--FILE-- +<?php + +const A = [][] ?? 1; + +?> +--EXPECTF-- +Fatal error: Cannot use [] for reading in %s.php on line %d + diff --git a/Zend/tests/constant_expressions_dynamic.phpt b/Zend/tests/constant_expressions_dynamic.phpt index d4e06ee258..d038591036 100644 --- a/Zend/tests/constant_expressions_dynamic.phpt +++ b/Zend/tests/constant_expressions_dynamic.phpt @@ -35,10 +35,12 @@ const T_19 = [ false => false, true => true, ]; +eval("const T_20x = 'a';"); +const T_20 = null ?: (T_20x . 'bc'); var_dump( T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9, T_10, - T_11, T_12, T_13, T_14, T_15, T_16, T_17, T_18, T_19 + T_11, T_12, T_13, T_14, T_15, T_16, T_17, T_18, T_19, T_20 ); ?> @@ -75,3 +77,4 @@ array(6) { [1]=> bool(true) } +string(3) "abc" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 18836d6418..20575360c3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6967,14 +6967,16 @@ void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */ zend_compile_const_expr(&ast); if (ast->kind == ZEND_AST_ZVAL) { ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast)); - - /* Kill this branch of the original AST, as it was already destroyed. - * It would be nice to find a better solution to this problem in the - * future. */ - orig_ast->kind = 0; } else { ZVAL_NEW_AST(result, zend_ast_copy(ast)); + /* destroy the ast here, it might have been replaced */ + zend_ast_destroy(ast); } + + /* Kill this branch of the original AST, as it was already destroyed. + * It would be nice to find a better solution to this problem in the + * future. */ + orig_ast->kind = 0; } /* }}} */ @@ -7385,6 +7387,26 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ zend_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0])); break; + case ZEND_AST_COALESCE: + zend_eval_const_expr(&ast->child[0]); + + if (ast->child[0]->kind != ZEND_AST_ZVAL) { + /* ensure everything was compile-time evaluated at least once */ + zend_eval_const_expr(&ast->child[1]); + return; + } + + if (Z_TYPE_P(zend_ast_get_zval(ast->child[0])) == IS_NULL) { + zend_eval_const_expr(&ast->child[1]); + *ast_ptr = ast->child[1]; + ast->child[1] = NULL; + zend_ast_destroy(ast); + } else { + *ast_ptr = ast->child[0]; + ast->child[0] = NULL; + zend_ast_destroy(ast); + } + return; case ZEND_AST_CONDITIONAL: { zend_ast **child, *child_ast; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 324cf82e2b..cda98fd8a4 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1914,7 +1914,7 @@ ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval * ZEND_API void zend_fetch_dimension_by_zval_is(zval *result, zval *container, zval *dim, int dim_type) { - zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1); + zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS); } |