diff options
Diffstat (limited to 'Zend/zend_compile.c')
| -rw-r--r-- | Zend/zend_compile.c | 734 |
1 files changed, 301 insertions, 433 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 494bd3112f..b388ebfb82 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -71,7 +71,7 @@ static inline uint32_t zend_alloc_cache_slot(void) { } ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type); -ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename); +ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, const char *filename); #ifndef ZTS ZEND_API zend_compiler_globals compiler_globals; @@ -469,17 +469,6 @@ static int lookup_cv(zend_string *name) /* {{{ */{ } /* }}} */ -void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */ -{ - zval_ptr_dtor_nogc(CT_CONSTANT_EX(op_array, n)); - if (n + 1 == op_array->last_literal) { - op_array->last_literal--; - } else { - ZVAL_UNDEF(CT_CONSTANT_EX(op_array, n)); - } -} -/* }}} */ - static inline zend_string *zval_make_interned_string(zval *zv) /* {{{ */ { ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING); @@ -599,10 +588,6 @@ static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) zend_str_tolower(ZSTR_VAL(tmp_name), ns_len); zend_add_literal_string(&tmp_name); - /* lowercased namespace name & lowercased constant name */ - tmp_name = zend_string_tolower(name); - zend_add_literal_string(&tmp_name); - if (!unqualified) { return ret; } @@ -614,11 +599,6 @@ static int zend_add_const_name_literal(zend_string *name, zend_bool unqualified) tmp_name = zend_string_init(after_ns, after_ns_len, 0); zend_add_literal_string(&tmp_name); - /* lowercased unqualified constant name */ - tmp_name = zend_string_alloc(after_ns_len, 0); - zend_str_tolower_copy(ZSTR_VAL(tmp_name), after_ns, after_ns_len); - zend_add_literal_string(&tmp_name); - return ret; } /* }}} */ @@ -1000,10 +980,9 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */ if (op_array->refcount) { (*op_array->refcount)++; } - if (op_array->static_variables) { - if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { - GC_ADDREF(op_array->static_variables); - } + if (op_array->static_variables + && !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { + GC_ADDREF(op_array->static_variables); } 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*))); @@ -1090,6 +1069,70 @@ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */ } /* }}} */ +zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) { + zend_bool nullable = ZEND_TYPE_ALLOW_NULL(type); + zend_string *str; + if (ZEND_TYPE_IS_NAME(type)) { + zend_string *name = ZEND_TYPE_NAME(type); + if (scope) { + if (zend_string_equals_literal_ci(name, "self")) { + name = scope->name; + } else if (zend_string_equals_literal_ci(name, "parent") && scope->parent) { + name = scope->parent->name; + } + } + str = zend_string_copy(name); + } else if (ZEND_TYPE_IS_CE(type)) { + str = zend_string_copy(ZEND_TYPE_CE(type)->name); + } else { + uint32_t type_mask = ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(type)); + switch (type_mask) { + case MAY_BE_FALSE|MAY_BE_TRUE: + str = ZSTR_KNOWN(ZEND_STR_BOOL); + break; + case MAY_BE_LONG: + str = ZSTR_KNOWN(ZEND_STR_INT); + break; + case MAY_BE_DOUBLE: + str = ZSTR_KNOWN(ZEND_STR_FLOAT); + break; + case MAY_BE_STRING: + str = ZSTR_KNOWN(ZEND_STR_STRING); + break; + case MAY_BE_ARRAY: + str = ZSTR_KNOWN(ZEND_STR_ARRAY); + break; + case MAY_BE_OBJECT: + str = ZSTR_KNOWN(ZEND_STR_OBJECT); + break; + case MAY_BE_CALLABLE: + str = ZSTR_KNOWN(ZEND_STR_CALLABLE); + break; + case MAY_BE_ITERABLE: + str = ZSTR_KNOWN(ZEND_STR_ITERABLE); + break; + case MAY_BE_VOID: + str = ZSTR_KNOWN(ZEND_STR_VOID); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + + if (nullable) { + zend_string *nullable_str = zend_string_alloc(ZSTR_LEN(str) + 1, 0); + ZSTR_VAL(nullable_str)[0] = '?'; + memcpy(ZSTR_VAL(nullable_str) + 1, ZSTR_VAL(str), ZSTR_LEN(str)); + ZSTR_VAL(nullable_str)[ZSTR_LEN(nullable_str)] = '\0'; + zend_string_release(str); + return nullable_str; + } + return str; +} + +zend_string *zend_type_to_string(zend_type type) { + return zend_type_to_string_resolved(type, NULL); +} + static void zend_mark_function_as_generator() /* {{{ */ { if (!CG(active_op_array)->function_name) { @@ -1099,19 +1142,22 @@ static void zend_mark_function_as_generator() /* {{{ */ if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { zend_arg_info return_info = CG(active_op_array)->arg_info[-1]; + zend_bool valid_type; + if (ZEND_TYPE_IS_CLASS(return_info.type)) { + zend_string *name = ZEND_TYPE_NAME(return_info.type); + valid_type = zend_string_equals_literal_ci(name, "Traversable") + || zend_string_equals_literal_ci(name, "Iterator") + || zend_string_equals_literal_ci(name, "Generator"); + } else { + valid_type = (ZEND_TYPE_MASK(return_info.type) & MAY_BE_ITERABLE) != 0; + } - 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))); - } - - if (!zend_string_equals_literal_ci(ZEND_TYPE_NAME(return_info.type), "Traversable") - && !zend_string_equals_literal_ci(ZEND_TYPE_NAME(return_info.type), "Iterator") - && !zend_string_equals_literal_ci(ZEND_TYPE_NAME(return_info.type), "Generator")) { - zend_error_noreturn(E_COMPILE_ERROR, msg, ZSTR_VAL(ZEND_TYPE_NAME(return_info.type))); - } + if (!valid_type) { + zend_string *str = zend_type_to_string(return_info.type); + zend_error_noreturn(E_COMPILE_ERROR, + "Generators may only declare a return type of " \ + "Generator, Iterator, Traversable, or iterable, %s is not permitted", + ZSTR_VAL(str)); } } @@ -1251,26 +1297,13 @@ ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char } /* }}} */ -static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */ -{ - zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len); - if (c && !(ZEND_CONSTANT_FLAGS(c) & CONST_CS) && (ZEND_CONSTANT_FLAGS(c) & CONST_CT_SUBST)) { - return c; - } - return NULL; -} -/* }}} */ - static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */ { - zend_constant *c; - - /* Substitute case-sensitive (or lowercase) constants */ - c = zend_hash_find_ptr(EG(zend_constants), name); + zend_constant *c = zend_hash_find_ptr(EG(zend_constants), name); if (c && ( ((ZEND_CONSTANT_FLAGS(c) & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) - && (!(ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) || !(CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) + && !((ZEND_CONSTANT_FLAGS(c) & CONST_NO_FILE_CACHE) && (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) )) { ZVAL_COPY_OR_DUP(zv, &c->value); @@ -1281,19 +1314,19 @@ static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool i /* Substitute true, false and null (including unqualified usage in namespaces) */ const char *lookup_name = ZSTR_VAL(name); size_t lookup_len = ZSTR_LEN(name); + zval *val; if (!is_fully_qualified) { zend_get_unqualified_name(name, &lookup_name, &lookup_len); } - c = zend_lookup_reserved_const(lookup_name, lookup_len); - if (c) { - ZVAL_COPY_OR_DUP(zv, &c->value); + if ((val = zend_get_special_const(lookup_name, lookup_len))) { + ZVAL_COPY_VALUE(zv, val); return 1; } - } - return 0; + return 0; + } } /* }}} */ @@ -2074,11 +2107,12 @@ static void zend_compile_memoized_expr(znode *result, zend_ast *expr) /* {{{ */ static void zend_emit_return_type_check( znode *expr, zend_arg_info *return_info, zend_bool implicit) /* {{{ */ { - if (ZEND_TYPE_IS_SET(return_info->type)) { + zend_type type = return_info->type; + if (ZEND_TYPE_IS_SET(type)) { zend_op *opline; /* `return ...;` is illegal in a void function (but `return;` isn't) */ - if (ZEND_TYPE_CODE(return_info->type) == IS_VOID) { + if (ZEND_TYPE_IS_MASK(type) && ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) { if (expr) { if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) { zend_error_noreturn(E_COMPILE_ERROR, @@ -2093,7 +2127,7 @@ static void zend_emit_return_type_check( } if (!expr && !implicit) { - if (ZEND_TYPE_ALLOW_NULL(return_info->type)) { + if (ZEND_TYPE_ALLOW_NULL(type)) { zend_error_noreturn(E_COMPILE_ERROR, "A function with return type must return a value " "(did you mean \"return null;\" instead of \"return;\"?)"); @@ -2104,12 +2138,8 @@ static void zend_emit_return_type_check( } if (expr && expr->op_type == IS_CONST) { - if ((ZEND_TYPE_CODE(return_info->type) == Z_TYPE(expr->u.constant)) - ||((ZEND_TYPE_CODE(return_info->type) == _IS_BOOL) - && (Z_TYPE(expr->u.constant) == IS_FALSE - || Z_TYPE(expr->u.constant) == IS_TRUE)) - || (ZEND_TYPE_ALLOW_NULL(return_info->type) - && Z_TYPE(expr->u.constant) == IS_NULL)) { + if (ZEND_TYPE_IS_MASK(type) + && ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) { /* we don't need run-time check */ return; } @@ -2479,10 +2509,6 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t CG(active_op_array)->fn_flags |= ZEND_ACC_USES_THIS; } else { opline = zend_delayed_compile_var(&obj_node, obj_ast, type, 0); - if (opline && type == BP_VAR_W && (opline->opcode == ZEND_FETCH_STATIC_PROP_W || opline->opcode == ZEND_FETCH_OBJ_W)) { - opline->extended_value |= ZEND_FETCH_OBJ_WRITE; - } - zend_separate_if_call_and_write(&obj_node, obj_ast, type); } zend_compile_expr(&prop_node, prop_ast); @@ -2979,26 +3005,26 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */ } arg_count++; - if (zend_is_variable_or_call(arg)) { - if (zend_is_call(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 */ - opcode = ZEND_SEND_VAL; - } else { - if (fbc) { - if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAR_NO_REF; - } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { - opcode = ZEND_SEND_VAL; - } else { - opcode = ZEND_SEND_VAR; - } + if (zend_is_call(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 */ + opcode = ZEND_SEND_VAL; + } else { + if (fbc) { + if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAR_NO_REF; + } else if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) { + opcode = ZEND_SEND_VAL; } else { - opcode = ZEND_SEND_VAR_NO_REF_EX; + opcode = ZEND_SEND_VAR; } + } else { + opcode = ZEND_SEND_VAR_NO_REF_EX; } - } else if (fbc) { + } + } else if (zend_is_variable(arg)) { + if (fbc) { if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) { zend_compile_var(&arg_node, arg, BP_VAR_W, 1); opcode = ZEND_SEND_REF; @@ -3077,7 +3103,7 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc) if (fbc) { if (fbc->type == ZEND_INTERNAL_FUNCTION && !(CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS)) { if (init_op->opcode == ZEND_INIT_FCALL && !zend_execute_internal) { - if (!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_RETURN_REFERENCE))) { + if (!(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED))) { return ZEND_DO_ICALL; } else { return ZEND_DO_FCALL_BY_NAME; @@ -3196,9 +3222,7 @@ int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */ { znode arg_node; - if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) - || args->children != 1 - ) { + if (args->children != 1) { return FAILURE; } @@ -3278,13 +3302,6 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */ LITERAL_STR(opline->op1, name); opline->extended_value = zend_alloc_cache_slot(); - /* Lowercase constant name in a separate literal */ - { - zval c; - zend_string *lcname = zend_string_tolower(name); - ZVAL_NEW_STR(&c, lcname); - zend_add_literal(&c); - } return SUCCESS; } /* }}} */ @@ -3927,6 +3944,24 @@ static zend_bool zend_is_constructor(zend_string *name) /* {{{ */ } /* }}} */ +static zend_function *zend_get_compatible_func_or_null(zend_class_entry *ce, zend_string *lcname) /* {{{ */ +{ + zend_function *fbc = zend_hash_find_ptr(&ce->function_table, lcname); + if (!fbc || (fbc->common.fn_flags & ZEND_ACC_PUBLIC) || ce == CG(active_class_entry)) { + return fbc; + } + + if (!(fbc->common.fn_flags & ZEND_ACC_PRIVATE) + && (fbc->common.scope->ce_flags & ZEND_ACC_LINKED) + && (!CG(active_class_entry) || (CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) + && zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry))) { + return fbc; + } + + return NULL; +} +/* }}} */ + void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ { zend_ast *class_ast = ast->child[0]; @@ -3985,18 +4020,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ } if (ce) { zend_string *lcname = Z_STR_P(CT_CONSTANT(opline->op2) + 1); - fbc = zend_hash_find_ptr(&ce->function_table, lcname); - if (fbc && !(fbc->common.fn_flags & ZEND_ACC_PUBLIC)) { - if (ce != CG(active_class_entry) - && ((fbc->common.fn_flags & ZEND_ACC_PRIVATE) - || !(fbc->common.scope->ce_flags & ZEND_ACC_LINKED) - || (CG(active_class_entry) - && !(CG(active_class_entry)->ce_flags & ZEND_ACC_LINKED)) - || !zend_check_protected(zend_get_function_root_class(fbc), CG(active_class_entry)))) { - /* incompatibe function */ - fbc = NULL; - } - } + fbc = zend_get_compatible_func_or_null(ce, lcname); } } @@ -5273,7 +5297,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null } if (ast->kind == ZEND_AST_TYPE) { - return ZEND_TYPE_ENCODE(ast->attr, allow_null); + return ZEND_TYPE_ENCODE_CODE(ast->attr, allow_null); } else { zend_string *class_name = zend_ast_get_str(ast); zend_uchar type = zend_lookup_builtin_type_by_name(class_name); @@ -5284,7 +5308,10 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null "Type declaration '%s' must be unqualified", ZSTR_VAL(zend_string_tolower(class_name))); } - return ZEND_TYPE_ENCODE(type, allow_null); + if (type == IS_VOID && allow_null) { + zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable"); + } + return ZEND_TYPE_ENCODE_CODE(type, allow_null); } else { uint32_t fetch_type = zend_get_class_fetch_type_ast(ast); if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { @@ -5301,6 +5328,29 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null } /* }}} */ +static zend_bool zend_is_valid_default_value(zend_type type, zval *value) +{ + ZEND_ASSERT(ZEND_TYPE_IS_SET(type)); + if (Z_TYPE_P(value) == IS_NULL && ZEND_TYPE_ALLOW_NULL(type)) { + return 1; + } + + if (ZEND_TYPE_IS_CLASS(type)) { + return 0; + } + if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE_P(value))) { + return 1; + } + if ((ZEND_TYPE_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) { + /* Integers are allowed as initializers for floating-point values. */ + return 1; + } + if ((ZEND_TYPE_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) { + return 1; + } + return 0; +} + void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -5315,11 +5365,6 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; arg_infos->is_variadic = 0; arg_infos->type = zend_compile_typename(return_type_ast, 0); - - if (ZEND_TYPE_CODE(arg_infos->type) == IS_VOID && ZEND_TYPE_ALLOW_NULL(arg_infos->type)) { - zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable"); - } - arg_infos++; op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE; } else { @@ -5393,90 +5438,36 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info->name = zend_string_copy(name); arg_info->pass_by_reference = is_ref; arg_info->is_variadic = is_variadic; - /* TODO: Keep compatibility, but may be better reset "allow_null" ??? */ - arg_info->type = ZEND_TYPE_ENCODE(0, 1); + arg_info->type = ZEND_TYPE_ENCODE_NONE(); if (type_ast) { - zend_bool has_null_default = default_ast - && (Z_TYPE(default_node.u.constant) == IS_NULL - || (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)); + uint32_t default_type = default_ast ? Z_TYPE(default_node.u.constant) : IS_UNDEF; + + uint32_t arg_type; + zend_bool is_class; op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; - arg_info->type = zend_compile_typename(type_ast, has_null_default); + arg_info->type = zend_compile_typename(type_ast, default_type == IS_NULL); + + is_class = ZEND_TYPE_IS_CLASS(arg_info->type); + arg_type = !is_class ? ZEND_TYPE_MASK(arg_info->type) : 0; - if (ZEND_TYPE_CODE(arg_info->type) == IS_VOID) { + if (arg_type & MAY_BE_VOID) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } - if (type_ast->kind == ZEND_AST_TYPE) { - if (ZEND_TYPE_CODE(arg_info->type) == IS_ARRAY) { - if (default_ast && !has_null_default - && Z_TYPE(default_node.u.constant) != IS_ARRAY - && 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_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_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"); - } else switch (ZEND_TYPE_CODE(arg_info->type)) { - case IS_DOUBLE: - if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " - "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 " - "with iterable type can only be an array or NULL"); - } - break; - - case IS_OBJECT: - 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 " - "with a %s type can only be %s or NULL", - zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)), zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type))); - } - break; - } - } + if (default_type > IS_NULL && default_type != IS_CONSTANT_AST + && !zend_is_valid_default_value(arg_info->type, &default_node.u.constant)) { + zend_string *type_str = zend_type_to_string(arg_info->type); + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use %s as default value for parameter $%s of type %s", + zend_get_type_by_const(default_type), + ZSTR_VAL(name), ZSTR_VAL(type_str)); } /* Allocate cache slot to speed-up run-time class resolution */ - if (opline->opcode == ZEND_RECV_INIT) { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->extended_value = zend_alloc_cache_slot(); - } - } else { - if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - opline->op2.num = op_array->cache_size; - op_array->cache_size += sizeof(void*); - } else { - opline->op2.num = -1; - } - } - } else { - if (opline->opcode != ZEND_RECV_INIT) { - opline->op2.num = -1; + if (is_class) { + opline->extended_value = zend_alloc_cache_slot(); } } } @@ -5678,18 +5669,30 @@ static void zend_compile_implicit_closure_uses(closure_info *info) ZEND_HASH_FOREACH_END(); } +static void zend_check_magic_method_attr(uint32_t attr, const char* method, zend_bool is_static) /* {{{ */ +{ + if (is_static) { + if (!(attr & ZEND_ACC_PUBLIC) || !(attr & ZEND_ACC_STATIC)) { + zend_error(E_WARNING, "The magic method %s() must have public visibility and be static", method); + } + } else if (!(attr & ZEND_ACC_PUBLIC) || (attr & ZEND_ACC_STATIC)) { + zend_error(E_WARNING, + "The magic method %s() must have public visibility and cannot be static", + method); + } +} +/* }}} */ + void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */ { zend_class_entry *ce = CG(active_class_entry); zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0; - zend_bool in_trait = (ce->ce_flags & ZEND_ACC_TRAIT) != 0; - zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0; - zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0; + uint32_t fn_flags = op_array->fn_flags; zend_string *lcname; if (in_interface) { - if (!is_public || (op_array->fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { + if (!(fn_flags & ZEND_ACC_PUBLIC) || (fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_ABSTRACT))) { zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method " "%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name)); } @@ -5724,134 +5727,48 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo ZSTR_VAL(ce->name), ZSTR_VAL(name)); } - if (in_interface) { - if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - /* pass */ - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - } - } else { - if (!in_trait && zend_string_equals_ci(lcname, ce->name)) { - if (!ce->constructor) { - ce->constructor = (zend_function *) op_array; - } - } else if (zend_string_equals_literal(lcname, "serialize")) { - ce->serialize_func = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, "unserialize")) { - ce->unserialize_func = (zend_function *) op_array; - } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { - if (!is_static) { - op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } - } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { - ce->constructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { - ce->destructor = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { - ce->clone = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __call() must have " - "public visibility and cannot be static"); - } - ce->__call = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { - if (!is_public || !is_static) { - zend_error(E_WARNING, "The magic method __callStatic() must have " - "public visibility and be static"); - } - ce->__callstatic = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __get() must have " - "public visibility and cannot be static"); - } - ce->__get = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __set() must have " - "public visibility and cannot be static"); - } - ce->__set = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __unset() must have " - "public visibility and cannot be static"); - } - ce->__unset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __isset() must have " - "public visibility and cannot be static"); - } - ce->__isset = (zend_function *) op_array; - ce->ce_flags |= ZEND_ACC_USE_GUARDS; - } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __toString() must have " - "public visibility and cannot be static"); - } - ce->__tostring = (zend_function *) op_array; - } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __invoke() must have " - "public visibility and cannot be static"); - } - } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { - if (!is_public || is_static) { - zend_error(E_WARNING, "The magic method __debugInfo() must have " - "public visibility and cannot be static"); - } - ce->__debugInfo = (zend_function *) op_array; - } else if (!is_static) { - op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; - } + if (zend_string_equals_literal(lcname, "serialize")) { + ce->serialize_func = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, "unserialize")) { + ce->unserialize_func = (zend_function *) op_array; + } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { + /* pass */ + } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { + ce->constructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { + ce->destructor = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) { + ce->clone = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__call", 0); + ce->__call = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__callStatic", 1); + ce->__callstatic = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__get", 0); + ce->__get = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__set", 0); + ce->__set = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__unset", 0); + ce->__unset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__isset", 0); + ce->__isset = (zend_function *) op_array; + ce->ce_flags |= ZEND_ACC_USE_GUARDS; + } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__toString", 0); + ce->__tostring = (zend_function *) op_array; + } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__invoke", 0); + } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) { + zend_check_magic_method_attr(fn_flags, "__debugInfo", 0); + ce->__debugInfo = (zend_function *) op_array; } zend_string_release_ex(lcname, 0); @@ -5860,7 +5777,6 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl, zend_bool toplevel) /* {{{ */ { - zend_ast *params_ast = decl->child[0]; zend_string *unqualified_name, *name, *lcname, *key; zend_op *opline; @@ -5877,18 +5793,14 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as } } - if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)) { - if (zend_ast_get_list(params_ast)->children != 1) { - zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", - ZEND_AUTOLOAD_FUNC_NAME); - } - - zend_error(E_DEPRECATED, "__autoload() is deprecated, use spl_autoload_register() instead"); + if (zend_string_equals_literal(lcname, "__autoload")) { + zend_error_noreturn(E_COMPILE_ERROR, + "__autoload() is no longer supported, use spl_autoload_register() instead"); } if (zend_string_equals_literal_ci(unqualified_name, "assert")) { - zend_error(E_DEPRECATED, - "Defining a custom assert() function is deprecated, " + zend_error(E_COMPILE_ERROR, + "Defining a custom assert() function is not allowed, " "as the function has special semantics"); } @@ -6057,17 +5969,17 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast)); zend_string *doc_comment = NULL; zval value_zv; - zend_type type = 0; + zend_type type = ZEND_TYPE_ENCODE_NONE(); if (type_ast) { type = zend_compile_typename(type_ast, 0); - if (ZEND_TYPE_CODE(type) == IS_VOID || ZEND_TYPE_CODE(type) == IS_CALLABLE) { + if (ZEND_TYPE_IS_MASK(type) + && (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE))) { + zend_string *str = zend_type_to_string(type); zend_error_noreturn(E_COMPILE_ERROR, "Property %s::$%s cannot have type %s", - ZSTR_VAL(ce->name), - ZSTR_VAL(name), - zend_get_type_by_const(ZEND_TYPE_CODE(type))); + ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str)); } } @@ -6090,35 +6002,19 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) / if (value_ast) { zend_const_expr_to_zval(&value_zv, value_ast); - if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv)) { + if (ZEND_TYPE_IS_SET(type) && !Z_CONSTANT(value_zv) + && !zend_is_valid_default_value(type, &value_zv)) { + zend_string *str = zend_type_to_string(type); if (Z_TYPE(value_zv) == IS_NULL) { - if (!ZEND_TYPE_ALLOW_NULL(type)) { - const char *name = ZEND_TYPE_IS_CLASS(type) - ? ZSTR_VAL(ZEND_TYPE_NAME(type)) : zend_get_type_by_const(ZEND_TYPE_CODE(type)); - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s may not be null. " - "Use the nullable type ?%s to allow null default value", - name, name); - } - } else if (ZEND_TYPE_IS_CLASS(type)) { zend_error_noreturn(E_COMPILE_ERROR, - "Property of type %s may not have default value", ZSTR_VAL(ZEND_TYPE_NAME(type))); - } else if (ZEND_TYPE_CODE(type) == IS_ARRAY || ZEND_TYPE_CODE(type) == IS_ITERABLE) { - if (Z_TYPE(value_zv) != IS_ARRAY) { - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s can only be an array", - zend_get_type_by_const(ZEND_TYPE_CODE(type))); - } - } else if (ZEND_TYPE_CODE(type) == IS_DOUBLE) { - if (Z_TYPE(value_zv) != IS_DOUBLE && Z_TYPE(value_zv) != IS_LONG) { - zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type float can only be float or int"); - } - } else if (!ZEND_SAME_FAKE_TYPE(ZEND_TYPE_CODE(type), Z_TYPE(value_zv))) { + "Default value for property of type %s may not be null. " + "Use the nullable type ?%s to allow null default value", + ZSTR_VAL(str), ZSTR_VAL(str)); + } else { zend_error_noreturn(E_COMPILE_ERROR, - "Default value for property of type %s can only be %s", - zend_get_type_by_const(ZEND_TYPE_CODE(type)), - zend_get_type_by_const(ZEND_TYPE_CODE(type))); + "Cannot use %s as default value for property %s::$%s of type %s", + zend_get_type_by_const(Z_TYPE(value_zv)), + ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(str)); } } } else if (!ZEND_TYPE_IS_SET(type)) { @@ -6141,6 +6037,18 @@ void zend_compile_prop_group(zend_ast *list) /* {{{ */ } /* }}} */ +static void zend_check_const_and_trait_alias_attr(uint32_t attr, const char* entity) /* {{{ */ +{ + if (attr & ZEND_ACC_STATIC) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as %s modifier", entity); + } else if (attr & ZEND_ACC_ABSTRACT) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as %s modifier", entity); + } else if (attr & ZEND_ACC_FINAL) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as %s modifier", entity); + } +} +/* }}} */ + void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ { zend_ast_list *list = zend_ast_get_list(ast); @@ -6162,13 +6070,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zval value_zv; if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { - if (ast->attr & ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier"); - } else if (ast->attr & ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier"); - } else if (ast->attr & ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier"); - } + zend_check_const_and_trait_alias_attr(ast->attr, "constant"); } zend_const_expr_to_zval(&value_zv, value_ast); @@ -6220,13 +6122,7 @@ static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */ zend_trait_alias *alias; - if (modifiers == ZEND_ACC_STATIC) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier"); - } else if (modifiers == ZEND_ACC_ABSTRACT) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier"); - } else if (modifiers == ZEND_ACC_FINAL) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier"); - } + zend_check_const_and_trait_alias_attr(modifiers, "method"); alias = emalloc(sizeof(zend_trait_alias)); zend_compile_method_ref(method_ref_ast, &alias->trait_method); @@ -6429,11 +6325,6 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ /* Reset lineno for final opcodes and errors */ CG(zend_lineno) = ast->lineno; - if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) { - /* For traits this check is delayed until after trait binding */ - zend_check_deprecated_constructor(ce); - } - if (ce->constructor) { ce->constructor->common.fn_flags |= ZEND_ACC_CTOR; if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) { @@ -6502,13 +6393,11 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } 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 NULL; - } + } 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 NULL; } } @@ -6677,10 +6566,8 @@ void zend_compile_use(zend_ast *ast) /* {{{ */ } zend_string_efree(ns_name); - } else { - if (zend_have_seen_symbol(lookup_name, type)) { - zend_check_already_in_use(type, old_name, new_name, lookup_name); - } + } else if (zend_have_seen_symbol(lookup_name, type)) { + zend_check_already_in_use(type, old_name, new_name, lookup_name); } zend_string_addref(old_name); @@ -6733,7 +6620,7 @@ void zend_compile_const_decl(zend_ast *ast) /* {{{ */ value_node.op_type = IS_CONST; zend_const_expr_to_zval(value_zv, value_ast); - if (zend_lookup_reserved_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) { + if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name)); } @@ -7146,12 +7033,10 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type"); break; } - } else { - if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { - zval_ptr_dtor_nogc(value); - zval_ptr_dtor(result); - return 0; - } + } else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) { + zval_ptr_dtor_nogc(value); + zval_ptr_dtor(result); + return 0; } } @@ -7165,16 +7050,6 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */ zend_ast *right_ast = ast->child[1]; uint32_t opcode = ast->attr; - if ((opcode == ZEND_ADD || opcode == ZEND_SUB) && left_ast->kind == ZEND_AST_BINARY_OP && left_ast->attr == ZEND_CONCAT) { - zend_error(E_DEPRECATED, "The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence"); - } - if ((opcode == ZEND_SL || opcode == ZEND_SR) && ((left_ast->kind == ZEND_AST_BINARY_OP && left_ast->attr == ZEND_CONCAT) || (right_ast->kind == ZEND_AST_BINARY_OP && right_ast->attr == ZEND_CONCAT))) { - zend_error(E_DEPRECATED, "The behavior of unparenthesized expressions containing both '.' and '>>'/'<<' will change in PHP 8: '<<'/'>>' will take a higher precedence"); - } - if (opcode == ZEND_PARENTHESIZED_CONCAT) { - opcode = ZEND_CONCAT; - } - znode left_node, right_node; zend_compile_expr(&left_node, left_ast); zend_compile_expr(&right_node, right_ast); @@ -7297,12 +7172,11 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); - if (expr_node.op_type == IS_CONST) { - if (zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { - result->op_type = IS_CONST; - zval_ptr_dtor(&expr_node.u.constant); - return; - } + if (expr_node.op_type == IS_CONST + && zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { + result->op_type = IS_CONST; + zval_ptr_dtor(&expr_node.u.constant); + return; } lefthand_node.op_type = IS_CONST; @@ -7425,7 +7299,7 @@ void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */ opline->extended_value = ast->attr; if (ast->attr == IS_NULL) { - zend_error(E_DEPRECATED, "The (unset) cast is deprecated"); + zend_error(E_COMPILE_ERROR, "The (unset) cast is no longer supported"); } } /* }}} */ @@ -7970,19 +7844,13 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */ opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL); opline->op2_type = IS_CONST; - if (is_fully_qualified) { + if (is_fully_qualified || !FC(current_namespace)) { opline->op2.constant = zend_add_const_name_literal( resolved_name, 0); } else { - opline->op1.num = IS_CONSTANT_UNQUALIFIED; - if (FC(current_namespace)) { - opline->op1.num |= IS_CONSTANT_IN_NAMESPACE; - opline->op2.constant = zend_add_const_name_literal( - resolved_name, 1); - } else { - opline->op2.constant = zend_add_const_name_literal( - resolved_name, 0); - } + opline->op1.num = IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE; + opline->op2.constant = zend_add_const_name_literal( + resolved_name, 1); } opline->extended_value = zend_alloc_cache_slot(); } @@ -8313,7 +8181,8 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */ } zend_ast_destroy(ast); - *ast_ptr = zend_ast_create_constant(resolved_name, !is_fully_qualified ? IS_CONSTANT_UNQUALIFIED : 0); + *ast_ptr = zend_ast_create_constant(resolved_name, + !is_fully_qualified && FC(current_namespace) ? IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE : 0); } /* }}} */ @@ -8762,11 +8631,10 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ int i; for (i = 0; i <= 1; i++) { zend_eval_const_expr(&ast->child[i]); - if (ast->child[i]->kind == ZEND_AST_ZVAL) { - if (zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) { - ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); - return; - } + if (ast->child[i]->kind == ZEND_AST_ZVAL + && zend_is_true(zend_ast_get_zval(ast->child[i])) == (ast->kind == ZEND_AST_OR)) { + ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); + return; } } |
