summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c639
1 files changed, 391 insertions, 248 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 19a1c543ab..deff0dbe57 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -87,7 +87,7 @@ ZEND_API zend_executor_globals executor_globals;
#endif
static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2);
-static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast);
+static bool zend_try_ct_eval_array(zval *result, zend_ast *ast);
static void init_op(zend_op *op)
{
@@ -145,7 +145,7 @@ static zend_string *zend_build_runtime_definition_key(zend_string *name, uint32_
}
/* }}} */
-static zend_bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
+static bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
{
const char *ns_separator = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
if (ns_separator != NULL) {
@@ -180,7 +180,7 @@ static const struct reserved_class_name reserved_class_names[] = {
{NULL, 0}
};
-static zend_bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
+static bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
{
const struct reserved_class_name *reserved = reserved_class_names;
@@ -259,7 +259,7 @@ static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend
}
/* }}} */
-static zend_always_inline zend_bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */
+static zend_always_inline bool zend_is_confusable_type(const zend_string *name, const char **correct_name) /* {{{ */
{
const confusable_type_info *info = confusable_types;
@@ -278,7 +278,7 @@ static zend_always_inline zend_bool zend_is_confusable_type(const zend_string *n
}
/* }}} */
-static zend_bool zend_is_not_imported(zend_string *name) {
+static bool zend_is_not_imported(zend_string *name) {
/* Assuming "name" is unqualified here. */
return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL;
}
@@ -393,7 +393,7 @@ static void zend_register_seen_symbol(zend_string *name, uint32_t kind) {
}
}
-static zend_bool zend_have_seen_symbol(zend_string *name, uint32_t kind) {
+static bool zend_have_seen_symbol(zend_string *name, uint32_t kind) {
zval *zv = zend_hash_find(&FC(seen_symbols), name);
return zv && (Z_LVAL_P(zv) & kind) != 0;
}
@@ -417,6 +417,8 @@ void init_compiler(void) /* {{{ */
CG(delayed_variance_obligations) = NULL;
CG(delayed_autoloads) = NULL;
+ CG(unlinked_uses) = NULL;
+ CG(current_linking_class) = NULL;
}
/* }}} */
@@ -428,7 +430,6 @@ void shutdown_compiler(void) /* {{{ */
zend_stack_destroy(&CG(loop_var_stack));
zend_stack_destroy(&CG(delayed_oplines_stack));
zend_stack_destroy(&CG(short_circuiting_opnums));
- zend_arena_destroy(CG(arena));
if (CG(delayed_variance_obligations)) {
zend_hash_destroy(CG(delayed_variance_obligations));
@@ -440,6 +441,12 @@ void shutdown_compiler(void) /* {{{ */
FREE_HASHTABLE(CG(delayed_autoloads));
CG(delayed_autoloads) = NULL;
}
+ if (CG(unlinked_uses)) {
+ zend_hash_destroy(CG(unlinked_uses));
+ FREE_HASHTABLE(CG(unlinked_uses));
+ CG(unlinked_uses) = NULL;
+ }
+ CG(current_linking_class) = NULL;
}
/* }}} */
@@ -472,7 +479,7 @@ ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
}
/* }}} */
-ZEND_API zend_bool zend_is_compiling(void) /* {{{ */
+ZEND_API bool zend_is_compiling(void) /* {{{ */
{
return CG(in_compilation);
}
@@ -609,7 +616,7 @@ static int zend_add_class_name_literal(zend_string *name) /* {{{ */
}
/* }}} */
-static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) /* {{{ */
+static int zend_add_const_name_literal(zend_string *name, bool unqualified) /* {{{ */
{
zend_string *tmp_name;
@@ -658,7 +665,7 @@ void zend_stop_lexing(void)
}
static inline void zend_begin_loop(
- zend_uchar free_opcode, const znode *loop_var, zend_bool is_switch) /* {{{ */
+ zend_uchar free_opcode, const znode *loop_var, bool is_switch) /* {{{ */
{
zend_brk_cont_element *brk_cont_element;
int parent = CG(context).current_brk_cont;
@@ -860,8 +867,8 @@ zend_string *zend_prefix_with_ns(zend_string *name) {
}
zend_string *zend_resolve_non_class_name(
- zend_string *name, uint32_t type, zend_bool *is_fully_qualified,
- zend_bool case_sensitive, HashTable *current_import_sub
+ zend_string *name, uint32_t type, bool *is_fully_qualified,
+ bool case_sensitive, HashTable *current_import_sub
) {
char *compound;
*is_fully_qualified = 0;
@@ -917,14 +924,14 @@ zend_string *zend_resolve_non_class_name(
}
/* }}} */
-zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */
+zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, bool *is_fully_qualified) /* {{{ */
{
return zend_resolve_non_class_name(
name, type, is_fully_qualified, 0, FC(imports_function));
}
/* }}} */
-zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */ {
+zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, bool *is_fully_qualified) /* {{{ */ {
return zend_resolve_non_class_name(
name, type, is_fully_qualified, 1, FC(imports_const));
}
@@ -934,22 +941,35 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
{
char *compound;
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ if (type == ZEND_NAME_FQ) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "'\\%s' is an invalid class name", ZSTR_VAL(name));
+ }
+ if (type == ZEND_NAME_RELATIVE) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "'namespace\\%s' is an invalid class name", ZSTR_VAL(name));
+ }
+ ZEND_ASSERT(type == ZEND_NAME_NOT_FQ);
+ return zend_string_copy(name);
+ }
+
if (type == ZEND_NAME_RELATIVE) {
return zend_prefix_with_ns(name);
}
- if (type == ZEND_NAME_FQ || ZSTR_VAL(name)[0] == '\\') {
- /* Remove \ prefix (only relevant if this is a string rather than a label) */
+ if (type == ZEND_NAME_FQ) {
if (ZSTR_VAL(name)[0] == '\\') {
+ /* Remove \ prefix (only relevant if this is a string rather than a label) */
name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
- } else {
- zend_string_addref(name);
- }
- /* Ensure that \self, \parent and \static are not used */
- if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
- zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", ZSTR_VAL(name));
+ if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "'\\%s' is an invalid class name", ZSTR_VAL(name));
+ }
+ return name;
}
- return name;
+
+ return zend_string_copy(name);
}
if (FC(imports)) {
@@ -1001,7 +1021,7 @@ static void str_dtor(zval *zv) /* {{{ */ {
}
/* }}} */
-static zend_bool zend_is_call(zend_ast *ast);
+static bool zend_is_call(zend_ast *ast);
static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
{
@@ -1022,28 +1042,27 @@ static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
}
/* }}} */
+void zend_init_static_variables_map_ptr(zend_op_array *op_array)
+{
+ if (op_array->static_variables) {
+ ZEND_MAP_PTR_INIT(op_array->static_variables_ptr,
+ zend_arena_alloc(&CG(arena), sizeof(HashTable *)));
+ ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
+ }
+}
+
ZEND_API void function_add_ref(zend_function *function) /* {{{ */
{
if (function->type == ZEND_USER_FUNCTION) {
zend_op_array *op_array = &function->op_array;
-
if (op_array->refcount) {
(*op_array->refcount)++;
}
- if (op_array->static_variables
- && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
- GC_ADDREF(op_array->static_variables);
- }
- if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
- ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_PRELOADED);
- ZEND_MAP_PTR_NEW(op_array->run_time_cache);
- ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
- } else {
- ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
- ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
- ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
- }
+ ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void *)));
+ ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
+
+ zend_init_static_variables_map_ptr(op_array);
}
if (function->common.function_name) {
@@ -1052,7 +1071,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
}
/* }}} */
-static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, zend_bool compile_time) /* {{{ */
+static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zend_string *lcname, zend_op_array *op_array, bool compile_time) /* {{{ */
{
zval *zv = zend_hash_find_ex(compile_time ? CG(function_table) : EG(function_table), lcname, 1);
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
@@ -1072,27 +1091,19 @@ static zend_never_inline ZEND_COLD ZEND_NORETURN void do_bind_function_error(zen
}
}
-ZEND_API zend_result do_bind_function(zval *lcname) /* {{{ */
+ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ */
{
- zend_function *function;
- zval *rtd_key, *zv;
-
- rtd_key = lcname + 1;
- zv = zend_hash_find_ex(EG(function_table), Z_STR_P(rtd_key), 1);
- if (UNEXPECTED(!zv)) {
- do_bind_function_error(Z_STR_P(lcname), NULL, 0);
+ zend_function *added_func = zend_hash_add_ptr(EG(function_table), Z_STR_P(lcname), func);
+ if (UNEXPECTED(!added_func)) {
+ do_bind_function_error(Z_STR_P(lcname), &func->op_array, 0);
return FAILURE;
}
- function = (zend_function*)Z_PTR_P(zv);
- if (UNEXPECTED(function->common.fn_flags & ZEND_ACC_PRELOADED)
- && !(CG(compiler_options) & ZEND_COMPILE_PRELOAD)) {
- zv = zend_hash_add(EG(function_table), Z_STR_P(lcname), zv);
- } else {
- zv = zend_hash_set_bucket_key(EG(function_table), (Bucket*)zv, Z_STR_P(lcname));
+
+ if (func->op_array.refcount) {
+ ++*func->op_array.refcount;
}
- if (UNEXPECTED(!zv)) {
- do_bind_function_error(Z_STR_P(lcname), &function->op_array, 0);
- return FAILURE;
+ if (func->common.function_name) {
+ zend_string_addref(func->common.function_name);
}
return SUCCESS;
}
@@ -1136,7 +1147,12 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /*
return FAILURE;
}
- if (zend_do_link_class(ce, lc_parent_name) == FAILURE) {
+ if (ce->ce_flags & ZEND_ACC_LINKED) {
+ return SUCCESS;
+ }
+
+ ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname));
+ if (!ce) {
/* Reload bucket pointer, the hash table may have been reallocated */
zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key));
@@ -1187,13 +1203,34 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
if (ZEND_TYPE_HAS_CE(*list_type)) {
str = add_type_string(str, ZEND_TYPE_CE(*list_type)->name);
} else {
- zend_string *resolved = resolve_class_name(ZEND_TYPE_NAME(*list_type), scope);
- str = add_type_string(str, resolved);
- zend_string_release(resolved);
+ if (ZEND_TYPE_HAS_CE_CACHE(*list_type)
+ && ZEND_TYPE_CE_CACHE(*list_type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE_CACHE(*list_type);
+ if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
+ zend_string *tmp = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
+ str = add_type_string(str, tmp);
+ } else {
+ str = add_type_string(str, ce->name);
+ }
+ } else {
+ zend_string *resolved = resolve_class_name(ZEND_TYPE_NAME(*list_type), scope);
+ str = add_type_string(str, resolved);
+ zend_string_release(resolved);
+ }
}
} ZEND_TYPE_LIST_FOREACH_END();
} else if (ZEND_TYPE_HAS_NAME(type)) {
- str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
+ if (ZEND_TYPE_HAS_CE_CACHE(type)
+ && ZEND_TYPE_CE_CACHE(type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE_CACHE(type);
+ if (ce->ce_flags & ZEND_ACC_ANON_CLASS) {
+ str = zend_string_init(ZSTR_VAL(ce->name), strlen(ZSTR_VAL(ce->name)), 0);
+ } else {
+ str = zend_string_copy(ce->name);
+ }
+ } else {
+ str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
+ }
} else if (ZEND_TYPE_HAS_CE(type)) {
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
}
@@ -1246,7 +1283,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
}
if (type_mask & MAY_BE_NULL) {
- zend_bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
+ bool is_union = !str || memchr(ZSTR_VAL(str), '|', ZSTR_LEN(str)) != NULL;
if (!is_union) {
zend_string *nullable_str = zend_string_concat2("?", 1, ZSTR_VAL(str), ZSTR_LEN(str));
zend_string_release(str);
@@ -1262,7 +1299,7 @@ ZEND_API zend_string *zend_type_to_string(zend_type type) {
return zend_type_to_string_resolved(type, NULL);
}
-static zend_bool is_generator_compatible_class_type(zend_string *name) {
+static bool is_generator_compatible_class_type(zend_string *name) {
return zend_string_equals_literal_ci(name, "Traversable")
|| zend_string_equals_literal_ci(name, "Iterator")
|| zend_string_equals_literal_ci(name, "Generator");
@@ -1277,7 +1314,7 @@ static void zend_mark_function_as_generator() /* {{{ */
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
zend_type return_type = CG(active_op_array)->arg_info[-1].type;
- zend_bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & (MAY_BE_ITERABLE | MAY_BE_OBJECT)) != 0;
+ bool valid_type = (ZEND_TYPE_FULL_MASK(return_type) & (MAY_BE_ITERABLE | MAY_BE_OBJECT)) != 0;
if (!valid_type) {
zend_type *single_type;
ZEND_TYPE_FOREACH(return_type, single_type) {
@@ -1326,7 +1363,7 @@ ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_
ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array, uint32_t first_early_binding_opline) /* {{{ */
{
if (first_early_binding_opline != (uint32_t)-1) {
- zend_bool orig_in_compilation = CG(in_compilation);
+ bool orig_in_compilation = CG(in_compilation);
uint32_t opline_num = first_early_binding_opline;
void **run_time_cache;
@@ -1354,7 +1391,8 @@ ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array, uint32_t fi
zend_class_entry *parent_ce = zend_hash_find_ex_ptr(EG(class_table), lc_parent_name, 1);
if (parent_ce) {
- if (zend_try_early_bind(ce, parent_ce, Z_STR_P(lcname), zv)) {
+ ce = zend_try_early_bind(ce, parent_ce, Z_STR_P(lcname), zv);
+ if (ce) {
/* Store in run-time cache */
((void**)((char*)run_time_cache + opline->extended_value))[0] = ce;
}
@@ -1433,7 +1471,7 @@ ZEND_API zend_result zend_unmangle_property_name_ex(const zend_string *name, con
}
/* }}} */
-static zend_bool can_ct_eval_const(zend_constant *c) {
+static bool can_ct_eval_const(zend_constant *c) {
if (ZEND_CONSTANT_FLAGS(c) & CONST_DEPRECATED) {
return 0;
}
@@ -1450,7 +1488,7 @@ static zend_bool can_ct_eval_const(zend_constant *c) {
return 0;
}
-static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */
+static bool zend_try_ct_eval_const(zval *zv, zend_string *name, bool is_fully_qualified) /* {{{ */
{
zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name);
if (c && can_ct_eval_const(c)) {
@@ -1477,8 +1515,13 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i
}
/* }}} */
-static inline zend_bool zend_is_scope_known() /* {{{ */
+static inline bool zend_is_scope_known() /* {{{ */
{
+ if (!CG(active_op_array)) {
+ /* This can only happen when evaluating a default value string. */
+ return 0;
+ }
+
if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
/* Closures can be rebound to a different scope */
return 0;
@@ -1495,7 +1538,7 @@ static inline zend_bool zend_is_scope_known() /* {{{ */
}
/* }}} */
-static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
+static inline bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
{
if (!CG(active_class_entry)) {
return 0;
@@ -1560,7 +1603,7 @@ static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
}
/* }}} */
-static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
+static bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast) /* {{{ */
{
uint32_t fetch_type;
zval *class_name;
@@ -1603,7 +1646,7 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a
/* }}} */
/* We don't use zend_verify_const_access because we need to deal with unlinked classes. */
-static zend_bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope)
+static bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_entry *scope)
{
if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
return 1;
@@ -1632,7 +1675,7 @@ static zend_bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_
}
}
-static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
+static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
{
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
zend_class_constant *cc;
@@ -1733,7 +1776,7 @@ void zend_do_extended_fcall_end(void) /* {{{ */
}
/* }}} */
-zend_bool zend_is_auto_global_str(const char *name, size_t len) /* {{{ */ {
+bool zend_is_auto_global_str(const char *name, size_t len) /* {{{ */ {
zend_auto_global *auto_global;
if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
@@ -1746,7 +1789,7 @@ zend_bool zend_is_auto_global_str(const char *name, size_t len) /* {{{ */ {
}
/* }}} */
-zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
+bool zend_is_auto_global(zend_string *name) /* {{{ */
{
zend_auto_global *auto_global;
@@ -1760,7 +1803,7 @@ zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
}
/* }}} */
-zend_result zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
+zend_result zend_register_auto_global(zend_string *name, bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
{
zend_auto_global auto_global;
zend_result retval;
@@ -1808,9 +1851,9 @@ int ZEND_FASTCALL zendlex(zend_parser_stack_elem *elem) /* {{{ */
}
/* }}} */
-ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) /* {{{ */
+ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_handlers) /* {{{ */
{
- zend_bool persistent_hashes = ce->type == ZEND_INTERNAL_CLASS;
+ bool persistent_hashes = ce->type == ZEND_INTERNAL_CLASS;
ce->refcount = 1;
ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
@@ -1831,6 +1874,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
ce->info.user.doc_comment = NULL;
}
+ ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
ce->default_properties_count = 0;
ce->default_static_members_count = 0;
@@ -2243,7 +2287,7 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
}
/* }}} */
-static zend_bool zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)
+static bool zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)
{
switch (ast_kind) {
case ZEND_AST_DIM:
@@ -2259,7 +2303,7 @@ static zend_bool zend_ast_kind_is_short_circuited(zend_ast_kind ast_kind)
}
}
-static zend_bool zend_ast_is_short_circuited(const zend_ast *ast)
+static bool zend_ast_is_short_circuited(const zend_ast *ast)
{
switch (ast->kind) {
case ZEND_AST_DIM:
@@ -2295,7 +2339,7 @@ static uint32_t zend_short_circuiting_checkpoint()
static void zend_short_circuiting_commit(uint32_t checkpoint, znode *result, zend_ast *ast)
{
- zend_bool is_short_circuited = zend_ast_kind_is_short_circuited(ast->kind)
+ bool is_short_circuited = zend_ast_kind_is_short_circuited(ast->kind)
|| ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY;
if (!is_short_circuited) {
ZEND_ASSERT(zend_stack_count(&CG(short_circuiting_opnums)) == checkpoint
@@ -2382,7 +2426,7 @@ static size_t zend_type_get_num_classes(zend_type type) {
}
static void zend_emit_return_type_check(
- znode *expr, zend_arg_info *return_info, zend_bool implicit) /* {{{ */
+ znode *expr, zend_arg_info *return_info, bool implicit) /* {{{ */
{
zend_type type = return_info->type;
if (ZEND_TYPE_IS_SET(type)) {
@@ -2439,7 +2483,7 @@ void zend_emit_final_return(bool return_one) /* {{{ */
{
znode zn;
zend_op *ret;
- zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+ bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
if ((CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)
&& !(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR)) {
@@ -2458,7 +2502,7 @@ void zend_emit_final_return(bool return_one) /* {{{ */
}
/* }}} */
-static inline zend_bool zend_is_variable(zend_ast *ast) /* {{{ */
+static inline bool zend_is_variable(zend_ast *ast) /* {{{ */
{
return ast->kind == ZEND_AST_VAR
|| ast->kind == ZEND_AST_DIM
@@ -2468,7 +2512,7 @@ static inline zend_bool zend_is_variable(zend_ast *ast) /* {{{ */
}
/* }}} */
-static inline zend_bool zend_is_call(zend_ast *ast) /* {{{ */
+static inline bool zend_is_call(zend_ast *ast) /* {{{ */
{
return ast->kind == ZEND_AST_CALL
|| ast->kind == ZEND_AST_METHOD_CALL
@@ -2477,13 +2521,13 @@ static inline zend_bool zend_is_call(zend_ast *ast) /* {{{ */
}
/* }}} */
-static inline zend_bool zend_is_variable_or_call(zend_ast *ast) /* {{{ */
+static inline bool zend_is_variable_or_call(zend_ast *ast) /* {{{ */
{
return zend_is_variable(ast) || zend_is_call(ast);
}
/* }}} */
-static inline zend_bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
+static inline bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
{
return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL
|| ast->kind == ZEND_AST_PROP_DECL || ast->kind == ZEND_AST_CLASS_CONST_GROUP
@@ -2491,7 +2535,7 @@ static inline zend_bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
}
/* }}} */
-static inline zend_bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
+static inline bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
{
while (
ast->kind == ZEND_AST_DIM
@@ -2504,7 +2548,7 @@ static inline zend_bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
}
/* }}} */
-static inline zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
+static inline bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
{
if (name_ast->kind != ZEND_AST_ZVAL) {
return 0;
@@ -2674,7 +2718,7 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
}
/* }}} */
-static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
+static bool is_this_fetch(zend_ast *ast) /* {{{ */
{
if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
zval *name = zend_ast_get_zval(ast->child[0]);
@@ -2685,7 +2729,22 @@ static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
}
/* }}} */
-static zend_bool this_guaranteed_exists() /* {{{ */
+static bool is_globals_fetch(const zend_ast *ast)
+{
+ if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
+ zval *name = zend_ast_get_zval(ast->child[0]);
+ return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "GLOBALS");
+ }
+
+ return 0;
+}
+
+static bool is_global_var_fetch(zend_ast *ast)
+{
+ return ast->kind == ZEND_AST_DIM && is_globals_fetch(ast->child[0]);
+}
+
+static bool this_guaranteed_exists() /* {{{ */
{
zend_op_array *op_array = CG(active_op_array);
/* Instance methods always have a $this.
@@ -2705,6 +2764,13 @@ static zend_op *zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t t
}
CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS;
return opline;
+ } else if (is_globals_fetch(ast)) {
+ zend_op *opline = zend_emit_op(result, ZEND_FETCH_GLOBALS, NULL, NULL);
+ if (type == BP_VAR_R || type == BP_VAR_IS) {
+ opline->result_type = IS_TMP_VAR;
+ result->op_type = IS_TMP_VAR;
+ }
+ return opline;
} else if (zend_try_compile_cv(result, ast) == FAILURE) {
return zend_compile_simple_var_no_cv(result, ast, type, delayed);
}
@@ -2726,7 +2792,7 @@ static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t
}
/* }}} */
-zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, zend_bool by_ref);
+zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, 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) /* {{{ */
@@ -2750,10 +2816,26 @@ static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t
znode var_node, dim_node;
- zend_short_circuiting_mark_inner(var_ast);
- 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;
+ if (is_globals_fetch(var_ast)) {
+ if (dim_ast == NULL) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot append to $GLOBALS");
+ }
+
+ zend_compile_expr(&dim_node, dim_ast);
+ if (dim_node.op_type == IS_CONST) {
+ convert_to_string(&dim_node.u.constant);
+ }
+
+ opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &dim_node, NULL);
+ opline->extended_value = ZEND_FETCH_GLOBAL;
+ zend_adjust_for_fetch_type(opline, result, type);
+ return opline;
+ } else {
+ zend_short_circuiting_mark_inner(var_ast);
+ 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);
@@ -2795,7 +2877,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
znode obj_node, prop_node;
zend_op *opline;
- zend_bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_PROP;
+ bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_PROP;
if (is_this_fetch(obj_ast)) {
if (this_guaranteed_exists()) {
@@ -2812,7 +2894,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0);
zend_separate_if_call_and_write(&obj_node, obj_ast, type);
if (nullsafe) {
- /* We will push to the short_cirtcuiting_opnums stack in zend_delayed_compile_end(). */
+ /* We will push to the short_circuiting_opnums stack in zend_delayed_compile_end(). */
opline = zend_delayed_emit_op(NULL, ZEND_JMP_NULL, &obj_node, NULL);
if (opline->op1_type == IS_CONST) {
Z_TRY_ADDREF_P(CT_CONSTANT(opline->op1));
@@ -2904,9 +2986,9 @@ static void zend_verify_list_assign_target(zend_ast *var_ast, zend_ast_attr arra
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) { /* {{{ */
+static bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */
zend_ast_list *list = zend_ast_get_list(ast);
- zend_bool has_refs = 0;
+ bool has_refs = 0;
uint32_t i;
for (i = 0; i < list->children; ++i) {
@@ -2925,14 +3007,23 @@ static zend_bool zend_propagate_list_refs(zend_ast *ast) { /* {{{ */
}
/* }}} */
+static bool list_is_keyed(zend_ast_list *list)
+{
+ for (uint32_t i = 0; i < list->children; i++) {
+ if (list->child[i]) {
+ return list->child[i]->child[1] != NULL;
+ }
+ }
+ return false;
+}
+
static void zend_compile_list_assign(
znode *result, zend_ast *ast, znode *expr_node, zend_ast_attr array_style) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(ast);
uint32_t i;
- zend_bool has_elems = 0;
- zend_bool is_keyed =
- list->children > 0 && list->child[0] != NULL && list->child[0]->child[1] != NULL;
+ bool has_elems = 0;
+ bool is_keyed = list_is_keyed(list);
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);
@@ -3031,11 +3122,15 @@ static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
if (zend_ast_is_short_circuited(ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Can't use nullsafe operator in write context");
}
+ if (is_globals_fetch(ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax");
+ }
}
/* }}} */
/* Detects $a... = $a pattern */
-zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
+bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
{
if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
return 0;
@@ -3052,7 +3147,7 @@ zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ *
{
zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
- zend_bool result = zend_string_equals(name1, name2);
+ bool result = zend_string_equals(name1, name2);
zend_string_release_ex(name1, 0);
zend_string_release_ex(name2, 0);
return result;
@@ -3074,7 +3169,9 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
zend_ensure_writable_variable(var_ast);
- switch (var_ast->kind) {
+ /* Treat $GLOBALS['x'] assignment like assignment to variable. */
+ zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
+ switch (kind) {
case ZEND_AST_VAR:
offset = zend_delayed_compile_begin();
zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W, 0);
@@ -3182,6 +3279,9 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
if (zend_ast_is_short_circuited(source_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot take reference of a nullsafe chain");
}
+ if (is_globals_fetch(source_ast)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot acquire reference to $GLOBALS");
+ }
offset = zend_delayed_compile_begin();
zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W, 1);
@@ -3251,7 +3351,9 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
zend_ensure_writable_variable(var_ast);
- switch (var_ast->kind) {
+ /* Treat $GLOBALS['x'] assignment like assignment to variable. */
+ zend_ast_kind kind = is_global_var_fetch(var_ast) ? ZEND_AST_VAR : var_ast->kind;
+ switch (kind) {
case ZEND_AST_VAR:
offset = zend_delayed_compile_begin();
zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW, 0);
@@ -3337,14 +3439,14 @@ uint32_t zend_compile_args(
{
zend_ast_list *args = zend_ast_get_list(ast);
uint32_t i;
- zend_bool uses_arg_unpack = 0;
+ bool uses_arg_unpack = 0;
uint32_t arg_count = 0; /* number of arguments not including unpacks */
/* Whether named arguments are used syntactically, to enforce language level limitations.
* May not actually use named argument passing. */
- zend_bool uses_named_args = 0;
+ bool uses_named_args = 0;
/* Whether there may be any undef arguments due to the use of named arguments. */
- zend_bool may_have_undef = 0;
+ bool may_have_undef = 0;
/* Whether there may be any extra named arguments collected into a variadic. */
*may_have_extra_named_args = 0;
@@ -3421,7 +3523,9 @@ uint32_t zend_compile_args(
arg_count++;
}
- if (zend_is_call(arg)) {
+ /* Treat passing of $GLOBALS the same as passing a call.
+ * This will error at runtime if the argument is by-ref. */
+ if (zend_is_call(arg) || is_globals_fetch(arg)) {
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 */
@@ -3586,10 +3690,10 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *
}
/* }}} */
-zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
+bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
{
zend_string *orig_name = zend_ast_get_str(name_ast);
- zend_bool is_fully_qualified;
+ bool is_fully_qualified;
name_node->op_type = IS_CONST;
ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
@@ -3646,7 +3750,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
}
/* }}} */
-static inline zend_bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */
+static inline bool zend_args_contain_unpack_or_named(zend_ast_list *args) /* {{{ */
{
uint32_t i;
for (i = 0; i < args->children; ++i) {
@@ -3802,7 +3906,7 @@ zend_result zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */
/* We can only calculate the stack size for functions that have been fully compiled, otherwise
* additional CV or TMP slots may still be added. This prevents the use of INIT_FCALL for
* directly or indirectly recursive function calls. */
-static zend_bool fbc_is_finalized(zend_function *fbc) {
+static bool fbc_is_finalized(zend_function *fbc) {
return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO);
}
@@ -3874,7 +3978,7 @@ zend_result zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_stri
&& args->child[1]->child[1]->kind == ZEND_AST_ARG_LIST) {
zend_string *orig_name = zend_ast_get_str(args->child[1]->child[0]);
zend_ast_list *list = zend_ast_get_list(args->child[1]->child[1]);
- zend_bool is_fully_qualified;
+ bool is_fully_qualified;
zend_string *name = zend_resolve_function_name(orig_name, args->child[1]->child[0]->attr, &is_fully_qualified);
if (zend_string_equals_literal_ci(name, "array_slice")
@@ -3988,7 +4092,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string
static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args) /* {{{ */
{
- zend_bool strict = 0;
+ bool strict = 0;
znode array, needly;
zend_op *opline;
@@ -3998,7 +4102,7 @@ static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args
} else if (args->child[2]->kind == ZEND_AST_CONST) {
zval value;
zend_ast *name_ast = args->child[2]->child[0];
- zend_bool is_fully_qualified;
+ bool is_fully_qualified;
zend_string *resolved_name = zend_resolve_const_name(
zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
@@ -4023,7 +4127,7 @@ static zend_result zend_compile_func_in_array(znode *result, zend_ast_list *args
}
if (zend_hash_num_elements(Z_ARRVAL(array.u.constant)) > 0) {
- zend_bool ok = 1;
+ bool ok = 1;
zval *val, tmp;
HashTable *src = Z_ARRVAL(array.u.constant);
HashTable *dst = zend_new_array(zend_hash_num_elements(src));
@@ -4180,7 +4284,7 @@ zend_result zend_compile_func_array_slice(znode *result, zend_ast_list *args) /*
&& args->child[1]->kind == ZEND_AST_ZVAL) {
zend_string *orig_name = zend_ast_get_str(args->child[0]->child[0]);
- zend_bool is_fully_qualified;
+ bool is_fully_qualified;
zend_string *name = zend_resolve_function_name(orig_name, args->child[0]->child[0]->attr, &is_fully_qualified);
zend_ast_list *list = zend_ast_get_list(args->child[0]->child[1]);
zval *zv = zend_ast_get_zval(args->child[1]);
@@ -4302,7 +4406,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
}
{
- zend_bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
+ bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
if (runtime_resolution) {
if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")) {
zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL);
@@ -4368,7 +4472,7 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
znode obj_node, method_node;
zend_op *opline;
zend_function *fbc = NULL;
- zend_bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL;
+ bool nullsafe = ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL;
if (is_this_fetch(obj_ast)) {
if (this_guaranteed_exists()) {
@@ -4421,7 +4525,7 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
}
/* }}} */
-static zend_bool zend_is_constructor(zend_string *name) /* {{{ */
+static bool zend_is_constructor(zend_string *name) /* {{{ */
{
return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
}
@@ -4513,7 +4617,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
}
/* }}} */
-void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel);
+void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel);
void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
{
@@ -4569,6 +4673,7 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
convert_to_string(&name_node.u.constant);
}
+ // TODO(GLOBALS) Forbid "global $GLOBALS"?
if (is_this_fetch(var_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
} else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
@@ -4640,6 +4745,21 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
zend_ensure_writable_variable(var_ast);
+ if (is_global_var_fetch(var_ast)) {
+ if (!var_ast->child[1]) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
+ }
+
+ zend_compile_expr(&var_node, var_ast->child[1]);
+ if (var_node.op_type == IS_CONST) {
+ convert_to_string(&var_node.u.constant);
+ }
+
+ opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
+ opline->extended_value = ZEND_FETCH_GLOBAL;
+ return;
+ }
+
switch (var_ast->kind) {
case ZEND_AST_VAR:
if (is_this_fetch(var_ast)) {
@@ -4759,8 +4879,8 @@ static bool zend_has_finally(void) /* {{{ */
void zend_compile_return(zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
- zend_bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0;
- zend_bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+ bool is_generator = (CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0;
+ bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
znode expr_node;
zend_op *opline;
@@ -5127,8 +5247,8 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
zend_ast *value_ast = ast->child[1];
zend_ast *key_ast = ast->child[2];
zend_ast *stmt_ast = ast->child[3];
- zend_bool by_ref = value_ast->kind == ZEND_AST_REF;
- zend_bool is_variable = zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast);
+ bool by_ref = value_ast->kind == ZEND_AST_REF;
+ bool is_variable = zend_is_variable(expr_ast) && zend_can_write_to_variable(expr_ast);
znode expr_node, reset_node, value_node, key_node;
zend_op *opline;
@@ -5297,7 +5417,7 @@ static zend_uchar determine_switch_jumptable_type(zend_ast_list *cases) {
return common_type;
}
-static zend_bool should_use_jumptable(zend_ast_list *cases, zend_uchar jumptable_type) {
+static bool should_use_jumptable(zend_ast_list *cases, zend_uchar jumptable_type) {
if (CG(compiler_options) & ZEND_COMPILE_NO_JUMPTABLES) {
return 0;
}
@@ -5318,7 +5438,7 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
uint32_t i;
- zend_bool has_default_case = 0;
+ bool has_default_case = 0;
znode expr_node, case_node;
zend_op *opline;
@@ -5463,7 +5583,7 @@ static uint32_t count_match_conds(zend_ast_list *arms)
return num_conds;
}
-static zend_bool can_match_use_jumptable(zend_ast_list *arms) {
+static bool can_match_use_jumptable(zend_ast_list *arms) {
for (uint32_t i = 0; i < arms->children; i++) {
zend_ast *arm_ast = arms->child[i];
if (!arm_ast->child[0]) {
@@ -5494,7 +5614,7 @@ void zend_compile_match(znode *result, zend_ast *ast)
{
zend_ast *expr_ast = ast->child[0];
zend_ast_list *arms = zend_ast_get_list(ast->child[1]);
- zend_bool has_default_arm = 0;
+ bool has_default_arm = 0;
uint32_t opnum_match = (uint32_t)-1;
znode expr_node;
@@ -5506,7 +5626,7 @@ void zend_compile_match(znode *result, zend_ast *ast)
uint32_t num_conds = count_match_conds(arms);
zend_uchar can_use_jumptable = can_match_use_jumptable(arms);
- zend_bool uses_jumptable = can_use_jumptable && num_conds >= 2;
+ bool uses_jumptable = can_use_jumptable && num_conds >= 2;
HashTable *jumptable = NULL;
uint32_t *jmpnz_opnums = NULL;
@@ -5572,7 +5692,7 @@ void zend_compile_match(znode *result, zend_ast *ast)
opnum_default_jmp = zend_emit_jump(0);
}
- zend_bool is_first_case = 1;
+ bool is_first_case = 1;
uint32_t cond_count = 0;
uint32_t *jmp_end_opnums = safe_emalloc(sizeof(uint32_t), arms->children, 0);
@@ -5731,7 +5851,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
zend_ast *var_ast = catch_ast->child[1];
zend_ast *stmt_ast = catch_ast->child[2];
zend_string *var_name = var_ast ? zval_make_interned_string(zend_ast_get_zval(var_ast)) : NULL;
- zend_bool is_last_catch = (i + 1 == catches->children);
+ bool is_last_catch = (i + 1 == catches->children);
uint32_t *jmp_multicatch = safe_emalloc(sizeof(uint32_t), classes->children - 1, 0);
uint32_t opnum_catch = (uint32_t)-1;
@@ -5740,7 +5860,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
for (j = 0; j < classes->children; j++) {
zend_ast *class_ast = classes->child[j];
- zend_bool is_last_class = (j + 1 == classes->children);
+ bool is_last_class = (j + 1 == classes->children);
if (!zend_is_const_default_class_ref(class_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
@@ -5847,7 +5967,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
/* }}} */
/* Encoding declarations must already be handled during parsing */
-zend_bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
+bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
{
zend_ast_list *declares = zend_ast_get_list(ast);
uint32_t i;
@@ -5899,7 +6019,7 @@ zend_bool zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
/* }}} */
/* Check whether this is the first statement, not counting declares. */
-static zend_result zend_is_first_statement(zend_ast *ast, zend_bool allow_nop) /* {{{ */
+static zend_result zend_is_first_statement(zend_ast *ast, bool allow_nop) /* {{{ */
{
uint32_t i = 0;
zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
@@ -6075,7 +6195,7 @@ static zend_type zend_compile_single_typename(zend_ast *ast)
}
}
-static zend_bool zend_type_contains_traversable(zend_type type) {
+static bool zend_type_contains_traversable(zend_type type) {
zend_type *single_type;
ZEND_TYPE_FOREACH(type, single_type) {
if (ZEND_TYPE_HAS_NAME(*single_type)
@@ -6089,9 +6209,9 @@ static zend_bool zend_type_contains_traversable(zend_type type) {
// TODO: Ideally we'd canonicalize "iterable" into "array|Traversable" and essentially
// treat it as a built-in type alias.
static zend_type zend_compile_typename(
- zend_ast *ast, zend_bool force_allow_null, zend_bool use_arena) /* {{{ */
+ zend_ast *ast, bool force_allow_null) /* {{{ */
{
- zend_bool allow_null = force_allow_null;
+ bool allow_null = force_allow_null;
zend_ast_attr orig_ast_attr = ast->attr;
zend_type type = ZEND_TYPE_INIT_NONE(0);
if (ast->attr & ZEND_TYPE_NULLABLE) {
@@ -6101,6 +6221,12 @@ static zend_type zend_compile_typename(
if (ast->kind == ZEND_AST_TYPE_UNION) {
zend_ast_list *list = zend_ast_get_list(ast);
+ zend_type_list *type_list;
+ ALLOCA_FLAG(use_heap)
+
+ type_list = do_alloca(ZEND_TYPE_LIST_SIZE(list->children), use_heap);
+ type_list->num_types = 0;
+
for (uint32_t i = 0; i < list->children; i++) {
zend_ast *type_ast = list->child[i];
zend_type single_type = zend_compile_single_typename(type_ast);
@@ -6126,37 +6252,20 @@ static zend_type zend_compile_typename(
ZEND_TYPE_SET_PTR(type, ZEND_TYPE_NAME(single_type));
ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_NAME_BIT;
} else {
- zend_type_list *list;
- if (ZEND_TYPE_HAS_LIST(type)) {
- /* Add name to existing name list. */
- zend_type_list *old_list = ZEND_TYPE_LIST(type);
- if (use_arena) {
- // TODO: Add a zend_arena_realloc API?
- list = zend_arena_alloc(
- &CG(arena), ZEND_TYPE_LIST_SIZE(old_list->num_types + 1));
- memcpy(list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types));
- } else {
- list = erealloc(old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types + 1));
- }
- } else {
+ if (type_list->num_types == 0) {
/* Switch from single name to name list. */
- size_t size = ZEND_TYPE_LIST_SIZE(2);
- list = use_arena ? zend_arena_alloc(&CG(arena), size) : emalloc(size);
- list->num_types = 1;
- list->types[0] = type;
- ZEND_TYPE_FULL_MASK(list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
+ type_list->num_types = 1;
+ type_list->types[0] = type;
+ ZEND_TYPE_FULL_MASK(type_list->types[0]) &= ~_ZEND_TYPE_MAY_BE_MASK;
+ ZEND_TYPE_SET_LIST(type, type_list);
}
- list->types[list->num_types++] = single_type;
- ZEND_TYPE_SET_LIST(type, list);
- if (use_arena) {
- ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
- }
+ type_list->types[type_list->num_types++] = single_type;
/* Check for trivially redundant class types */
- for (size_t i = 0; i < list->num_types - 1; i++) {
+ for (size_t i = 0; i < type_list->num_types - 1; i++) {
if (zend_string_equals_ci(
- ZEND_TYPE_NAME(list->types[i]), ZEND_TYPE_NAME(single_type))) {
+ ZEND_TYPE_NAME(type_list->types[i]), ZEND_TYPE_NAME(single_type))) {
zend_string *single_type_str = zend_type_to_string(single_type);
zend_error_noreturn(E_COMPILE_ERROR,
"Duplicate type %s is redundant", ZSTR_VAL(single_type_str));
@@ -6165,6 +6274,16 @@ static zend_type zend_compile_typename(
}
}
}
+
+ if (type_list->num_types) {
+ zend_type_list *list = zend_arena_alloc(
+ &CG(arena), ZEND_TYPE_LIST_SIZE(type_list->num_types));
+ memcpy(list, type_list, ZEND_TYPE_LIST_SIZE(type_list->num_types));
+ ZEND_TYPE_SET_LIST(type, list);
+ ZEND_TYPE_FULL_MASK(type) |= _ZEND_TYPE_ARENA_BIT;
+ }
+
+ free_alloca(type_list, use_heap);
} else {
type = zend_compile_single_typename(ast);
}
@@ -6217,7 +6336,7 @@ static zend_type zend_compile_typename(
/* }}} */
/* May convert value from int to float. */
-static zend_bool zend_is_valid_default_value(zend_type type, zval *value)
+static bool zend_is_valid_default_value(zend_type type, zval *value)
{
ZEND_ASSERT(ZEND_TYPE_IS_SET(type));
if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) {
@@ -6266,7 +6385,7 @@ static void zend_compile_attributes(HashTable **attributes, zend_ast *ast, uint3
if (args) {
ZEND_ASSERT(args->kind == ZEND_AST_ARG_LIST);
- zend_bool uses_named_args = 0;
+ bool uses_named_args = 0;
for (j = 0; j < args->children; j++) {
zend_ast **arg_ast_ptr = &args->child[j];
zend_ast *arg_ast = *arg_ast_ptr;
@@ -6341,7 +6460,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
arg_infos->name = NULL;
if (return_type_ast) {
arg_infos->type = zend_compile_typename(
- return_type_ast, /* force_allow_null */ 0, /* use_arena */ 0);
+ return_type_ast, /* force_allow_null */ 0);
ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS(
(op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0);
} else {
@@ -6364,8 +6483,8 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
zend_ast *attributes_ast = param_ast->child[3];
zend_ast *doc_comment_ast = param_ast->child[4];
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;
+ bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
+ bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
uint32_t visibility =
param_ast->attr & (ZEND_ACC_PUBLIC|ZEND_ACC_PROTECTED|ZEND_ACC_PRIVATE);
@@ -6414,7 +6533,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
if (!optional_param) {
/* Ignore parameters of the form "Type $param = null".
* This is the PHP 5 style way of writing "?Type $param", so allow it for now. */
- zend_bool is_implicit_nullable =
+ bool is_implicit_nullable =
type_ast && Z_TYPE(default_node.u.constant) == IS_NULL;
if (!is_implicit_nullable) {
optional_param = name;
@@ -6440,10 +6559,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
if (type_ast) {
uint32_t default_type = *default_ast_ptr ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
- zend_bool force_nullable = default_type == IS_NULL && !visibility;
+ bool force_nullable = default_type == IS_NULL && !visibility;
op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
- arg_info->type = zend_compile_typename(type_ast, force_nullable, /* use_arena */ 0);
+ arg_info->type = zend_compile_typename(type_ast, force_nullable);
if (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID) {
zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
@@ -6480,7 +6599,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
if (visibility) {
zend_op_array *op_array = CG(active_op_array);
zend_class_entry *scope = op_array->scope;
- zend_bool is_ctor =
+ bool is_ctor =
scope && zend_is_constructor(op_array->function_name);
if (!is_ctor) {
zend_error_noreturn(E_COMPILE_ERROR,
@@ -6509,7 +6628,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
/* Recompile the type, as it has different memory management requirements. */
zend_type type = ZEND_TYPE_INIT_NONE(0);
if (type_ast) {
- type = zend_compile_typename(type_ast, /* force_allow_null */ 0, /* use_arena */ 1);
+ type = zend_compile_typename(type_ast, /* force_allow_null */ 0);
}
/* Don't give the property an explicit default value. For typed properties this means
@@ -6544,7 +6663,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32_t fall
for (i = 0; i < list->children; i++) {
zend_ast *param_ast = list->child[i];
- zend_bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
+ bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
uint32_t visibility =
param_ast->attr & (ZEND_ACC_PUBLIC|ZEND_ACC_PROTECTED|ZEND_ACC_PRIVATE);
if (!visibility) {
@@ -6614,7 +6733,7 @@ static void zend_compile_closure_binding(znode *closure, zend_op_array *op_array
typedef struct {
HashTable uses;
- zend_bool varvars_used;
+ bool varvars_used;
} closure_info;
static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) {
@@ -6770,10 +6889,10 @@ static void add_stringable_interface(zend_class_entry *ce) {
zend_string_init("stringable", sizeof("stringable") - 1, 0);
}
-zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */
+zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name, bool has_body) /* {{{ */
{
zend_class_entry *ce = CG(active_class_entry);
- zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
+ bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
uint32_t fn_flags = op_array->fn_flags;
zend_string *lcname;
@@ -6827,9 +6946,18 @@ zend_string *zend_begin_method_decl(zend_op_array *op_array, zend_string *name,
}
/* }}} */
-static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, zend_bool toplevel) /* {{{ */
+static uint32_t zend_add_dynamic_func_def(zend_op_array *def) {
+ zend_op_array *op_array = CG(active_op_array);
+ uint32_t def_offset = op_array->num_dynamic_func_defs++;
+ op_array->dynamic_func_defs = erealloc(
+ op_array->dynamic_func_defs, op_array->num_dynamic_func_defs * sizeof(zend_op_array *));
+ op_array->dynamic_func_defs[def_offset] = def;
+ return def_offset;
+}
+
+static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, bool toplevel) /* {{{ */
{
- zend_string *unqualified_name, *name, *lcname, *key;
+ zend_string *unqualified_name, *name, *lcname;
zend_op *opline;
unqualified_name = decl->name;
@@ -6865,38 +6993,29 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as
return;
}
- /* Generate RTD keys until we find one that isn't in use yet. */
- key = NULL;
- do {
- zend_tmp_string_release(key);
- key = zend_build_runtime_definition_key(lcname, decl->start_lineno);
- } while (!zend_hash_add_ptr(CG(function_table), key, op_array));
-
+ uint32_t func_ref = zend_add_dynamic_func_def(op_array);
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
- opline->extended_value = zend_alloc_cache_slot();
- opline->op1_type = IS_CONST;
- LITERAL_STR(opline->op1, key);
+ opline->op2.num = func_ref;
} else {
opline = get_next_op();
opline->opcode = ZEND_DECLARE_FUNCTION;
opline->op1_type = IS_CONST;
LITERAL_STR(opline->op1, zend_string_copy(lcname));
- /* RTD key is placed after lcname literal in op1 */
- zend_add_literal_string(&key);
+ opline->op2.num = func_ref;
}
zend_string_release_ex(lcname, 0);
}
/* }}} */
-void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* {{{ */
+void zend_compile_func_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
{
zend_ast_decl *decl = (zend_ast_decl *) ast;
zend_ast *params_ast = decl->child[0];
zend_ast *uses_ast = decl->child[1];
zend_ast *stmt_ast = decl->child[2];
zend_ast *return_type_ast = decl->child[3];
- zend_bool is_method = decl->kind == ZEND_AST_METHOD;
+ bool is_method = decl->kind == ZEND_AST_METHOD;
zend_string *method_lcname;
zend_class_entry *orig_class_entry = CG(active_class_entry);
@@ -6910,13 +7029,11 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
op_array->fn_flags |= ZEND_ACC_PRELOADED;
- ZEND_MAP_PTR_NEW(op_array->run_time_cache);
- ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
- } else {
- ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
- ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
}
+ ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void *)));
+ ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
+
op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
op_array->fn_flags |= decl->flags;
op_array->line_start = decl->start_lineno;
@@ -6930,7 +7047,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
}
if (is_method) {
- zend_bool has_body = stmt_ast != NULL;
+ bool has_body = stmt_ast != NULL;
method_lcname = zend_begin_method_decl(op_array, decl->name, has_body);
} else {
zend_begin_func_decl(result, op_array, decl, toplevel);
@@ -7002,6 +7119,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
zend_do_extended_stmt();
zend_emit_final_return(0);
+ zend_init_static_variables_map_ptr(op_array);
pass_two(CG(active_op_array));
zend_oparray_context_end(&orig_oparray_context);
@@ -7039,7 +7157,7 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, z
zend_type type = ZEND_TYPE_INIT_NONE(0);
if (type_ast) {
- type = zend_compile_typename(type_ast, /* force_allow_null */ 0, /* use_arena */ 1);
+ type = zend_compile_typename(type_ast, /* force_allow_null */ 0);
if (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
zend_string *str = zend_type_to_string(type);
@@ -7311,7 +7429,7 @@ static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
return zend_new_interned_string(result);
}
-void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* {{{ */
+void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
{
zend_ast_decl *decl = (zend_ast_decl *) ast;
zend_ast *extends_ast = decl->child[0];
@@ -7412,31 +7530,36 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /
ce->ce_flags |= ZEND_ACC_TOP_LEVEL;
}
- if (toplevel
- /* We currently don't early-bind classes that implement interfaces or use traits */
- && !ce->num_interfaces && !ce->num_traits
+ /* We currently don't early-bind classes that implement interfaces or use traits */
+ if (!ce->num_interfaces && !ce->num_traits
&& !(CG(compiler_options) & ZEND_COMPILE_WITHOUT_EXECUTION)) {
- if (extends_ast) {
- zend_class_entry *parent_ce = zend_lookup_class_ex(
- ce->parent_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
-
- if (parent_ce
- && ((parent_ce->type != ZEND_INTERNAL_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES))
- && ((parent_ce->type != ZEND_USER_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) || (parent_ce->info.user.filename == ce->info.user.filename))) {
-
- CG(zend_lineno) = decl->end_lineno;
- if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) {
+ if (toplevel) {
+ if (extends_ast) {
+ zend_class_entry *parent_ce = zend_lookup_class_ex(
+ ce->parent_name, NULL, ZEND_FETCH_CLASS_NO_AUTOLOAD);
+
+ if (parent_ce
+ && ((parent_ce->type != ZEND_INTERNAL_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES))
+ && ((parent_ce->type != ZEND_USER_CLASS) || !(CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) || (parent_ce->info.user.filename == ce->info.user.filename))) {
+
+ CG(zend_lineno) = decl->end_lineno;
+ if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) {
+ CG(zend_lineno) = ast->lineno;
+ zend_string_release(lcname);
+ return;
+ }
CG(zend_lineno) = ast->lineno;
- zend_string_release(lcname);
- return;
}
- CG(zend_lineno) = ast->lineno;
+ } 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;
}
- } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
- zend_string_release(lcname);
+ } else if (!extends_ast) {
+ /* Link unbound simple class */
zend_build_properties_info_table(ce);
ce->ce_flags |= ZEND_ACC_LINKED;
- return;
}
}
@@ -7550,7 +7673,7 @@ void zend_compile_use(zend_ast *ast) /* {{{ */
zend_string *current_ns = FC(current_namespace);
uint32_t type = ast->attr;
HashTable *current_import = zend_get_import_ht(type);
- zend_bool case_sensitive = type == ZEND_SYMBOL_CONST;
+ bool case_sensitive = type == ZEND_SYMBOL_CONST;
for (i = 0; i < list->children; ++i) {
zend_ast *use_ast = list->child[i];
@@ -7684,7 +7807,7 @@ void zend_compile_namespace(zend_ast *ast) /* {{{ */
zend_ast *name_ast = ast->child[0];
zend_ast *stmt_ast = ast->child[1];
zend_string *name;
- zend_bool with_bracket = stmt_ast != NULL;
+ bool with_bracket = stmt_ast != NULL;
/* handle mixed syntax declaration or nested namespaces */
if (!FC(has_bracketed_namespaces)) {
@@ -7705,7 +7828,7 @@ void zend_compile_namespace(zend_ast *ast) /* {{{ */
}
}
- zend_bool is_first_namespace = (!with_bracket && !FC(current_namespace))
+ bool is_first_namespace = (!with_bracket && !FC(current_namespace))
|| (with_bracket && !FC(has_bracketed_namespaces));
if (is_first_namespace && FAILURE == zend_is_first_statement(ast, /* allow_nop */ 1)) {
zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
@@ -7764,7 +7887,7 @@ void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
}
/* }}} */
-static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
+static bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
{
zend_op_array *op_array = CG(active_op_array);
zend_class_entry *ce = CG(active_class_entry);
@@ -7855,7 +7978,7 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
}
/* }}} */
-ZEND_API zend_bool zend_binary_op_produces_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */
+ZEND_API bool zend_binary_op_produces_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */
{
if ((opcode == ZEND_CONCAT || opcode == ZEND_FAST_CONCAT)) {
/* Array to string warning. */
@@ -7910,7 +8033,7 @@ ZEND_API zend_bool zend_binary_op_produces_error(uint32_t opcode, zval *op1, zva
}
/* }}} */
-static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
+static inline bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
{
if (zend_binary_op_produces_error(opcode, op1, op2)) {
return 0;
@@ -7922,7 +8045,7 @@ static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode
}
/* }}} */
-zend_bool zend_unary_op_produces_error(uint32_t opcode, zval *op)
+bool zend_unary_op_produces_error(uint32_t opcode, zval *op)
{
if (opcode == ZEND_BW_NOT) {
return Z_TYPE_P(op) <= IS_TRUE || Z_TYPE_P(op) == IS_ARRAY;
@@ -7931,7 +8054,7 @@ zend_bool zend_unary_op_produces_error(uint32_t opcode, zval *op)
return 0;
}
-static inline zend_bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
+static inline bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
{
if (zend_unary_op_produces_error(opcode, op)) {
return 0;
@@ -7943,7 +8066,7 @@ static inline zend_bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode,
}
/* }}} */
-static inline zend_bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
+static inline bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
{
zval right;
ZVAL_LONG(&right, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
@@ -7959,12 +8082,12 @@ static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *
}
/* }}} */
-static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
+static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(ast);
zend_ast *last_elem_ast = NULL;
uint32_t i;
- zend_bool is_constant = 1;
+ bool is_constant = 1;
if (ast->attr == ZEND_ARRAY_SYNTAX_LIST) {
zend_error(E_COMPILE_ERROR, "Cannot use list() as standalone expression");
@@ -8026,9 +8149,8 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
if (key) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot unpack array with string keys");
- }
- if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
+ zend_hash_update(Z_ARRVAL_P(result), key, val);
+ } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
zval_ptr_dtor(result);
return 0;
}
@@ -8490,7 +8612,7 @@ void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
znode var_node_is, var_node_w, default_node, assign_node, *node;
zend_op *opline;
uint32_t coalesce_opnum;
- zend_bool need_frees = 0;
+ bool need_frees = 0;
/* Remember expressions compiled during the initial BP_VAR_IS lookup,
* to avoid double-evaluation when we compile again with BP_VAR_W. */
@@ -8620,7 +8742,7 @@ void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
znode value_node, key_node;
znode *value_node_ptr = NULL, *key_node_ptr = NULL;
zend_op *opline;
- zend_bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
+ bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
zend_mark_function_as_generator();
@@ -8733,6 +8855,28 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
}
}
+ if (is_globals_fetch(var_ast)) {
+ result->op_type = IS_CONST;
+ ZVAL_BOOL(&result->u.constant, ast->kind == ZEND_AST_ISSET);
+ return;
+ }
+
+ if (is_global_var_fetch(var_ast)) {
+ if (!var_ast->child[1]) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
+ }
+
+ zend_compile_expr(&var_node, var_ast->child[1]);
+ if (var_node.op_type == IS_CONST) {
+ convert_to_string(&var_node.u.constant);
+ }
+
+ opline = zend_emit_op_tmp(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
+ opline->extended_value =
+ ZEND_FETCH_GLOBAL | (ast->kind == ZEND_AST_EMPTY ? ZEND_ISEMPTY : 0);
+ return;
+ }
+
zend_short_circuiting_mark_inner(var_ast);
switch (var_ast->kind) {
case ZEND_AST_VAR:
@@ -8811,7 +8955,7 @@ void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
zend_ast_list *list = zend_ast_get_list(ast);
zend_op *opline;
uint32_t i, opnum_init = -1;
- zend_bool packed = 1;
+ bool packed = 1;
if (zend_try_ct_eval_array(&result->u.constant, ast)) {
result->op_type = IS_CONST;
@@ -8824,7 +8968,7 @@ void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
for (i = 0; i < list->children; ++i) {
zend_ast *elem_ast = list->child[i];
zend_ast *value_ast, *key_ast;
- zend_bool by_ref;
+ bool by_ref;
znode value_node, key_node, *key_node_ptr = NULL;
if (elem_ast == NULL) {
@@ -8891,7 +9035,7 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
zend_op *opline;
- zend_bool is_fully_qualified;
+ bool is_fully_qualified;
zend_string *orig_name = zend_ast_get_str(name_ast);
zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
@@ -9168,7 +9312,7 @@ void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
}
/* }}} */
-zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
+bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
{
return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
|| kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
@@ -9255,7 +9399,7 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
zend_ast *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;
+ bool is_fully_qualified;
zval result;
zend_string *resolved_name;
@@ -9676,7 +9820,7 @@ zend_op *zend_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_r
return opcode;
}
-zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, zend_bool by_ref) /* {{{ */
+zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type, bool by_ref) /* {{{ */
{
switch (ast->kind) {
case ZEND_AST_VAR:
@@ -9737,7 +9881,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
case ZEND_AST_AND:
case ZEND_AST_OR:
{
- zend_bool child0_is_true, child1_is_true;
+ 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) {
@@ -9911,7 +10055,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
case ZEND_AST_CONST:
{
zend_ast *name_ast = ast->child[0];
- zend_bool is_fully_qualified;
+ bool is_fully_qualified;
zend_string *resolved_name = zend_resolve_const_name(
zend_ast_get_str(name_ast), name_ast->attr, &is_fully_qualified);
@@ -9940,7 +10084,6 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
}
resolved_name = zend_resolve_class_name_ast(class_ast);
-
if (!zend_try_ct_eval_class_const(&result, resolved_name, zend_ast_get_str(name_ast))) {
zend_string_release_ex(resolved_name, 0);
return;