mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Implement GH-18261: Allow cast to be used in constant expressions (#18264)
This commit is contained in:
1
NEWS
1
NEWS
@@ -44,6 +44,7 @@ PHP NEWS
|
||||
(timwolla, Volker Dusch)
|
||||
. Added get_error_handler(), get_exception_handler() functions. (Arnaud)
|
||||
. Fixed bug GH-15753 and GH-16198 (Bind traits before parent class). (ilutov)
|
||||
. Added support for casts in constant expressions. (nielsdos)
|
||||
|
||||
- Curl:
|
||||
. Added curl_multi_get_handles(). (timwolla)
|
||||
|
||||
@@ -130,6 +130,7 @@ PHP 8.5 UPGRADE NOTES
|
||||
RFC: https://wiki.php.net/rfc/marking_return_value_as_important
|
||||
. Added asymmetric visibility support for static properties.
|
||||
RFC: https://wiki.php.net/rfc/static-aviz
|
||||
. Added support for casts in constant expressions.
|
||||
|
||||
- Curl:
|
||||
. Added support for share handles that are persisted across multiple PHP
|
||||
|
||||
64
Zend/tests/constexpr/constant_expressions_cast.phpt
Normal file
64
Zend/tests/constexpr/constant_expressions_cast.phpt
Normal file
@@ -0,0 +1,64 @@
|
||||
--TEST--
|
||||
Constant expressions with cast
|
||||
--FILE--
|
||||
<?php
|
||||
class X {
|
||||
public int $foo = 3;
|
||||
}
|
||||
|
||||
const T1 = (int) 0.3;
|
||||
const T2 = (bool) 0.3;
|
||||
const T3 = (string) [];
|
||||
const T4 = (object) ["a" => 1];
|
||||
const T5 = (float) 5;
|
||||
const T6 = (array) "";
|
||||
const T7 = (array) var_dump(...);
|
||||
const T8 = (array) new X;
|
||||
const T9 = (array) new DateTime;
|
||||
const T10 = (int) new DateTime;
|
||||
|
||||
var_dump(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Array to string conversion in %s on line %d
|
||||
|
||||
Warning: Object of class DateTime could not be converted to int in %s on line %d
|
||||
int(0)
|
||||
bool(true)
|
||||
string(5) "Array"
|
||||
object(stdClass)#%d (1) {
|
||||
["a"]=>
|
||||
int(1)
|
||||
}
|
||||
float(5)
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(0) ""
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
object(Closure)#%d (2) {
|
||||
["function"]=>
|
||||
string(8) "var_dump"
|
||||
["parameter"]=>
|
||||
array(2) {
|
||||
["$value"]=>
|
||||
string(10) "<required>"
|
||||
["$values"]=>
|
||||
string(10) "<optional>"
|
||||
}
|
||||
}
|
||||
}
|
||||
array(1) {
|
||||
["foo"]=>
|
||||
int(3)
|
||||
}
|
||||
array(3) {
|
||||
["date"]=>
|
||||
string(%d) "%s"
|
||||
["timezone_type"]=>
|
||||
int(%d)
|
||||
["timezone"]=>
|
||||
string(%d) "%s"
|
||||
}
|
||||
int(1)
|
||||
@@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Constant expressions with object cast in property
|
||||
--FILE--
|
||||
<?php
|
||||
class X {
|
||||
public $foo = (object) [];
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Object casts are not supported in this context in %s on line %d
|
||||
@@ -702,6 +702,41 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
|
||||
}
|
||||
zval_ptr_dtor_nogc(&op1);
|
||||
break;
|
||||
case ZEND_AST_CAST:
|
||||
if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
|
||||
ret = FAILURE;
|
||||
break;
|
||||
}
|
||||
if (ast->attr == Z_TYPE(op1)) {
|
||||
ZVAL_COPY_VALUE(result, &op1);
|
||||
} else {
|
||||
switch (ast->attr) {
|
||||
case _IS_BOOL:
|
||||
ZVAL_BOOL(result, zend_is_true(&op1));
|
||||
break;
|
||||
case IS_LONG:
|
||||
ZVAL_LONG(result, zval_get_long_func(&op1, false));
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
ZVAL_DOUBLE(result, zval_get_double_func(&op1));
|
||||
break;
|
||||
case IS_STRING:
|
||||
ZVAL_STR(result, zval_get_string_func(&op1));
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
zend_cast_zval_to_array(result, &op1, IS_VAR);
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
zend_cast_zval_to_object(result, &op1, IS_VAR);
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE();
|
||||
}
|
||||
zval_ptr_dtor_nogc(&op1);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
ret = FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ZEND_AST_OR:
|
||||
if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
|
||||
ret = FAILURE;
|
||||
|
||||
@@ -11121,6 +11121,7 @@ static bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
|
||||
|| kind == ZEND_AST_AND || kind == ZEND_AST_OR
|
||||
|| kind == ZEND_AST_UNARY_OP
|
||||
|| kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
|
||||
|| kind == ZEND_AST_CAST
|
||||
|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
|
||||
|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
|
||||
|| kind == ZEND_AST_UNPACK
|
||||
@@ -11395,6 +11396,12 @@ static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */
|
||||
case ZEND_AST_MAGIC_CONST:
|
||||
zend_compile_const_expr_magic_const(ast_ptr);
|
||||
break;
|
||||
case ZEND_AST_CAST:
|
||||
if (ast->attr == IS_OBJECT && !ctx->allow_dynamic) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Object casts are not supported in this context");
|
||||
}
|
||||
break;
|
||||
case ZEND_AST_NEW:
|
||||
if (!ctx->allow_dynamic) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
|
||||
@@ -219,6 +219,60 @@ static zend_always_inline void zend_safe_assign_to_variable_noref(zval *variable
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_cast_zval_to_object(zval *result, zval *expr, uint8_t op1_type) {
|
||||
HashTable *ht;
|
||||
|
||||
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
|
||||
if (Z_TYPE_P(expr) == IS_ARRAY) {
|
||||
ht = zend_symtable_to_proptable(Z_ARR_P(expr));
|
||||
if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
|
||||
/* TODO: try not to duplicate immutable arrays as well ??? */
|
||||
ht = zend_array_dup(ht);
|
||||
}
|
||||
Z_OBJ_P(result)->properties = ht;
|
||||
} else if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
|
||||
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
|
||||
if (op1_type == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_cast_zval_to_array(zval *result, zval *expr, uint8_t op1_type) {
|
||||
extern zend_class_entry *zend_ce_closure;
|
||||
if (op1_type == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
|
||||
if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
ZVAL_ARR(result, zend_new_array(1));
|
||||
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
||||
if (op1_type == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
|
||||
/* Optimized version without rebuilding properties HashTable */
|
||||
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
|
||||
} else {
|
||||
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
|
||||
if (obj_ht) {
|
||||
/* fast copy */
|
||||
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
|
||||
(Z_OBJCE_P(expr)->default_properties_count ||
|
||||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
|
||||
GC_IS_RECURSIVE(obj_ht))));
|
||||
zend_release_properties(obj_ht);
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API zend_result ZEND_FASTCALL zval_update_constant(zval *pp);
|
||||
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope);
|
||||
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_with_ctx(zval *pp, zend_class_entry *scope, zend_ast_evaluate_ctx *ctx);
|
||||
|
||||
@@ -6459,7 +6459,6 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
|
||||
USE_OPLINE
|
||||
zval *expr;
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
HashTable *ht;
|
||||
|
||||
SAVE_OPLINE();
|
||||
expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
@@ -6493,53 +6492,10 @@ ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
|
||||
}
|
||||
|
||||
if (opline->extended_value == IS_ARRAY) {
|
||||
if (OP1_TYPE == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
|
||||
if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
ZVAL_ARR(result, zend_new_array(1));
|
||||
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
|
||||
/* Optimized version without rebuilding properties HashTable */
|
||||
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
|
||||
} else {
|
||||
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
|
||||
if (obj_ht) {
|
||||
/* fast copy */
|
||||
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
|
||||
(Z_OBJCE_P(expr)->default_properties_count ||
|
||||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
|
||||
GC_IS_RECURSIVE(obj_ht))));
|
||||
zend_release_properties(obj_ht);
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_array(result, expr, OP1_TYPE);
|
||||
} else {
|
||||
ZEND_ASSERT(opline->extended_value == IS_OBJECT);
|
||||
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
|
||||
if (Z_TYPE_P(expr) == IS_ARRAY) {
|
||||
ht = zend_symtable_to_proptable(Z_ARR_P(expr));
|
||||
if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
|
||||
/* TODO: try not to duplicate immutable arrays as well ??? */
|
||||
ht = zend_array_dup(ht);
|
||||
}
|
||||
Z_OBJ_P(result)->properties = ht;
|
||||
} else if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
|
||||
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_object(result, expr, OP1_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
192
Zend/zend_vm_execute.h
generated
192
Zend/zend_vm_execute.h
generated
@@ -5233,7 +5233,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H
|
||||
USE_OPLINE
|
||||
zval *expr;
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
HashTable *ht;
|
||||
|
||||
SAVE_OPLINE();
|
||||
expr = RT_CONSTANT(opline, opline->op1);
|
||||
@@ -5266,53 +5265,10 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_H
|
||||
}
|
||||
|
||||
if (opline->extended_value == IS_ARRAY) {
|
||||
if (IS_CONST == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
|
||||
if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
ZVAL_ARR(result, zend_new_array(1));
|
||||
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
||||
if (IS_CONST == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
|
||||
/* Optimized version without rebuilding properties HashTable */
|
||||
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
|
||||
} else {
|
||||
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
|
||||
if (obj_ht) {
|
||||
/* fast copy */
|
||||
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
|
||||
(Z_OBJCE_P(expr)->default_properties_count ||
|
||||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
|
||||
GC_IS_RECURSIVE(obj_ht))));
|
||||
zend_release_properties(obj_ht);
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_array(result, expr, IS_CONST);
|
||||
} else {
|
||||
ZEND_ASSERT(opline->extended_value == IS_OBJECT);
|
||||
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
|
||||
if (Z_TYPE_P(expr) == IS_ARRAY) {
|
||||
ht = zend_symtable_to_proptable(Z_ARR_P(expr));
|
||||
if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
|
||||
/* TODO: try not to duplicate immutable arrays as well ??? */
|
||||
ht = zend_array_dup(ht);
|
||||
}
|
||||
Z_OBJ_P(result)->properties = ht;
|
||||
} else if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
|
||||
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
|
||||
if (IS_CONST == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_object(result, expr, IS_CONST);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20154,7 +20110,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC
|
||||
USE_OPLINE
|
||||
zval *expr;
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
HashTable *ht;
|
||||
|
||||
SAVE_OPLINE();
|
||||
expr = _get_zval_ptr_tmp(opline->op1.var EXECUTE_DATA_CC);
|
||||
@@ -20187,53 +20142,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC
|
||||
}
|
||||
|
||||
if (opline->extended_value == IS_ARRAY) {
|
||||
if (IS_TMP_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
|
||||
if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
ZVAL_ARR(result, zend_new_array(1));
|
||||
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
||||
if (IS_TMP_VAR == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
|
||||
/* Optimized version without rebuilding properties HashTable */
|
||||
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
|
||||
} else {
|
||||
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
|
||||
if (obj_ht) {
|
||||
/* fast copy */
|
||||
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
|
||||
(Z_OBJCE_P(expr)->default_properties_count ||
|
||||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
|
||||
GC_IS_RECURSIVE(obj_ht))));
|
||||
zend_release_properties(obj_ht);
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_array(result, expr, IS_TMP_VAR);
|
||||
} else {
|
||||
ZEND_ASSERT(opline->extended_value == IS_OBJECT);
|
||||
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
|
||||
if (Z_TYPE_P(expr) == IS_ARRAY) {
|
||||
ht = zend_symtable_to_proptable(Z_ARR_P(expr));
|
||||
if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
|
||||
/* TODO: try not to duplicate immutable arrays as well ??? */
|
||||
ht = zend_array_dup(ht);
|
||||
}
|
||||
Z_OBJ_P(result)->properties = ht;
|
||||
} else if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
|
||||
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
|
||||
if (IS_TMP_VAR == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_object(result, expr, IS_TMP_VAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22820,7 +22732,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC
|
||||
USE_OPLINE
|
||||
zval *expr;
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
HashTable *ht;
|
||||
|
||||
SAVE_OPLINE();
|
||||
expr = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC);
|
||||
@@ -22854,53 +22765,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC
|
||||
}
|
||||
|
||||
if (opline->extended_value == IS_ARRAY) {
|
||||
if (IS_VAR == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
|
||||
if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
ZVAL_ARR(result, zend_new_array(1));
|
||||
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
||||
if (IS_VAR == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
|
||||
/* Optimized version without rebuilding properties HashTable */
|
||||
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
|
||||
} else {
|
||||
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
|
||||
if (obj_ht) {
|
||||
/* fast copy */
|
||||
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
|
||||
(Z_OBJCE_P(expr)->default_properties_count ||
|
||||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
|
||||
GC_IS_RECURSIVE(obj_ht))));
|
||||
zend_release_properties(obj_ht);
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_array(result, expr, IS_VAR);
|
||||
} else {
|
||||
ZEND_ASSERT(opline->extended_value == IS_OBJECT);
|
||||
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
|
||||
if (Z_TYPE_P(expr) == IS_ARRAY) {
|
||||
ht = zend_symtable_to_proptable(Z_ARR_P(expr));
|
||||
if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
|
||||
/* TODO: try not to duplicate immutable arrays as well ??? */
|
||||
ht = zend_array_dup(ht);
|
||||
}
|
||||
Z_OBJ_P(result)->properties = ht;
|
||||
} else if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
|
||||
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
|
||||
if (IS_VAR == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_object(result, expr, IS_VAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41061,7 +40929,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO
|
||||
USE_OPLINE
|
||||
zval *expr;
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
HashTable *ht;
|
||||
|
||||
SAVE_OPLINE();
|
||||
expr = _get_zval_ptr_cv_BP_VAR_R(opline->op1.var EXECUTE_DATA_CC);
|
||||
@@ -41094,53 +40961,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO
|
||||
}
|
||||
|
||||
if (opline->extended_value == IS_ARRAY) {
|
||||
if (IS_CV == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
|
||||
if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
ZVAL_ARR(result, zend_new_array(1));
|
||||
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
||||
if (IS_CV == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
} else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
|
||||
/* Optimized version without rebuilding properties HashTable */
|
||||
ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
|
||||
} else {
|
||||
HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
|
||||
if (obj_ht) {
|
||||
/* fast copy */
|
||||
ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
|
||||
(Z_OBJCE_P(expr)->default_properties_count ||
|
||||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
|
||||
GC_IS_RECURSIVE(obj_ht))));
|
||||
zend_release_properties(obj_ht);
|
||||
} else {
|
||||
ZVAL_EMPTY_ARRAY(result);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_array(result, expr, IS_CV);
|
||||
} else {
|
||||
ZEND_ASSERT(opline->extended_value == IS_OBJECT);
|
||||
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
|
||||
if (Z_TYPE_P(expr) == IS_ARRAY) {
|
||||
ht = zend_symtable_to_proptable(Z_ARR_P(expr));
|
||||
if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
|
||||
/* TODO: try not to duplicate immutable arrays as well ??? */
|
||||
ht = zend_array_dup(ht);
|
||||
}
|
||||
Z_OBJ_P(result)->properties = ht;
|
||||
} else if (Z_TYPE_P(expr) != IS_NULL) {
|
||||
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
|
||||
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
|
||||
if (IS_CV == IS_CONST) {
|
||||
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
|
||||
} else {
|
||||
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
||||
}
|
||||
}
|
||||
zend_cast_zval_to_object(result, expr, IS_CV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user