diff options
Diffstat (limited to 'Zend/zend_compile.c')
| -rw-r--r-- | Zend/zend_compile.c | 442 |
1 files changed, 245 insertions, 197 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 95d93903de..68cd87d40b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -98,26 +98,6 @@ static void zend_destroy_property_info_internal(zval *zv) /* {{{ */ } /* }}} */ -static void zend_destroy_class_constant_internal(zval *zv) /* {{{ */ -{ - free(Z_PTR_P(zv)); -} -/* }}} */ - -static zend_string *zend_new_interned_string_safe(zend_string *str) /* {{{ */ { - zend_string *interned_str; - - zend_string_addref(str); - interned_str = zend_new_interned_string(str); - if (str != interned_str) { - return interned_str; - } else { - zend_string_release(str); - return str; - } -} -/* }}} */ - static zend_string *zend_build_runtime_definition_key(zend_string *name, unsigned char *lex_pos) /* {{{ */ { zend_string *result; @@ -382,8 +362,9 @@ ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filen return Z_STR_P(p); } - ZVAL_STR_COPY(&rv, new_compiled_filename); - zend_hash_update(&CG(filenames_table), new_compiled_filename, &rv); + new_compiled_filename = zend_new_interned_string(zend_string_copy(new_compiled_filename)); + ZVAL_STR(&rv, new_compiled_filename); + zend_hash_add_new(&CG(filenames_table), new_compiled_filename, &rv); CG(compiled_filename) = new_compiled_filename; return new_compiled_filename; @@ -420,16 +401,14 @@ static uint32_t get_temporary_variable(zend_op_array *op_array) /* {{{ */ } /* }}} */ -static int lookup_cv(zend_op_array *op_array, zend_string* name) /* {{{ */{ +static int lookup_cv(zend_op_array *op_array, zend_string *name) /* {{{ */{ int i = 0; zend_ulong hash_value = zend_string_hash_val(name); while (i < op_array->last_var) { if (ZSTR_VAL(op_array->vars[i]) == ZSTR_VAL(name) || (ZSTR_H(op_array->vars[i]) == hash_value && - ZSTR_LEN(op_array->vars[i]) == ZSTR_LEN(name) && - memcmp(ZSTR_VAL(op_array->vars[i]), ZSTR_VAL(name), ZSTR_LEN(name)) == 0)) { - zend_string_release(name); + zend_string_equal_content(op_array->vars[i], name))) { return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i); } i++; @@ -441,7 +420,7 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name) /* {{{ */{ op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*)); } - op_array->vars[i] = zend_new_interned_string(name); + op_array->vars[i] = zend_string_copy(name); return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i); } /* }}} */ @@ -457,15 +436,21 @@ void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */ } /* }}} */ +static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */ +{ + ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); + Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv)); + if (ZSTR_IS_INTERNED(Z_STR_P(zv))) { + Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); + } + return Z_STR_P(zv); +} + /* Common part of zend_add_literal and zend_append_individual_literal */ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */ { - if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) { - zend_string_hash_val(Z_STR_P(zv)); - Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv)); - if (ZSTR_IS_INTERNED(Z_STR_P(zv))) { - Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); - } + if (Z_TYPE_P(zv) == IS_STRING) { + zval_make_interned_string(zv); } ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv); Z_CACHE_SLOT(op_array->literals[literal_position]) = -1; @@ -786,7 +771,8 @@ void zend_do_free(znode *op1) /* {{{ */ } } else { while (opline >= CG(active_op_array)->opcodes) { - if (opline->opcode == ZEND_FETCH_LIST && + if ((opline->opcode == ZEND_FETCH_LIST_R || + opline->opcode == ZEND_FETCH_LIST_W) && opline->op1_type == IS_VAR && opline->op1.var == op1->u.op.var) { zend_emit_op(NULL, ZEND_FREE, op1, NULL); @@ -1061,7 +1047,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ } if (op_array->static_variables) { if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_REFCOUNT(op_array->static_variables)++; + GC_ADDREF(op_array->static_variables); } } op_array->run_time_cache = NULL; @@ -1076,25 +1062,28 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */ { zend_function *function, *new_function; - zval *lcname, *rtd_key; + zval *lcname, *rtd_key, *zv; if (compile_time) { lcname = CT_CONSTANT_EX(op_array, opline->op1.constant); rtd_key = lcname + 1; } else { - lcname = RT_CONSTANT(op_array, opline->op1); + lcname = RT_CONSTANT(opline, opline->op1); rtd_key = lcname + 1; } - function = zend_hash_find_ptr(function_table, Z_STR_P(rtd_key)); + zv = zend_hash_find_ex(function_table, Z_STR_P(rtd_key), 1); + function = (zend_function*)Z_PTR_P(zv); new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, function, sizeof(zend_op_array)); if (zend_hash_add_ptr(function_table, Z_STR_P(lcname), new_function) == NULL) { int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR; zend_function *old_function; - if ((old_function = zend_hash_find_ptr(function_table, Z_STR_P(lcname))) != NULL - && old_function->type == ZEND_USER_FUNCTION + zv = zend_hash_find_ex(function_table, Z_STR_P(lcname), 1); + ZEND_ASSERT(zv != NULL); + old_function = (zend_function*)Z_PTR_P(zv); + if (old_function->type == ZEND_USER_FUNCTION && old_function->op_array.last > 0) { zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)", ZSTR_VAL(function->common.function_name), @@ -1117,17 +1106,18 @@ ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opli ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time) /* {{{ */ { zend_class_entry *ce; - zval *lcname, *rtd_key; + zval *lcname, *rtd_key, *zv; if (compile_time) { lcname = CT_CONSTANT_EX(op_array, opline->op1.constant); rtd_key = lcname + 1; } else { - lcname = RT_CONSTANT(op_array, opline->op1); + lcname = RT_CONSTANT(opline, opline->op1); rtd_key = lcname + 1; } - ce = zend_hash_find_ptr(class_table, Z_STR_P(rtd_key)); - ZEND_ASSERT(ce); + zv = zend_hash_find_ex(class_table, Z_STR_P(rtd_key), 1); + ZEND_ASSERT(zv); + ce = (zend_class_entry*)Z_PTR_P(zv); ce->refcount++; if (zend_hash_add_ptr(class_table, Z_STR_P(lcname), ce) == NULL) { ce->refcount--; @@ -1152,19 +1142,19 @@ ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const ze ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time) /* {{{ */ { zend_class_entry *ce; - zval *lcname, *rtd_key; + zval *lcname, *rtd_key, *zv; if (compile_time) { lcname = CT_CONSTANT_EX(op_array, opline->op1.constant); rtd_key = lcname + 1; } else { - lcname = RT_CONSTANT(op_array, opline->op1); + lcname = RT_CONSTANT(opline, opline->op1); rtd_key = lcname + 1; } - ce = zend_hash_find_ptr(class_table, Z_STR_P(rtd_key)); + zv = zend_hash_find_ex(class_table, Z_STR_P(rtd_key), 1); - if (!ce) { + if (!zv) { if (!compile_time) { /* If we're in compile time, in practice, it's quite possible * that we'll never reach this class declaration at runtime, @@ -1176,6 +1166,8 @@ ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array return NULL; } + ce = (zend_class_entry*)Z_PTR_P(zv); + if (zend_hash_exists(class_table, Z_STR_P(lcname))) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); } @@ -1278,7 +1270,7 @@ static void zend_mark_function_as_generator() /* {{{ */ if (ZEND_TYPE_CODE(return_info.type) != IS_ITERABLE) { const char *msg = "Generators may only declare a return type of Generator, Iterator, Traversable, or iterable, %s is not permitted"; - + if (!ZEND_TYPE_IS_CLASS(return_info.type)) { zend_error_noreturn(E_COMPILE_ERROR, msg, zend_get_type_by_const(ZEND_TYPE_CODE(return_info.type))); } @@ -1304,7 +1296,8 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array) /* {{ CG(in_compilation) = 1; while (opline_num != (uint32_t)-1) { - zval *parent_name = RT_CONSTANT(op_array, op_array->opcodes[opline_num-1].op2); + const zend_op *opline = &op_array->opcodes[opline_num-1]; + zval *parent_name = RT_CONSTANT(opline, opline->op2); if ((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) != NULL) { do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0); } @@ -1401,7 +1394,7 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i ((c->flags & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION)) || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) )) { - ZVAL_DUP(zv, &c->value); + ZVAL_COPY_OR_DUP(zv, &c->value); return 1; } @@ -1416,7 +1409,7 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i c = zend_lookup_reserved_const(lookup_name, lookup_len); if (c) { - ZVAL_DUP(zv, &c->value); + ZVAL_COPY_OR_DUP(zv, &c->value); return 1; } } @@ -1569,7 +1562,7 @@ static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, /* Substitute case-sensitive (or lowercase) persistent class constants */ if (Z_TYPE_P(c) < IS_OBJECT) { - ZVAL_DUP(zv, c); + ZVAL_COPY_OR_DUP(zv, c); return 1; } @@ -1677,13 +1670,12 @@ int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global zend_auto_global auto_global; int retval; - auto_global.name = zend_new_interned_string(name); + auto_global.name = name; auto_global.auto_global_callback = auto_global_callback; auto_global.jit = jit; retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE; - zend_string_release(name); return retval; } /* }}} */ @@ -1759,7 +1751,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify ce->default_properties_table = NULL; ce->default_static_members_table = NULL; zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : NULL), persistent_hashes, 0); - zend_hash_init_ex(&ce->constants_table, 8, NULL, (persistent_hashes ? zend_destroy_class_constant_internal : NULL), persistent_hashes, 0); + zend_hash_init_ex(&ce->constants_table, 8, NULL, NULL, persistent_hashes, 0); zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0); if (ce->type == ZEND_INTERNAL_CLASS) { @@ -1947,10 +1939,6 @@ ZEND_API size_t zend_dirname(char *path, size_t len) static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */ { zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3; - - if (opline->opcode == ZEND_FETCH_THIS) { - return; - } switch (type & BP_VAR_MASK) { case BP_VAR_R: @@ -2091,7 +2079,8 @@ static void zend_check_live_ranges(zend_op *opline) /* {{{ */ opline->opcode == ZEND_ROPE_ADD || opline->opcode == ZEND_ROPE_END || opline->opcode == ZEND_END_SILENCE || - opline->opcode == ZEND_FETCH_LIST || + opline->opcode == ZEND_FETCH_LIST_R || + opline->opcode == ZEND_FETCH_LIST_W || opline->opcode == ZEND_VERIFY_RETURN_TYPE || opline->opcode == ZEND_BIND_LEXICAL) { /* these opcodes are handled separately */ @@ -2185,7 +2174,7 @@ static void zend_emit_tick(void) /* {{{ */ if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) { return; } - + opline = get_next_op(CG(active_op_array)); opline->opcode = ZEND_TICKS; @@ -2575,18 +2564,25 @@ static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *name_ast = ast->child[0]; if (name_ast->kind == ZEND_AST_ZVAL) { - zend_string *name = zval_get_string(zend_ast_get_zval(name_ast)); + zval *zv = zend_ast_get_zval(name_ast); + zend_string *name; + + if (EXPECTED(Z_TYPE_P(zv) == IS_STRING)) { + name = zval_make_interned_string(zv); + } else { + name = zend_new_interned_string(zval_get_string_func(zv)); + } if (zend_is_auto_global(name)) { - zend_string_release(name); return FAILURE; } result->op_type = IS_CV; result->u.op.var = lookup_cv(CG(active_op_array), name); - /* lookup_cv may be using another zend_string instance */ - name = CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)]; + if (UNEXPECTED(Z_TYPE_P(zv) != IS_STRING)) { + zend_string_release(name); + } return SUCCESS; } @@ -2612,7 +2608,7 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL); } - if (name_node.op_type == IS_CONST && + if (name_node.op_type == IS_CONST && zend_is_auto_global(Z_STR(name_node.u.constant))) { opline->extended_value = ZEND_FETCH_GLOBAL; @@ -2620,6 +2616,7 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint opline->extended_value = ZEND_FETCH_LOCAL; } + zend_adjust_for_fetch_type(opline, type); return opline; } /* }}} */ @@ -2637,14 +2634,10 @@ 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) /* {{{ */ { - zend_op *opline; - if (is_this_fetch(ast)) { - opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL); - zend_adjust_for_fetch_type(opline, type); + zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL); } else if (zend_try_compile_cv(result, ast) == FAILURE) { - zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type, delayed); - zend_adjust_for_fetch_type(opline, type); + zend_compile_simple_var_no_cv(result, ast, type, delayed); } } /* }}} */ @@ -2665,18 +2658,13 @@ 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); void zend_compile_assign(znode *result, zend_ast *ast); -static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node, zend_bool old_style); static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */ { znode dummy_node; - if (var_ast->kind == ZEND_AST_ARRAY) { - zend_compile_list_assign(&dummy_node, var_ast, value_node, var_ast->attr); - } else { - zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast, - zend_ast_create_znode(value_node)); - zend_compile_assign(&dummy_node, assign_ast); - } + zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast, + zend_ast_create_znode(value_node)); + zend_compile_assign(&dummy_node, assign_ast); zend_do_free(&dummy_node); } /* }}} */ @@ -2685,6 +2673,7 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t { zend_ast *var_ast = ast->child[0]; zend_ast *dim_ast = ast->child[1]; + zend_op *opline; znode var_node, dim_node; @@ -2704,11 +2693,13 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t zend_handle_numeric_op(&dim_node); } - return zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node); + opline = zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node); + zend_adjust_for_fetch_type(opline, type); + return opline; } /* }}} */ -static inline zend_op *zend_compile_dim_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ +static zend_op *zend_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { uint32_t offset = zend_delayed_compile_begin(); zend_delayed_compile_dim(result, ast, type); @@ -2716,13 +2707,6 @@ static inline zend_op *zend_compile_dim_common(znode *result, zend_ast *ast, uin } /* }}} */ -void zend_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ -{ - zend_op *opline = zend_compile_dim_common(result, ast, type); - zend_adjust_for_fetch_type(opline, type); -} -/* }}} */ - static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *obj_ast = ast->child[0]; @@ -2745,11 +2729,12 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t zend_alloc_polymorphic_cache_slot(opline->op2.constant); } + zend_adjust_for_fetch_type(opline, type); return opline; } /* }}} */ -static zend_op *zend_compile_prop_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ +static zend_op *zend_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { uint32_t offset = zend_delayed_compile_begin(); zend_delayed_compile_prop(result, ast, type); @@ -2757,14 +2742,7 @@ static zend_op *zend_compile_prop_common(znode *result, zend_ast *ast, uint32_t } /* }}} */ -void zend_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ -{ - zend_op *opline = zend_compile_prop_common(result, ast, type); - zend_adjust_for_fetch_type(opline, type); -} -/* }}} */ - -zend_op *zend_compile_static_prop_common(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 delayed) /* {{{ */ { zend_ast *class_ast = ast->child[0]; zend_ast *prop_ast = ast->child[1]; @@ -2793,14 +2771,8 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t SET_NODE(opline->op2, &class_node); } - return opline; -} -/* }}} */ - -void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */ -{ - zend_op *opline = zend_compile_static_prop_common(result, ast, type, delayed); zend_adjust_for_fetch_type(opline, type); + return opline; } /* }}} */ @@ -2818,6 +2790,30 @@ static void zend_verify_list_assign_target(zend_ast *var_ast, zend_bool old_styl } /* }}} */ +static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node); + +/* Propagate refs used on leaf elements to the surrounding list() structures. */ +static zend_bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */ + zend_ast_list *list = zend_ast_get_list(ast); + zend_bool has_refs = 0; + uint32_t i; + + for (i = 0; i < list->children; ++i) { + zend_ast *elem_ast = list->child[i]; + + if (elem_ast) { + zend_ast *var_ast = elem_ast->child[0]; + if (var_ast->kind == ZEND_AST_ARRAY) { + elem_ast->attr = zend_propagate_list_refs(var_ast); + } + has_refs |= elem_ast->attr; + } + } + + return has_refs; +} +/* }}} */ + static void zend_compile_list_assign( znode *result, zend_ast *ast, znode *expr_node, zend_bool old_style) /* {{{ */ { @@ -2827,6 +2823,10 @@ static void zend_compile_list_assign( zend_bool is_keyed = list->children > 0 && list->child[0] != NULL && list->child[0]->child[1] != NULL; + if (list->children && expr_node->op_type == IS_CONST && Z_TYPE(expr_node->u.constant) == IS_STRING) { + zval_make_interned_string(&expr_node->u.constant); + } + for (i = 0; i < list->children; ++i) { zend_ast *elem_ast = list->child[i]; zend_ast *var_ast, *key_ast; @@ -2841,10 +2841,6 @@ static void zend_compile_list_assign( } } - if (elem_ast->attr) { - zend_error(E_COMPILE_ERROR, "[] and list() assignments cannot be by reference"); - } - var_ast = elem_ast->child[0]; key_ast = elem_ast->child[1]; has_elems = 1; @@ -2872,15 +2868,30 @@ static void zend_compile_list_assign( zend_verify_list_assign_target(var_ast, old_style); - zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node); - zend_emit_assign_znode(var_ast, &fetch_result); + zend_emit_op(&fetch_result, + elem_ast->attr ? ZEND_FETCH_LIST_W : ZEND_FETCH_LIST_R, expr_node, &dim_node); + + if (var_ast->kind == ZEND_AST_ARRAY) { + if (elem_ast->attr) { + zend_emit_op(&fetch_result, ZEND_MAKE_REF, &fetch_result, NULL); + } + zend_compile_list_assign(NULL, var_ast, &fetch_result, var_ast->attr); + } else if (elem_ast->attr) { + zend_emit_assign_ref_znode(var_ast, &fetch_result); + } else { + zend_emit_assign_znode(var_ast, &fetch_result); + } } if (has_elems == 0) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list"); } - *result = *expr_node; + if (result) { + *result = *expr_node; + } else { + zend_do_free(expr_node); + } } /* }}} */ @@ -2999,7 +3010,13 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ if (zend_is_assign_to_self(var_ast, expr_ast) && !is_this_fetch(expr_ast)) { /* $a[0] = $a should evaluate the right $a first */ - zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0); + znode cv_node; + + if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) { + zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0); + } else { + zend_emit_op(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL); + } } else { zend_compile_expr(&expr_node, expr_ast); } @@ -3020,11 +3037,32 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ zend_emit_op_data(&expr_node); return; case ZEND_AST_ARRAY: - if (zend_list_has_assign_to_self(var_ast, expr_ast)) { - /* list($a, $b) = $a should evaluate the right $a first */ - zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0); + if (zend_propagate_list_refs(var_ast)) { + if (!zend_is_variable(expr_ast)) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot assign reference to non referencable value"); + } + + zend_compile_var(&expr_node, expr_ast, BP_VAR_W); + /* 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 + || zend_list_has_assign_to_self(var_ast, expr_ast)) { + zend_emit_op(&expr_node, ZEND_MAKE_REF, &expr_node, NULL); + } } else { - zend_compile_expr(&expr_node, expr_ast); + if (zend_list_has_assign_to_self(var_ast, expr_ast)) { + /* list($a, $b) = $a should evaluate the right $a first */ + znode cv_node; + + if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) { + zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0); + } else { + zend_emit_op(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL); + } + } else { + zend_compile_expr(&expr_node, expr_ast); + } } zend_compile_list_assign(result, var_ast, &expr_node, var_ast->attr); @@ -3402,7 +3440,11 @@ int zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t typ zend_compile_expr(&arg_node, args->child[0]); opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL); - opline->extended_value = type; + if (type != _IS_BOOL) { + opline->extended_value = (1 << type); + } else { + opline->extended_value = (1 << IS_FALSE) | (1 << IS_TRUE); + } return SUCCESS; } /* }}} */ @@ -3711,9 +3753,8 @@ static int zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ zend_bool ok = 1; zval *val, tmp; HashTable *src = Z_ARRVAL(array.u.constant); - HashTable *dst = emalloc(sizeof(HashTable)); + HashTable *dst = zend_new_array(zend_hash_num_elements(src)); - zend_hash_init(dst, zend_hash_num_elements(src), NULL, ZVAL_PTR_DTOR, 0); ZVAL_TRUE(&tmp); if (strict) { @@ -4232,32 +4273,38 @@ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_ { znode var_node; zend_op *opline; + zend_string *var_name; - zend_compile_expr(&var_node, var_ast); + if (var_ast->kind == ZEND_AST_ZVAL) { + var_name = zval_make_interned_string(zend_ast_get_zval(var_ast)); + zend_compile_expr(&var_node, var_ast); + } else { + zend_compile_expr(&var_node, var_ast); + var_name = zval_make_interned_string(&var_node.u.constant); + } 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; } - ALLOC_HASHTABLE(CG(active_op_array)->static_variables); - zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0); + CG(active_op_array)->static_variables = zend_new_array(8); } if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) { if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_REFCOUNT(CG(active_op_array)->static_variables)--; + GC_DELREF(CG(active_op_array)->static_variables); } CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables); } - zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value); + zend_hash_update(CG(active_op_array)->static_variables, var_name, value); - if (zend_string_equals_literal(Z_STR(var_node.u.constant), "this")) { + if (zend_string_equals_literal(var_name, "this")) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable"); } opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &var_node); opline->op1_type = IS_CV; - opline->op1.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR(var_node.u.constant))); + opline->op1.var = lookup_cv(CG(active_op_array), var_name); opline->extended_value = by_ref; } /* }}} */ @@ -4298,15 +4345,15 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */ } return; case ZEND_AST_DIM: - opline = zend_compile_dim_common(NULL, var_ast, BP_VAR_UNSET); + opline = zend_compile_dim(NULL, var_ast, BP_VAR_UNSET); opline->opcode = ZEND_UNSET_DIM; return; case ZEND_AST_PROP: - opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_UNSET); + opline = zend_compile_prop(NULL, var_ast, BP_VAR_UNSET); opline->opcode = ZEND_UNSET_OBJ; return; case ZEND_AST_STATIC_PROP: - opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET, 0); + opline = zend_compile_static_prop(NULL, var_ast, BP_VAR_UNSET, 0); opline->opcode = ZEND_UNSET_STATIC_PROP; return; EMPTY_SWITCH_DEFAULT_CASE() @@ -4755,6 +4802,10 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */ value_ast = value_ast->child[0]; } + if (value_ast->kind == ZEND_AST_ARRAY && zend_propagate_list_refs(value_ast)) { + by_ref = 1; + } + if (by_ref && is_variable) { zend_compile_var(&expr_node, expr_ast, BP_VAR_W); } else { @@ -4776,13 +4827,15 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */ if (is_this_fetch(value_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); } else if (value_ast->kind == ZEND_AST_VAR && - zend_try_compile_cv(&value_node, value_ast) == SUCCESS) { + zend_try_compile_cv(&value_node, value_ast) == SUCCESS) { SET_NODE(opline->op2, &value_node); } else { opline->op2_type = IS_VAR; opline->op2.var = get_temporary_variable(CG(active_op_array)); GET_NODE(&value_node, opline->op2); - if (by_ref) { + if (value_ast->kind == ZEND_AST_ARRAY) { + zend_compile_list_assign(NULL, value_ast, &value_node, value_ast->attr); + } else if (by_ref) { zend_emit_assign_ref_znode(value_ast, &value_node); } else { zend_emit_assign_znode(value_ast, &value_node); @@ -4968,8 +5021,10 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */ } else if (expr_node.op_type == IS_CONST && Z_TYPE(expr_node.u.constant) == IS_TRUE) { jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0); - } else { - opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node); + } else { + opline = zend_emit_op(NULL, + (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) ? ZEND_CASE : ZEND_IS_EQUAL, + &expr_node, &cond_node); SET_NODE(opline->result, &case_node); if (opline->op1_type == IS_CONST) { zval_copy_ctor(CT_CONSTANT(opline->op1)); @@ -4992,7 +5047,7 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */ if (jumptable) { zval *cond_zv = zend_ast_get_zval(cond_ast); zval jmp_target; - ZVAL_LONG(&jmp_target, get_next_op_number(CG(active_op_array))); + ZVAL_LONG(&jmp_target, get_next_op_number(CG(active_op_array))); ZEND_ASSERT(Z_TYPE_P(cond_zv) == jumptable_type); if (Z_TYPE_P(cond_zv) == IS_LONG) { @@ -5097,7 +5152,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ zend_ast_list *classes = zend_ast_get_list(catch_ast->child[0]); zend_ast *var_ast = catch_ast->child[1]; zend_ast *stmt_ast = catch_ast->child[2]; - zval *var_name = zend_ast_get_zval(var_ast); + zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_ast)); zend_bool is_last_catch = (i + 1 == catches->children); uint32_t *jmp_multicatch = safe_emalloc(sizeof(uint32_t), classes->children - 1, 0); @@ -5125,12 +5180,12 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), zend_resolve_class_name_ast(class_ast)); - if (zend_string_equals_literal(Z_STR_P(var_name), "this")) { + if (zend_string_equals_literal(var_name, "this")) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); } opline->op2_type = IS_CV; - opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR_P(var_name))); + opline->op2.var = lookup_cv(CG(active_op_array), var_name); opline->result.num = is_last_catch && is_last_class; @@ -5166,7 +5221,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ if (finally_ast) { zend_loop_var discard_exception; uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1; - + /* Pop FAST_CALL from unwind stack */ zend_stack_del_top(&CG(loop_var_stack)); @@ -5417,7 +5472,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ uint32_t i; zend_op_array *op_array = CG(active_op_array); zend_arg_info *arg_infos; - + if (return_type_ast) { zend_bool allow_null = 0; @@ -5453,7 +5508,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ zend_ast *type_ast = param_ast->child[0]; zend_ast *var_ast = param_ast->child[1]; zend_ast *default_ast = param_ast->child[2]; - zend_string *name = zend_ast_get_str(var_ast); + zend_string *name = zval_make_interned_string(zend_ast_get_zval(var_ast)); zend_bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0; zend_bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0; @@ -5468,7 +5523,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } var_node.op_type = IS_CV; - var_node.u.op.var = lookup_cv(CG(active_op_array), zend_string_copy(name)); + var_node.u.op.var = lookup_cv(CG(active_op_array), name); if (EX_VAR_TO_NUM(var_node.u.op.var) != i) { zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s", @@ -5519,8 +5574,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ zend_bool allow_null; zend_bool has_null_default = default_ast && (Z_TYPE(default_node.u.constant) == IS_NULL - || (Z_TYPE(default_node.u.constant) == IS_CONSTANT - && strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0)); + || (Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST + && Z_ASTVAL(default_node.u.constant)->kind == ZEND_AST_CONSTANT + && strcasecmp(ZSTR_VAL(zend_ast_get_constant_name(Z_ASTVAL(default_node.u.constant))), "NULL") == 0)); zend_bool is_explicitly_nullable = (type_ast->attr & ZEND_TYPE_NULLABLE) == ZEND_TYPE_NULLABLE; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; @@ -5537,19 +5593,19 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_ARRAY - && !Z_CONSTANT(default_node.u.constant) + && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST ) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with array type can only be an array or NULL"); } } else if (ZEND_TYPE_CODE(arg_info->type) == IS_CALLABLE && default_ast) { - if (!has_null_default && !Z_CONSTANT(default_node.u.constant)) { + if (!has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type can only be NULL"); } } } else { - if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) { + if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_CONSTANT_AST) { if (ZEND_TYPE_IS_CLASS(arg_info->type)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a class type can only be NULL"); @@ -5560,7 +5616,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ "with a float type can only be float, integer, or NULL"); } break; - + case IS_ITERABLE: if (Z_TYPE(default_node.u.constant) != IS_ARRAY) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " @@ -5572,7 +5628,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with an object type can only be NULL"); break; - + default: if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(arg_info->type), Z_TYPE(default_node.u.constant))) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " @@ -5605,7 +5661,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ } else { opline->op2.num = -1; } - } + } } /* These are assigned at the end to avoid unitialized memory in case of an error */ @@ -5627,7 +5683,7 @@ static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /* for (i = 0; i < list->children; ++i) { zend_ast *var_name_ast = list->child[i]; - zend_string *var_name = zend_ast_get_str(var_name_ast); + zend_string *var_name = zval_make_interned_string(zend_ast_get_zval(var_name_ast)); zend_bool by_ref = var_name_ast->attr; zend_op *opline; @@ -5641,7 +5697,7 @@ static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /* opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL); opline->op2_type = IS_CV; - opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(var_name)); + opline->op2.var = lookup_cv(CG(active_op_array), var_name); opline->extended_value = by_ref; } } @@ -6005,7 +6061,7 @@ void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ zend_ast *name_ast = prop_ast->child[0]; zend_ast *value_ast = prop_ast->child[1]; zend_ast *doc_comment_ast = prop_ast->child[2]; - zend_string *name = zend_ast_get_str(name_ast); + zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast)); zend_string *doc_comment = NULL; zval value_zv; @@ -6031,7 +6087,6 @@ void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ ZVAL_NULL(&value_zv); } - name = zend_new_interned_string_safe(name); zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment); } } @@ -6053,7 +6108,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zend_ast *name_ast = const_ast->child[0]; zend_ast *value_ast = const_ast->child[1]; zend_ast *doc_comment_ast = const_ast->child[2]; - zend_string *name = zend_ast_get_str(name_ast); + zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast)); zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL; zval value_zv; @@ -6068,8 +6123,6 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ } zend_const_expr_to_zval(&value_zv, value_ast); - - name = zend_new_interned_string_safe(name); zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment); } } @@ -6937,6 +6990,11 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ return 0; } + if (!list->children) { + ZVAL_EMPTY_ARRAY(result); + return 1; + } + array_init_size(result, list->children); for (i = 0; i < list->children; ++i) { zend_ast *elem_ast = list->child[i]; @@ -6944,7 +7002,7 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_ast *key_ast = elem_ast->child[1]; zval *value = zend_ast_get_zval(value_ast); - if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); + Z_TRY_ADDREF_P(value); if (key_ast) { zval *key = zend_ast_get_zval(key_ast); @@ -7038,6 +7096,9 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */ if (right_node.op_type == IS_CONST) { convert_to_string(&right_node.u.constant); } + if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) { + opcode = ZEND_FAST_CONCAT; + } } zend_emit_op_tmp(result, opcode, &left_node, &right_node); } while (0); @@ -7180,7 +7241,7 @@ 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_common(NULL, var_ast, BP_VAR_RW); + zend_op *opline = zend_compile_prop(NULL, var_ast, BP_VAR_RW); opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ; zend_make_tmp_result(result, opline); } else { @@ -7200,7 +7261,7 @@ 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_common(result, var_ast, BP_VAR_RW); + zend_op *opline = zend_compile_prop(result, var_ast, BP_VAR_RW); opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ; } else { znode var_node; @@ -7407,8 +7468,10 @@ void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&obj_node, obj_ast); if (obj_node.op_type == IS_CONST) { - zend_error_noreturn(E_COMPILE_ERROR, - "instanceof expects an object instance, constant given"); + zend_do_free(&obj_node); + result->op_type = IS_CONST; + ZVAL_FALSE(&result->u.constant); + return; } zend_compile_class_ref_ex(&class_node, class_ast, @@ -7476,15 +7539,15 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */ } break; case ZEND_AST_DIM: - opline = zend_compile_dim_common(result, var_ast, BP_VAR_IS); + opline = zend_compile_dim(result, var_ast, BP_VAR_IS); opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ; break; case ZEND_AST_PROP: - opline = zend_compile_prop_common(result, var_ast, BP_VAR_IS); + opline = zend_compile_prop(result, var_ast, BP_VAR_IS); opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ; break; case ZEND_AST_STATIC_PROP: - opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS, 0); + opline = zend_compile_static_prop(result, var_ast, BP_VAR_IS, 0); opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP; break; EMPTY_SWITCH_DEFAULT_CASE() @@ -7856,7 +7919,7 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */ i = ((j * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval); while (i > 1) { get_temporary_variable(CG(active_op_array)); - i--; + i--; } zend_end_live_range(CG(active_op_array), range, opline - CG(active_op_array)->opcodes, @@ -7917,6 +7980,7 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */ zend_ast *const_ast = ast->child[1]; zend_string *class_name; zend_string *const_name = zend_ast_get_str(const_ast); + zend_string *name; zval result; int fetch_type; @@ -7944,16 +8008,13 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */ zend_string_addref(class_name); } - Z_STR(result) = zend_concat3( + name = zend_concat3( ZSTR_VAL(class_name), ZSTR_LEN(class_name), "::", 2, ZSTR_VAL(const_name), ZSTR_LEN(const_name)); - Z_TYPE_INFO(result) = IS_CONSTANT_EX; - Z_CONST_FLAGS(result) = fetch_type; - zend_ast_destroy(ast); zend_string_release(class_name); - *ast_ptr = zend_ast_create_zval(&result); + *ast_ptr = zend_ast_create_constant(name, fetch_type); } /* }}} */ @@ -7963,25 +8024,21 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */ zend_ast *name_ast = ast->child[0]; zend_string *orig_name = zend_ast_get_str(name_ast); zend_bool is_fully_qualified; + zval result; + zend_string *resolved_name; - zval result, resolved_name; - ZVAL_STR(&resolved_name, zend_resolve_const_name( - orig_name, name_ast->attr, &is_fully_qualified)); + resolved_name = zend_resolve_const_name( + orig_name, name_ast->attr, &is_fully_qualified); - if (zend_try_ct_eval_const(&result, Z_STR(resolved_name), is_fully_qualified)) { - zend_string_release(Z_STR(resolved_name)); + if (zend_try_ct_eval_const(&result, resolved_name, is_fully_qualified)) { + zend_string_release(resolved_name); zend_ast_destroy(ast); *ast_ptr = zend_ast_create_zval(&result); return; } - Z_TYPE_INFO(resolved_name) = IS_CONSTANT_EX; - if (!is_fully_qualified) { - Z_CONST_FLAGS(resolved_name) = IS_CONSTANT_UNQUALIFIED; - } - zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_zval(&resolved_name); + *ast_ptr = zend_ast_create_constant(resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0); } /* }}} */ @@ -7994,14 +8051,8 @@ void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */ CG(active_class_entry) && (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0); - { - zval const_zv; - Z_STR(const_zv) = zend_string_init("__CLASS__", sizeof("__CLASS__")-1, 0); - Z_TYPE_INFO(const_zv) = IS_CONSTANT_EX | (IS_CONSTANT_CLASS << Z_CONST_FLAGS_SHIFT); - - zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_zval(&const_zv); - } + zend_ast_destroy(ast); + *ast_ptr = zend_ast_create_ex(ZEND_AST_CONSTANT_CLASS, 0); } /* }}} */ @@ -8041,7 +8092,7 @@ void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */ if (ast->kind == ZEND_AST_ZVAL) { ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast)); } else { - ZVAL_NEW_AST(result, zend_ast_copy(ast)); + ZVAL_AST(result, zend_ast_copy(ast)); /* destroy the ast here, it might have been replaced */ zend_ast_destroy(ast); } @@ -8361,18 +8412,15 @@ void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { - zend_op *opline; switch (ast->kind) { case ZEND_AST_VAR: zend_compile_simple_var(result, ast, type, 1); return; case ZEND_AST_DIM: - opline = zend_delayed_compile_dim(result, ast, type); - zend_adjust_for_fetch_type(opline, type); + zend_delayed_compile_dim(result, ast, type); return; case ZEND_AST_PROP: - opline = zend_delayed_compile_prop(result, ast, type); - zend_adjust_for_fetch_type(opline, type); + zend_delayed_compile_prop(result, ast, type); return; case ZEND_AST_STATIC_PROP: zend_compile_static_prop(result, ast, type, 1); |
