mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Use zend_ast_apply in zend_eval_const_expr (#11261)
Supporting new constant expressions requires remembering to add them to zend_eval_const_expr, even if it only evalutes its children. This is routinely forgotten, at least by me. Use zend_ast_apply to solve this generically.
This commit is contained in:
parent
a59c933ac0
commit
1c733c8bbc
1 changed files with 24 additions and 46 deletions
|
@ -10557,7 +10557,7 @@ static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
||||
static void zend_eval_const_expr_inner(zend_ast **ast_ptr, void *ctx) /* {{{ */
|
||||
{
|
||||
zend_ast *ast = *ast_ptr;
|
||||
zval result;
|
||||
|
@ -10566,10 +10566,25 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
return;
|
||||
}
|
||||
|
||||
/* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
|
||||
if (ast->kind == ZEND_AST_DIM
|
||||
&& (ast->attr & ZEND_DIM_IS)
|
||||
&& ast->child[0]->kind == ZEND_AST_DIM) {
|
||||
ast->child[0]->attr |= ZEND_DIM_IS;
|
||||
}
|
||||
|
||||
/* We don't want to evaluate the class name of ZEND_AST_CLASS_NAME nodes. We need to be able to
|
||||
* differenciate between literal class names and expressions that evaluate to strings. Strings
|
||||
* are not actually allowed in ::class expressions.
|
||||
*
|
||||
* ZEND_AST_COALESCE and ZEND_AST_CONDITIONAL will manually evaluate only the children for the
|
||||
* taken paths. */
|
||||
if (ast->kind != ZEND_AST_CLASS_NAME && ast->kind != ZEND_AST_COALESCE && ast->kind != ZEND_AST_CONDITIONAL) {
|
||||
zend_ast_apply(ast, zend_eval_const_expr_inner, ctx);
|
||||
}
|
||||
|
||||
switch (ast->kind) {
|
||||
case ZEND_AST_BINARY_OP:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
|
||||
return;
|
||||
}
|
||||
|
@ -10582,8 +10597,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
break;
|
||||
case ZEND_AST_GREATER:
|
||||
case ZEND_AST_GREATER_EQUAL:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
|
||||
return;
|
||||
}
|
||||
|
@ -10595,8 +10608,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
case ZEND_AST_OR:
|
||||
{
|
||||
bool child0_is_true, child1_is_true;
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
if (ast->child[0]->kind != ZEND_AST_ZVAL) {
|
||||
return;
|
||||
}
|
||||
|
@ -10620,7 +10631,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
break;
|
||||
}
|
||||
case ZEND_AST_UNARY_OP:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
if (ast->child[0]->kind != ZEND_AST_ZVAL) {
|
||||
return;
|
||||
}
|
||||
|
@ -10631,7 +10641,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
break;
|
||||
case ZEND_AST_UNARY_PLUS:
|
||||
case ZEND_AST_UNARY_MINUS:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
if (ast->child[0]->kind != ZEND_AST_ZVAL) {
|
||||
return;
|
||||
}
|
||||
|
@ -10702,13 +10711,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
zend_error(E_COMPILE_ERROR, "Array and string offset access syntax with curly braces is no longer supported");
|
||||
}
|
||||
|
||||
/* Set isset fetch indicator here, opcache disallows runtime altering of the AST */
|
||||
if ((ast->attr & ZEND_DIM_IS) && ast->child[0]->kind == ZEND_AST_DIM) {
|
||||
ast->child[0]->attr |= ZEND_DIM_IS;
|
||||
}
|
||||
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
if (ast->child[0]->kind != ZEND_AST_ZVAL || ast->child[1]->kind != ZEND_AST_ZVAL) {
|
||||
return;
|
||||
}
|
||||
|
@ -10786,9 +10788,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
zend_ast *name_ast;
|
||||
zend_string *resolved_name;
|
||||
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
|
||||
if (UNEXPECTED(ast->child[1]->kind != ZEND_AST_ZVAL
|
||||
|| Z_TYPE_P(zend_ast_get_zval(ast->child[1])) != IS_STRING)) {
|
||||
return;
|
||||
|
@ -10818,33 +10817,6 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
}
|
||||
break;
|
||||
}
|
||||
// TODO: We should probably use zend_ast_apply to recursively walk nodes without
|
||||
// special handling. It is required that all nodes that are part of a const expr
|
||||
// are visited. Probably we should be distinguishing evaluation of const expr and
|
||||
// normal exprs here.
|
||||
case ZEND_AST_ARG_LIST:
|
||||
{
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
for (uint32_t i = 0; i < list->children; i++) {
|
||||
zend_eval_const_expr(&list->child[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ZEND_AST_NEW:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
return;
|
||||
case ZEND_AST_NAMED_ARG:
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
return;
|
||||
case ZEND_AST_CONST_ENUM_INIT:
|
||||
zend_eval_const_expr(&ast->child[2]);
|
||||
return;
|
||||
case ZEND_AST_PROP:
|
||||
case ZEND_AST_NULLSAFE_PROP:
|
||||
zend_eval_const_expr(&ast->child[0]);
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -10853,3 +10825,9 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
|||
*ast_ptr = zend_ast_create_zval(&result);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
|
||||
{
|
||||
zend_eval_const_expr_inner(ast_ptr, NULL);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue