diff options
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 278 |
1 files changed, 195 insertions, 83 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index c5c9f1f475..7210cb4bab 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -62,20 +62,15 @@ typedef struct _zend_loop_var { } u; } zend_loop_var; -static inline uint32_t zend_alloc_cache_slot(void) { +static inline uint32_t zend_alloc_cache_slots(unsigned count) { zend_op_array *op_array = CG(active_op_array); uint32_t ret = op_array->cache_size; - op_array->cache_size += sizeof(void*); + op_array->cache_size += count * sizeof(void*); return ret; } -#define POLYMORPHIC_CACHE_SLOT_SIZE 2 - -static inline uint32_t zend_alloc_polymorphic_cache_slot(void) { - zend_op_array *op_array = CG(active_op_array); - uint32_t ret = op_array->cache_size; - op_array->cache_size += POLYMORPHIC_CACHE_SLOT_SIZE * sizeof(void*); - return ret; +static inline uint32_t zend_alloc_cache_slot(void) { + return zend_alloc_cache_slots(1); } ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type); @@ -1605,6 +1600,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify ce->default_properties_count = 0; ce->default_static_members_count = 0; + ce->properties_info_table = NULL; if (nullify_handlers) { ce->constructor = NULL; @@ -2475,7 +2471,7 @@ static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */ +static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */ { if (is_this_fetch(ast)) { zend_op *opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL); @@ -2483,9 +2479,11 @@ static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, opline->result_type = IS_TMP_VAR; result->op_type = IS_TMP_VAR; } + return opline; } else if (zend_try_compile_cv(result, ast) == FAILURE) { - zend_compile_simple_var_no_cv(result, ast, type, delayed); + return zend_compile_simple_var_no_cv(result, ast, type, delayed); } + return NULL; } /* }}} */ @@ -2503,7 +2501,7 @@ static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t } /* }}} */ -void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type); +zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, zend_bool by_ref); void zend_compile_assign(znode *result, zend_ast *ast); static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */ @@ -2524,7 +2522,11 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t znode var_node, dim_node; - zend_delayed_compile_var(&var_node, var_ast, type); + opline = zend_delayed_compile_var(&var_node, var_ast, type, 0); + if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) { + opline->extended_value |= ZEND_FETCH_DIM_WRITE; + } + zend_separate_if_call_and_write(&var_node, var_ast, type); if (dim_ast == NULL) { @@ -2568,7 +2570,11 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t if (is_this_fetch(obj_ast)) { obj_node.op_type = IS_UNUSED; } else { - zend_delayed_compile_var(&obj_node, obj_ast, type); + opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); + if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) { + opline->extended_value |= ZEND_FETCH_OBJ_WRITE; + } + zend_separate_if_call_and_write(&obj_node, obj_ast, type); } zend_compile_expr(&prop_node, prop_ast); @@ -2576,7 +2582,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node); if (opline->op2_type == IS_CONST) { convert_to_string(CT_CONSTANT(opline->op2)); - opline->extended_value = zend_alloc_polymorphic_cache_slot(); + opline->extended_value = zend_alloc_cache_slots(3); } zend_adjust_for_fetch_type(opline, result, type); @@ -2584,15 +2590,18 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t } /* }}} */ -static zend_op *zend_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ +static zend_op *zend_compile_prop(znode *result, zend_ast *ast, uint32_t type, int by_ref) /* {{{ */ { uint32_t offset = zend_delayed_compile_begin(); - zend_delayed_compile_prop(result, ast, type); + zend_op *opline = zend_delayed_compile_prop(result, ast, type); + if (by_ref) { /* shared with cache_slot */ + opline->extended_value |= ZEND_FETCH_REF; + } return zend_delayed_compile_end(offset); } /* }}} */ -zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */ +zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int by_ref, int delayed) /* {{{ */ { zend_ast *class_ast = ast->child[0]; zend_ast *prop_ast = ast->child[1]; @@ -2611,7 +2620,7 @@ zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, i } if (opline->op1_type == IS_CONST) { convert_to_string(CT_CONSTANT(opline->op1)); - opline->extended_value = zend_alloc_polymorphic_cache_slot(); + opline->extended_value = zend_alloc_cache_slots(3); } if (class_node.op_type == IS_CONST) { opline->op2_type = IS_CONST; @@ -2624,6 +2633,10 @@ zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, i SET_NODE(opline->op2, &class_node); } + if (by_ref && (type == BP_VAR_W || type == BP_VAR_FUNC_ARG)) { /* shared with cache_slot */ + opline->extended_value |= ZEND_FETCH_REF; + } + zend_adjust_for_fetch_type(opline, result, type); return opline; } @@ -2854,13 +2867,22 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ switch (var_ast->kind) { case ZEND_AST_VAR: - case ZEND_AST_STATIC_PROP: offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W); + zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, 0); zend_compile_expr(&expr_node, expr_ast); zend_delayed_compile_end(offset); zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node); return; + case ZEND_AST_STATIC_PROP: + offset = zend_delayed_compile_begin(); + zend_delayed_compile_var(result, var_ast, BP_VAR_W, 0); + zend_compile_expr(&expr_node, expr_ast); + + opline = zend_delayed_compile_end(offset); + opline->opcode = ZEND_ASSIGN_STATIC_PROP; + + zend_emit_op_data(&expr_node); + return; case ZEND_AST_DIM: offset = zend_delayed_compile_begin(); zend_delayed_compile_dim(result, var_ast, BP_VAR_W); @@ -2901,7 +2923,7 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ "Cannot assign reference to non referencable value"); } - zend_compile_var(&expr_node, expr_ast, BP_VAR_W); + zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); /* MAKE_REF is usually not necessary for CVs. However, if there are * self-assignments, this forces the RHS to evaluate first. */ if (expr_node.op_type != IS_CV @@ -2945,8 +2967,8 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ zend_ensure_writable_variable(target_ast); offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W); - zend_compile_var(&source_node, source_ast, BP_VAR_W); + zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, 1); + zend_compile_var(&source_node, source_ast, BP_VAR_W, 1); if ((target_ast->kind != ZEND_AST_VAR || target_ast->child[0]->kind != ZEND_AST_ZVAL) @@ -2960,16 +2982,33 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ zend_emit_op(&source_node, ZEND_MAKE_REF, &source_node, NULL); } - zend_delayed_compile_end(offset); + opline = zend_delayed_compile_end(offset); if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context"); } - opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node); + if (opline && opline->opcode == ZEND_FETCH_OBJ_W) { + opline->opcode = ZEND_ASSIGN_OBJ_REF; + opline->extended_value &= ~ZEND_FETCH_REF; + zend_emit_op_data(&source_node); + if (result != NULL) { + *result = target_node; + } + } else if (opline && opline->opcode == ZEND_FETCH_STATIC_PROP_W) { + opline->opcode = ZEND_ASSIGN_STATIC_PROP_REF; + opline->extended_value &= ~ZEND_FETCH_REF; + zend_emit_op_data(&source_node); + if (result != NULL) { + *result = target_node; + } + } else { + opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node); + opline->extended_value = 0; + } if (zend_is_call(source_ast)) { - opline->extended_value = ZEND_RETURNS_FUNCTION; + opline->extended_value |= ZEND_RETURNS_FUNCTION; } } /* }}} */ @@ -2996,13 +3035,25 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */ switch (var_ast->kind) { case ZEND_AST_VAR: - case ZEND_AST_STATIC_PROP: offset = zend_delayed_compile_begin(); - zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW); + zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, 0); zend_compile_expr(&expr_node, expr_ast); zend_delayed_compile_end(offset); zend_emit_op(result, opcode, &var_node, &expr_node); return; + case ZEND_AST_STATIC_PROP: + offset = zend_delayed_compile_begin(); + zend_delayed_compile_var(result, var_ast, BP_VAR_RW, 0); + zend_compile_expr(&expr_node, expr_ast); + + opline = zend_delayed_compile_end(offset); + cache_slot = opline->extended_value; + opline->opcode = opcode; + opline->extended_value = ZEND_ASSIGN_STATIC_PROP; + + opline = zend_emit_op_data(&expr_node); + opline->extended_value = cache_slot; + return; case ZEND_AST_DIM: offset = zend_delayed_compile_begin(); zend_delayed_compile_dim(result, var_ast, BP_VAR_RW); @@ -3012,7 +3063,7 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */ opline->opcode = opcode; opline->extended_value = ZEND_ASSIGN_DIM; - opline = zend_emit_op_data(&expr_node); + zend_emit_op_data(&expr_node); return; case ZEND_AST_PROP: offset = zend_delayed_compile_begin(); @@ -3066,7 +3117,7 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ arg_count++; if (zend_is_variable(arg)) { if (zend_is_call(arg)) { - zend_compile_var(&arg_node, arg, BP_VAR_R); + zend_compile_var(&arg_node, arg, BP_VAR_R, 0); if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) { /* Function call was converted into builtin instruction */ opcode = ZEND_SEND_VAL; @@ -3085,10 +3136,10 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } } else if (fbc) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { - zend_compile_var(&arg_node, arg, BP_VAR_W); + zend_compile_var(&arg_node, arg, BP_VAR_W, 1); opcode = ZEND_SEND_REF; } else { - zend_compile_var(&arg_node, arg, BP_VAR_R); + zend_compile_var(&arg_node, arg, BP_VAR_R, 0); opcode = (arg_node.op_type == IS_TMP_VAR) ? ZEND_SEND_VAL : ZEND_SEND_VAR; } } else { @@ -3106,7 +3157,7 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } opline = zend_emit_op(NULL, ZEND_CHECK_FUNC_ARG, NULL, NULL); opline->op2.num = arg_num; - zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG); + zend_compile_var(&arg_node, arg, BP_VAR_FUNC_ARG, 1); opcode = ZEND_SEND_FUNC_ARG; } while (0); } @@ -3250,7 +3301,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a opline->op2_type = IS_CONST; opline->op2.constant = zend_add_func_name_literal(method); /* 2 slots, for class and method */ - opline->result.num = zend_alloc_polymorphic_cache_slot(); + opline->result.num = zend_alloc_cache_slots(2); zval_ptr_dtor(&name_node->u.constant); } else { zend_op *opline = get_next_op(); @@ -3980,7 +4031,7 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{ opline->op2_type = IS_CONST; opline->op2.constant = zend_add_func_name_literal( Z_STR(method_node.u.constant)); - opline->result.num = zend_alloc_polymorphic_cache_slot(); + opline->result.num = zend_alloc_cache_slots(2); } else { SET_NODE(opline->op2, &method_node); } @@ -4041,7 +4092,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ opline->op2_type = IS_CONST; opline->op2.constant = zend_add_func_name_literal( Z_STR(method_node.u.constant)); - opline->result.num = zend_alloc_polymorphic_cache_slot(); + opline->result.num = zend_alloc_cache_slots(2); } else { if (opline->op1_type == IS_CONST) { opline->result.num = zend_alloc_cache_slot(); @@ -4239,11 +4290,11 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */ opline->opcode = ZEND_UNSET_DIM; return; case ZEND_AST_PROP: - opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET); + opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET, 0); opline->opcode = ZEND_UNSET_OBJ; return; case ZEND_AST_STATIC_PROP: - opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, 0); + opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, 0, 0); opline->opcode = ZEND_UNSET_STATIC_PROP; return; EMPTY_SWITCH_DEFAULT_CASE() @@ -4356,7 +4407,7 @@ void zend_compile_return(zend_ast *ast) /* {{{ */ expr_node.op_type = IS_CONST; ZVAL_NULL(&expr_node.u.constant); } else if (by_ref && zend_is_variable(expr_ast) && !zend_is_call(expr_ast)) { - zend_compile_var(&expr_node, expr_ast, BP_VAR_W); + zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); } else { zend_compile_expr(&expr_node, expr_ast); } @@ -4714,7 +4765,7 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */ } if (by_ref && is_variable) { - zend_compile_var(&expr_node, expr_ast, BP_VAR_W); + zend_compile_var(&expr_node, expr_ast, BP_VAR_W, 1); } else { zend_compile_expr(&expr_node, expr_ast); } @@ -5979,10 +6030,9 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* } /* }}} */ -void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ +void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); - uint32_t flags = list->attr; zend_class_entry *ce = CG(active_class_entry); uint32_t i, children = list->children; @@ -6002,6 +6052,19 @@ void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast)); zend_string *doc_comment = NULL; zval value_zv; + zend_type type = 0; + + if (type_ast) { + type = zend_compile_typename(type_ast, 0); + + if (ZEND_TYPE_CODE(type) == IS_VOID || ZEND_TYPE_CODE(type) == IS_CALLABLE) { + zend_error_noreturn(E_COMPILE_ERROR, + "Property %s::$%s cannot have type %s", + ZSTR_VAL(ce->name), + ZSTR_VAL(name), + zend_get_type_by_const(ZEND_TYPE_CODE(type))); + } + } /* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */ if (doc_comment_ast) { @@ -6021,15 +6084,58 @@ void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ if (value_ast) { zend_const_expr_to_zval(&value_zv, value_ast); - } else { + + if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) { + if (Z_TYPE(value_zv) == IS_NULL) { + if (!ZEND_TYPE_ALLOW_NULL(type)) { + const char *name = ZEND_TYPE_IS_CLASS(type) + ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); + zend_error_noreturn(E_COMPILE_ERROR, + "Default value for property of type %s may not be null. " + "Use the nullable type ?%s to allow null default value", + name, name); + } + } else if (ZEND_TYPE_IS_CLASS(type)) { + zend_error_noreturn(E_COMPILE_ERROR, + "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type))); + } else if (ZEND_TYPE_CODE(type) == IS_ARRAY || ZEND_TYPE_CODE(type) == IS_ITERABLE) { + if (Z_TYPE(value_zv) != IS_ARRAY) { + zend_error_noreturn(E_COMPILE_ERROR, + "Default value for property of type %s can only be an array", + zend_get_type_by_const(ZEND_TYPE_CODE(type))); + } + } else if (ZEND_TYPE_CODE(type) == IS_DOUBLE) { + if (Z_TYPE(value_zv) != IS_DOUBLE && Z_TYPE(value_zv) != IS_LONG) { + zend_error_noreturn(E_COMPILE_ERROR, + "Default value for property of type float can only be float or int"); + } + } else if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(type), Z_TYPE(value_zv))) { + zend_error_noreturn(E_COMPILE_ERROR, + "Default value for property of type %s can only be %s", + zend_get_type_by_const(ZEND_TYPE_CODE(type)), + zend_get_type_by_const(ZEND_TYPE_CODE(type))); + } + } + } else if (!ZEND_TYPE_IS_SET(type)) { ZVAL_NULL(&value_zv); + } else { + ZVAL_UNDEF(&value_zv); } - zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment); + zend_declare_typed_property(ce, name, &value_zv, flags, doc_comment, type); } } /* }}} */ +void zend_compile_prop_group(zend_ast *list) /* {{{ */ +{ + zend_ast *type_ast = list->child[0]; + zend_ast *prop_ast = list->child[1]; + + zend_compile_prop_decl(prop_ast, type_ast, list->attr); +} +/* }}} */ + void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -6378,6 +6484,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ CG(zend_lineno) = decl->end_lineno; ce->ce_flags |= ZEND_ACC_LINKED; zend_do_inheritance(ce, parent_ce); + zend_build_properties_info_table(ce); if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { zend_verify_abstract_class(ce); } @@ -6389,6 +6496,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } else { if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) { zend_string_release(lcname); + zend_build_properties_info_table(ce); ce->ce_flags |= ZEND_ACC_LINKED; return; } @@ -7192,12 +7300,16 @@ void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */ zend_ensure_writable_variable(var_ast); if (var_ast->kind == ZEND_AST_PROP) { - zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW); + zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW, 0); opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ; zend_make_tmp_result(result, opline); + } else if (var_ast->kind == ZEND_AST_STATIC_PROP) { + zend_op *opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_RW, 0, 0); + opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_STATIC_PROP : ZEND_POST_DEC_STATIC_PROP; + zend_make_tmp_result(result, opline); } else { znode var_node; - zend_compile_var(&var_node, var_ast, BP_VAR_RW); + zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0); zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC, &var_node, NULL); } @@ -7212,11 +7324,14 @@ void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */ zend_ensure_writable_variable(var_ast); if (var_ast->kind == ZEND_AST_PROP) { - zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW); + zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW, 0); opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ; + } else if (var_ast->kind == ZEND_AST_STATIC_PROP) { + zend_op *opline = zend_compile_static_prop(result, var_ast, BP_VAR_RW, 0, 0); + opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_STATIC_PROP : ZEND_PRE_DEC_STATIC_PROP; } else { znode var_node; - zend_compile_var(&var_node, var_ast, BP_VAR_RW); + zend_compile_var(&var_node, var_ast, BP_VAR_RW, 0); zend_emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC, &var_node, NULL); } @@ -7310,7 +7425,7 @@ void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */ zend_op *opline; uint32_t opnum; - zend_compile_var(&expr_node, expr_ast, BP_VAR_IS); + zend_compile_var(&expr_node, expr_ast, BP_VAR_IS, 0); opnum = get_next_op_number(); zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL); @@ -7377,7 +7492,7 @@ void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */ if (value_ast) { if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) { - zend_compile_var(&value_node, value_ast, BP_VAR_W); + zend_compile_var(&value_node, value_ast, BP_VAR_W, 1); } else { zend_compile_expr(&value_node, value_ast); } @@ -7495,11 +7610,11 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ; break; case ZEND_AST_PROP: - opline = zend_compile_prop(result, var_ast, BP_VAR_IS); + opline = zend_compile_prop(result, var_ast, BP_VAR_IS, 0); opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ; break; case ZEND_AST_STATIC_PROP: - opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, 0); + opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, 0, 0); opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP; break; EMPTY_SWITCH_DEFAULT_CASE() @@ -7593,7 +7708,7 @@ void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */ if (by_ref) { zend_ensure_writable_variable(value_ast); - zend_compile_var(&value_node, value_ast, BP_VAR_W); + zend_compile_var(&value_node, value_ast, BP_VAR_W, 1); } else { zend_compile_expr(&value_node, value_ast); } @@ -7709,7 +7824,7 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */ zend_set_class_name_op1(opline, &class_node); - opline->extended_value = zend_alloc_polymorphic_cache_slot(); + opline->extended_value = zend_alloc_cache_slots(2); } /* }}} */ @@ -8146,8 +8261,8 @@ void zend_compile_stmt(zend_ast *ast) /* {{{ */ case ZEND_AST_METHOD: zend_compile_func_decl(NULL, ast, 0); break; - case ZEND_AST_PROP_DECL: - zend_compile_prop_decl(ast); + case ZEND_AST_PROP_GROUP: + zend_compile_prop_group(ast); break; case ZEND_AST_CLASS_CONST_DECL: zend_compile_class_const_decl(ast); @@ -8207,7 +8322,7 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */ case ZEND_AST_CALL: case ZEND_AST_METHOD_CALL: case ZEND_AST_STATIC_CALL: - zend_compile_var(result, ast, BP_VAR_R); + zend_compile_var(result, ast, BP_VAR_R, 0); return; case ZEND_AST_ASSIGN: zend_compile_assign(result, ast); @@ -8314,35 +8429,31 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */ } /* }}} */ -void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ +zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, int by_ref) /* {{{ */ { CG(zend_lineno) = zend_ast_get_lineno(ast); switch (ast->kind) { case ZEND_AST_VAR: - zend_compile_simple_var(result, ast, type, 0); - return; + return zend_compile_simple_var(result, ast, type, 0); case ZEND_AST_DIM: - zend_compile_dim(result, ast, type); - return; + return zend_compile_dim(result, ast, type); case ZEND_AST_PROP: - zend_compile_prop(result, ast, type); - return; + return zend_compile_prop(result, ast, type, by_ref); case ZEND_AST_STATIC_PROP: - zend_compile_static_prop(result, ast, type, 0); - return; + return zend_compile_static_prop(result, ast, type, by_ref, 0); case ZEND_AST_CALL: zend_compile_call(result, ast, type); - return; + return NULL; case ZEND_AST_METHOD_CALL: zend_compile_method_call(result, ast, type); - return; + return NULL; case ZEND_AST_STATIC_CALL: zend_compile_static_call(result, ast, type); - return; + return NULL; case ZEND_AST_ZNODE: *result = *zend_ast_get_znode(ast); - return; + return NULL; default: if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) { zend_error_noreturn(E_COMPILE_ERROR, @@ -8350,29 +8461,30 @@ void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ } zend_compile_expr(result, ast); - return; + return NULL; } } /* }}} */ -void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ +zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, zend_bool by_ref) /* {{{ */ { switch (ast->kind) { case ZEND_AST_VAR: - zend_compile_simple_var(result, ast, type, 1); - return; + return zend_compile_simple_var(result, ast, type, 1); case ZEND_AST_DIM: - zend_delayed_compile_dim(result, ast, type); - return; + return zend_delayed_compile_dim(result, ast, type); case ZEND_AST_PROP: - zend_delayed_compile_prop(result, ast, type); - return; + { + zend_op *opline = zend_delayed_compile_prop(result, ast, type); + if (by_ref) { + opline->extended_value |= ZEND_FETCH_REF; + } + return opline; + } case ZEND_AST_STATIC_PROP: - zend_compile_static_prop(result, ast, type, 1); - return; + return zend_compile_static_prop(result, ast, type, by_ref, 1); default: - zend_compile_var(result, ast, type); - return; + return zend_compile_var(result, ast, type, 0); } } /* }}} */ |