mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Allow arbitrary expressions in static variable initializer
Closes GH-9301
This commit is contained in:
parent
3189a9f94a
commit
0b1d750d91
44 changed files with 1118 additions and 690 deletions
|
@ -2293,6 +2293,7 @@ static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_t
|
|||
case ZEND_JMP_SET:
|
||||
case ZEND_COALESCE:
|
||||
case ZEND_JMP_NULL:
|
||||
case ZEND_BIND_INIT_STATIC_OR_JMP:
|
||||
opline->op2.opline_num = opnum_target;
|
||||
break;
|
||||
EMPTY_SWITCH_DEFAULT_CASE()
|
||||
|
@ -4885,16 +4886,55 @@ static void zend_compile_static_var_common(zend_string *var_name, zval *value, u
|
|||
static void zend_compile_static_var(zend_ast *ast) /* {{{ */
|
||||
{
|
||||
zend_ast *var_ast = ast->child[0];
|
||||
zend_ast **value_ast_ptr = &ast->child[1];
|
||||
zval value_zv;
|
||||
zend_string *var_name = zend_ast_get_str(var_ast);
|
||||
|
||||
if (*value_ast_ptr) {
|
||||
zend_const_expr_to_zval(&value_zv, value_ast_ptr, /* allow_dynamic */ true);
|
||||
} else {
|
||||
ZVAL_NULL(&value_zv);
|
||||
if (zend_string_equals_literal(var_name, "this")) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
|
||||
}
|
||||
|
||||
zend_compile_static_var_common(zend_ast_get_str(var_ast), &value_zv, ZEND_BIND_REF);
|
||||
if (!CG(active_op_array)->static_variables) {
|
||||
if (CG(active_op_array)->scope) {
|
||||
CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
|
||||
}
|
||||
CG(active_op_array)->static_variables = zend_new_array(8);
|
||||
}
|
||||
|
||||
if (zend_hash_exists(CG(active_op_array)->static_variables, var_name)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Duplicate declaration of static variable $%s", ZSTR_VAL(var_name));
|
||||
}
|
||||
|
||||
zend_eval_const_expr(&ast->child[1]);
|
||||
zend_ast *value_ast = ast->child[1];
|
||||
|
||||
if (!value_ast || value_ast->kind == ZEND_AST_ZVAL) {
|
||||
zval *value_zv = value_ast
|
||||
? zend_ast_get_zval(value_ast)
|
||||
: &EG(uninitialized_zval);
|
||||
Z_TRY_ADDREF_P(value_zv);
|
||||
zend_compile_static_var_common(var_name, value_zv, ZEND_BIND_REF);
|
||||
} else {
|
||||
zend_op *opline;
|
||||
|
||||
zval *placeholder_ptr = zend_hash_update(CG(active_op_array)->static_variables, var_name, &EG(uninitialized_zval));
|
||||
Z_TYPE_EXTRA_P(placeholder_ptr) |= IS_STATIC_VAR_UNINITIALIZED;
|
||||
uint32_t placeholder_offset = (uint32_t)((char*)placeholder_ptr - (char*)CG(active_op_array)->static_variables->arData);
|
||||
|
||||
uint32_t static_def_jmp_opnum = get_next_op_number();
|
||||
opline = zend_emit_op(NULL, ZEND_BIND_INIT_STATIC_OR_JMP, NULL, NULL);
|
||||
opline->op1_type = IS_CV;
|
||||
opline->op1.var = lookup_cv(var_name);
|
||||
opline->extended_value = placeholder_offset;
|
||||
|
||||
znode expr;
|
||||
zend_compile_expr(&expr, value_ast);
|
||||
|
||||
opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &expr);
|
||||
opline->op1_type = IS_CV;
|
||||
opline->op1.var = lookup_cv(var_name);
|
||||
opline->extended_value = placeholder_offset | ZEND_BIND_REF;
|
||||
|
||||
zend_update_jump_target_to_next(static_def_jmp_opnum);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue