mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Evaluate const expression cast at ct if possible
Related to GH-18264 Closes GH-18347
This commit is contained in:
@@ -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) /* {{{ */
|
zend_result zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1) /* {{{ */
|
||||||
{
|
{
|
||||||
switch (type) {
|
if (zend_try_ct_eval_cast(result, type, op1)) {
|
||||||
case IS_NULL:
|
return SUCCESS;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,28 @@ const T9 = (array) new DateTime;
|
|||||||
const T10 = (int) new DateTime;
|
const T10 = (int) new DateTime;
|
||||||
|
|
||||||
var_dump(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
|
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--
|
--EXPECTF--
|
||||||
Warning: Array to string conversion in %s on line %d
|
Warning: Array to string conversion in %s on line %d
|
||||||
@@ -62,3 +84,46 @@ array(3) {
|
|||||||
string(%d) "%s"
|
string(%d) "%s"
|
||||||
}
|
}
|
||||||
int(1)
|
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) /* {{{ */
|
static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_ast *ast = *ast_ptr;
|
zend_ast *ast = *ast_ptr;
|
||||||
@@ -12129,6 +12157,10 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||||||
return;
|
return;
|
||||||
case ZEND_AST_CAST:
|
case ZEND_AST_CAST:
|
||||||
zend_eval_const_expr(&ast->child[0]);
|
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;
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
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_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);
|
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 */
|
#endif /* ZEND_COMPILE_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user