mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Evaluate const expression cast at ct if possible
Related to GH-18264 Closes GH-18347
This commit is contained in:
parent
27b83e3095
commit
c97bdce962
4 changed files with 101 additions and 25 deletions
|
@ -82,31 +82,8 @@ zend_result zend_optimizer_eval_unary_op(zval *result, uint8_t opcode, zval *op1
|
|||
|
||||
zend_result zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1) /* {{{ */
|
||||
{
|
||||
switch (type) {
|
||||
case IS_NULL:
|
||||
ZVAL_NULL(result);
|
||||
return SUCCESS;
|
||||
case _IS_BOOL:
|
||||
ZVAL_BOOL(result, zval_is_true(op1));
|
||||
return SUCCESS;
|
||||
case IS_LONG:
|
||||
ZVAL_LONG(result, zval_get_long(op1));
|
||||
return SUCCESS;
|
||||
case IS_DOUBLE:
|
||||
ZVAL_DOUBLE(result, zval_get_double(op1));
|
||||
return SUCCESS;
|
||||
case IS_STRING:
|
||||
/* Conversion from double to string takes into account run-time
|
||||
'precision' setting and cannot be evaluated at compile-time */
|
||||
if (Z_TYPE_P(op1) != IS_ARRAY && Z_TYPE_P(op1) != IS_DOUBLE) {
|
||||
ZVAL_STR(result, zval_get_string(op1));
|
||||
return SUCCESS;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
ZVAL_COPY(result, op1);
|
||||
convert_to_array(result);
|
||||
return SUCCESS;
|
||||
if (zend_try_ct_eval_cast(result, type, op1)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,28 @@ const T9 = (array) new DateTime;
|
|||
const T10 = (int) new DateTime;
|
||||
|
||||
var_dump(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
|
||||
|
||||
const C_FLOAT = 0.3;
|
||||
const C_EMPTY_ARRAY = [];
|
||||
const C_ARRAY = ["a" => 1];
|
||||
const C_INT = 5;
|
||||
const C_EMPTY_STRING = "";
|
||||
const C_CALLABLE = var_dump(...);
|
||||
const C_USER_OBJECT = new X;
|
||||
const C_DATE_TIME = new DateTime;
|
||||
|
||||
const T11 = (int) C_FLOAT;
|
||||
const T12 = (bool) C_FLOAT;
|
||||
const T13 = (string) C_EMPTY_ARRAY;
|
||||
const T14 = (object) C_ARRAY;
|
||||
const T15 = (float) C_INT;
|
||||
const T16 = (array) C_EMPTY_STRING;
|
||||
const T17 = (array) C_CALLABLE;
|
||||
const T18 = (array) C_USER_OBJECT;
|
||||
const T19 = (array) C_DATE_TIME;
|
||||
const T20 = (int) C_DATE_TIME;
|
||||
|
||||
var_dump(T11, T12, T13, T14, T15, T16, T17, T18, T19, T20);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Array to string conversion in %s on line %d
|
||||
|
@ -62,3 +84,46 @@ array(3) {
|
|||
string(%d) "%s"
|
||||
}
|
||||
int(1)
|
||||
|
||||
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)
|
||||
|
|
|
@ -11842,6 +11842,34 @@ static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1)
|
||||
{
|
||||
switch (type) {
|
||||
case _IS_BOOL:
|
||||
ZVAL_BOOL(result, zval_is_true(op1));
|
||||
return true;
|
||||
case IS_LONG:
|
||||
ZVAL_LONG(result, zval_get_long(op1));
|
||||
return true;
|
||||
case IS_DOUBLE:
|
||||
ZVAL_DOUBLE(result, zval_get_double(op1));
|
||||
return true;
|
||||
case IS_STRING:
|
||||
/* Conversion from double to string takes into account run-time
|
||||
'precision' setting and cannot be evaluated at compile-time */
|
||||
if (Z_TYPE_P(op1) != IS_ARRAY && Z_TYPE_P(op1) != IS_DOUBLE) {
|
||||
ZVAL_STR(result, zval_get_string(op1));
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
ZVAL_COPY(result, op1);
|
||||
convert_to_array(result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
||||
{
|
||||
zend_ast *ast = *ast_ptr;
|
||||
|
@ -12129,6 +12157,10 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
return;
|
||||
case ZEND_AST_CAST:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
if (ast->child[0]->kind == ZEND_AST_ZVAL
|
||||
&& zend_try_ct_eval_cast(&result, ast->attr, zend_ast_get_zval(ast->child[0]))) {
|
||||
break;
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
|
|
|
@ -1301,4 +1301,6 @@ ZEND_API bool zend_is_op_long_compatible(const zval *op);
|
|||
ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, const zval *op1, const zval *op2);
|
||||
ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op);
|
||||
|
||||
bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1);
|
||||
|
||||
#endif /* ZEND_COMPILE_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue