diff --git a/Zend/zend.c b/Zend/zend.c index 4ad04f3876385..ceb46f28725ff 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -594,10 +594,7 @@ static void function_copy_ctor(zval *zv) /* {{{ */ for (i = 0 ; i < num_args; i++) { if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1); - - new_arg_info[i].type = - ZEND_TYPE_ENCODE_CLASS( - name, ZEND_TYPE_ALLOW_NULL(arg_info[i].type)); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, name); } } func->common.arg_info = new_arg_info + 1; @@ -968,7 +965,7 @@ static void zend_resolve_property_types(void) /* {{{ */ zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name); ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS); - prop_info->type = ZEND_TYPE_ENCODE_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type)); + prop_info->type = (zend_type) ZEND_TYPE_INIT_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type), 0); zend_string_release(lc_type_name); zend_string_release(type_name); } diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 34fcf1506a2cb..72144cb183d75 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2052,21 +2052,17 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } else { internal_function->required_num_args = info->required_num_args; } - if (info->return_reference) { + if (ZEND_ARG_SEND_MODE(info)) { internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE; } - if (ptr->arg_info[ptr->num_args].is_variadic) { + if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) { internal_function->fn_flags |= ZEND_ACC_VARIADIC; /* Don't count the variadic argument */ internal_function->num_args--; } if (ZEND_TYPE_IS_SET(info->type)) { if (ZEND_TYPE_IS_CLASS(info->type)) { - const char *type_name = (const char*)info->type; - - if (type_name[0] == '?') { - type_name++; - } + const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type); if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) { zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name); } @@ -2147,16 +2143,9 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio reg_function->common.arg_info = new_arg_info + 1; for (i = 0; i < num_args; i++) { if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) { - const char *class_name = (const char*)new_arg_info[i].type; - zend_bool allow_null = 0; - zend_string *str; - - if (class_name[0] == '?') { - class_name++; - allow_null = 1; - } - str = zend_string_init_interned(class_name, strlen(class_name), 1); - new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null); + const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, + zend_string_init_interned(class_name, strlen(class_name), 1)); } } } @@ -3719,7 +3708,7 @@ ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, ze ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */ { - return zend_declare_typed_property(ce, name, property, access_type, doc_comment, ZEND_TYPE_ENCODE_NONE()); + return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0)); } /* }}} */ diff --git a/Zend/zend_API.h b/Zend/zend_API.h index acc6bb9cf3718..fb3c6566d7f52 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -96,34 +96,45 @@ typedef struct _zend_fcall_info_cache { #define ZEND_FE_END { NULL, NULL, NULL, 0, 0 } -#define ZEND_ARG_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 0}, -#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, pass_by_ref, 0}, -#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(type_hint, allow_null), pass_by_ref, 0 }, -#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 1 }, -#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(type_hint, allow_null), pass_by_ref, 1 }, -#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_ENCODE_CLASS_CONST(#classname, allow_null), pass_by_ref, 1 }, +#define _ZEND_ARG_INFO_FLAGS(pass_by_ref, is_variadic) \ + (((pass_by_ref) << _ZEND_SEND_MODE_SHIFT) | ((is_variadic) ? _ZEND_IS_VARIADIC_BIT : 0)) + +#define ZEND_ARG_INFO(pass_by_ref, name) \ + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 0))}, +#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 0)) }, +#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) \ + { #name, ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, +#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) \ + { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, +#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) \ + { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null, _ZEND_ARG_INFO_FLAGS(pass_by_ref, 1)) }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CLASS_CONST(#class_name, allow_null), return_reference, 0 }, + { (const char*)(zend_uintptr_t)(required_num_args), \ + ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, #define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null) #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CODE(type, allow_null), return_reference, 0 }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null, _ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null) #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \ static const zend_internal_arg_info name[] = { \ - { (const char*)(zend_uintptr_t)(required_num_args), 0, return_reference, 0 }, + { (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(return_reference, 0)) }, #define ZEND_BEGIN_ARG_INFO(name, _unused) \ - ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1) + ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1) #define ZEND_END_ARG_INFO() }; /* Name macros */ diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 68e698b626222..ac9a41b54b49c 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -547,16 +547,16 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) if (arg_info->name) { if (zstr_args) { name = zend_strpprintf(0, "%s$%s", - arg_info->pass_by_reference ? "&" : "", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", ZSTR_VAL(arg_info->name)); } else { name = zend_strpprintf(0, "%s$%s", - arg_info->pass_by_reference ? "&" : "", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", ((zend_internal_arg_info*)arg_info)->name); } } else { name = zend_strpprintf(0, "%s$param%d", - arg_info->pass_by_reference ? "&" : "", + ZEND_ARG_SEND_MODE(arg_info) ? "&" : "", i + 1); } ZVAL_NEW_STR(&info, zend_strpprintf(0, "%s", i >= required ? "" : "")); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 9f499baf6faea..10dd0fe9c45b8 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1096,7 +1096,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop } 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)); + uint32_t type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type); switch (type_mask) { case MAY_BE_FALSE|MAY_BE_TRUE: str = ZSTR_KNOWN(ZEND_STR_BOOL); @@ -1160,7 +1160,7 @@ static void zend_mark_function_as_generator() /* {{{ */ || 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; + valid_type = (ZEND_TYPE_FULL_MASK(return_info.type) & MAY_BE_ITERABLE) != 0; } if (!valid_type) { @@ -2123,7 +2123,7 @@ static void zend_emit_return_type_check( zend_op *opline; /* `return ...;` is illegal in a void function (but `return;` isn't) */ - if (ZEND_TYPE_IS_MASK(type) && ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) { + if (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, @@ -2149,8 +2149,7 @@ static void zend_emit_return_type_check( } if (expr && expr->op_type == IS_CONST) { - if (ZEND_TYPE_IS_MASK(type) - && ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) { + if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) { /* we don't need run-time check */ return; } @@ -5289,11 +5288,11 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */ n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM); i = 0; while (i < n) { - ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference); + ZEND_SET_ARG_FLAG(func, i + 1, ZEND_ARG_SEND_MODE(&func->common.arg_info[i])); i++; } - if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && func->common.arg_info[i].pass_by_reference)) { - uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference; + if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && ZEND_ARG_SEND_MODE(&func->common.arg_info[i]))) { + uint32_t pass_by_reference = ZEND_ARG_SEND_MODE(&func->common.arg_info[i]); while (i < MAX_ARG_FLAG_NUM) { ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference); i++; @@ -5312,7 +5311,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_CODE(ast->attr, allow_null); + return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, allow_null, 0); } else { zend_string *class_name = zend_ast_get_str(ast); zend_uchar type = zend_lookup_builtin_type_by_name(class_name); @@ -5326,7 +5325,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_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); + return (zend_type) ZEND_TYPE_INIT_CODE(type, allow_null, 0); } else { uint32_t fetch_type = zend_get_class_fetch_type_ast(ast); if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { @@ -5337,7 +5336,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null zend_string_addref(class_name); } - return ZEND_TYPE_ENCODE_CLASS(class_name, allow_null); + return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null, 0); } } } @@ -5356,11 +5355,11 @@ static zend_bool zend_is_valid_default_value(zend_type type, zval *value) 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) { + if ((ZEND_TYPE_FULL_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) { + if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_ITERABLE) && Z_TYPE_P(value) == IS_ARRAY) { return 1; } return 0; @@ -5377,9 +5376,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ /* Use op_array->arg_info[-1] for return type */ arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0); arg_infos->name = NULL; - 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); + ZEND_TYPE_FULL_MASK(arg_infos->type) |= _ZEND_ARG_INFO_FLAGS( + (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0, /* is_variadic */ 0); arg_infos++; op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE; } else { @@ -5451,23 +5450,18 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ arg_info = &arg_infos[i]; arg_info->name = zend_string_copy(name); - arg_info->pass_by_reference = is_ref; - arg_info->is_variadic = is_variadic; - arg_info->type = ZEND_TYPE_ENCODE_NONE(); + arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE(0); if (type_ast) { 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, 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 (arg_type & MAY_BE_VOID) { + if (!is_class && (ZEND_TYPE_FULL_MASK(arg_info->type) & MAY_BE_VOID)) { zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type"); } @@ -5485,6 +5479,8 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */ opline->extended_value = zend_alloc_cache_slot(); } } + + ZEND_TYPE_FULL_MASK(arg_info->type) |= _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic); } /* These are assigned at the end to avoid uninitialized memory in case of an error */ @@ -5984,13 +5980,12 @@ 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 = ZEND_TYPE_ENCODE_NONE(); + zend_type type = ZEND_TYPE_INIT_NONE(0); if (type_ast) { type = zend_compile_typename(type_ast, 0); - if (ZEND_TYPE_IS_MASK(type) - && (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE))) { + if (ZEND_TYPE_FULL_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", diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index c4c2b8bac7a0c..648a573454419 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -383,16 +383,12 @@ typedef struct _zend_class_constant { typedef struct _zend_internal_arg_info { const char *name; zend_type type; - zend_uchar pass_by_reference; - zend_bool is_variadic; } zend_internal_arg_info; /* arg_info for user functions */ typedef struct _zend_arg_info { zend_string *name; zend_type type; - zend_uchar pass_by_reference; - zend_bool is_variadic; } zend_arg_info; /* the following structure repeats the layout of zend_internal_arg_info, @@ -403,8 +399,6 @@ typedef struct _zend_arg_info { typedef struct _zend_internal_function_info { zend_uintptr_t required_num_args; zend_type type; - zend_bool return_reference; - zend_bool _is_variadic; } zend_internal_function_info; struct _zend_op_array { @@ -931,6 +925,14 @@ zend_string *zend_type_to_string(zend_type type); #define ZEND_SEND_BY_REF 1u #define ZEND_SEND_PREFER_REF 2u +/* The send mode and is_variadic flag are stored as part of zend_type */ +#define _ZEND_SEND_MODE_SHIFT _ZEND_TYPE_EXTRA_FLAGS_SHIFT +#define _ZEND_IS_VARIADIC_BIT (1 << (_ZEND_TYPE_EXTRA_FLAGS_SHIFT + 2)) +#define ZEND_ARG_SEND_MODE(arg_info) \ + ((ZEND_TYPE_FULL_MASK((arg_info)->type) >> _ZEND_SEND_MODE_SHIFT) & 3) +#define ZEND_ARG_IS_VARIADIC(arg_info) \ + ((ZEND_TYPE_FULL_MASK((arg_info)->type) & _ZEND_IS_VARIADIC_BIT) != 0) + #define ZEND_DIM_IS (1 << 0) /* isset fetch needed for null coalesce */ #define ZEND_DIM_ALTERNATIVE_SYNTAX (1 << 1) /* deprecated curly brace usage */ @@ -947,7 +949,7 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, } arg_num = zf->common.num_args; } - return UNEXPECTED((zf->common.arg_info[arg_num].pass_by_reference & mask) != 0); + return UNEXPECTED((ZEND_ARG_SEND_MODE(&zf->common.arg_info[arg_num]) & mask) != 0); } #define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 2c7b9f50307e1..89e3e1e70624c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -711,8 +711,8 @@ static ZEND_COLD void zend_verify_type_error_common( *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)); } } else { - zend_type type = ZEND_TYPE_WITHOUT_NULL(arg_info->type); - switch (ZEND_TYPE_MASK(type)) { + uint32_t type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(arg_info->type); + switch (type_mask) { case MAY_BE_OBJECT: *need_msg = "be an "; *need_kind = "object"; @@ -726,11 +726,15 @@ static ZEND_COLD void zend_verify_type_error_common( *need_kind = ""; break; default: + { /* TODO: The zend_type_to_string() result is guaranteed interned here. * It would be beter to switch all this code to use zend_string though. */ + zend_type type = arg_info->type; + ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL; *need_msg = "be of the type "; *need_kind = ZSTR_VAL(zend_type_to_string(type)); break; + } } } @@ -933,7 +937,7 @@ static zend_bool zend_resolve_class_type(zend_type *type, zend_class_entry *self } zend_string_release(name); - *type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type)); + *type = (zend_type) ZEND_TYPE_INIT_CE(ce, ZEND_TYPE_ALLOW_NULL(*type), 0); return 1; } @@ -953,13 +957,13 @@ static zend_always_inline zend_bool i_zend_check_property_type(zend_property_inf return instanceof_function(Z_OBJCE_P(property), ZEND_TYPE_CE(info->type)); } - ZEND_ASSERT(!(ZEND_TYPE_MASK(info->type) & MAY_BE_CALLABLE)); + ZEND_ASSERT(!(ZEND_TYPE_FULL_MASK(info->type) & MAY_BE_CALLABLE)); if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(info->type, Z_TYPE_P(property)))) { return 1; - } else if (ZEND_TYPE_MASK(info->type) & MAY_BE_ITERABLE) { + } else if (ZEND_TYPE_FULL_MASK(info->type) & MAY_BE_ITERABLE) { return zend_is_iterable(property); } else { - return zend_verify_scalar_type_hint(ZEND_TYPE_MASK(info->type), property, strict, 0); + return zend_verify_scalar_type_hint(ZEND_TYPE_FULL_MASK(info->type), property, strict, 0); } } @@ -1029,7 +1033,7 @@ static zend_always_inline zend_bool zend_check_type( return 1; } - type_mask = ZEND_TYPE_MASK(type); + type_mask = ZEND_TYPE_FULL_MASK(type); if (type_mask & MAY_BE_CALLABLE) { return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL); } else if (type_mask & MAY_BE_ITERABLE) { @@ -1193,7 +1197,7 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret) zend_class_entry *ce = NULL; void *dummy_cache_slot = NULL; - if (ZEND_TYPE_IS_MASK(ret_info->type) && (ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID)) { + if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) { if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) { zend_verify_void_return_error(zf, zend_zval_type_name(ret), ""); return 0; @@ -1225,8 +1229,7 @@ static ZEND_COLD int zend_verify_missing_return_type(const zend_function *zf, vo zend_arg_info *ret_info = zf->common.arg_info - 1; if (ZEND_TYPE_IS_SET(ret_info->type) - && (!ZEND_TYPE_IS_MASK(ret_info->type) - || !(ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID))) { + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID)) { zend_class_entry *ce = NULL; if (ZEND_TYPE_IS_CLASS(ret_info->type)) { if (EXPECTED(*cache_slot)) { @@ -1576,7 +1579,7 @@ static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *re { zend_property_info *prop; ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - if (!ZEND_TYPE_IS_MASK(prop->type) || !(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) { + if (!(ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_DOUBLE)) { return prop; } } ZEND_REF_FOREACH_TYPE_SOURCES_END(); @@ -2545,7 +2548,7 @@ static zend_always_inline zend_bool check_type_array_assignable(zend_type type) if (!ZEND_TYPE_IS_SET(type)) { return 1; } - return ZEND_TYPE_IS_MASK(type) && (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)); + return (ZEND_TYPE_FULL_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0; } static zend_always_inline zend_bool check_type_stdClass_assignable(zend_type type) { @@ -2559,7 +2562,7 @@ static zend_always_inline zend_bool check_type_stdClass_assignable(zend_type typ return zend_string_equals_literal_ci(ZEND_TYPE_NAME(type), "stdclass"); } } else { - return (ZEND_TYPE_MASK(type) & MAY_BE_OBJECT) != 0; + return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) != 0; } } @@ -3020,7 +3023,7 @@ static zend_always_inline int i_zend_verify_type_assignable_zval( return 1; } - type_mask = ZEND_TYPE_MASK(type); + type_mask = ZEND_TYPE_FULL_MASK(type); if (type_mask & MAY_BE_ITERABLE) { return zend_is_iterable(zv); } @@ -3074,9 +3077,9 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference if (!seen_prop) { seen_prop = prop; seen_type_mask = ZEND_TYPE_IS_CLASS(prop->type) - ? MAY_BE_OBJECT : ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type)); + ? MAY_BE_OBJECT : ZEND_TYPE_PURE_MASK_WITHOUT_NULL(prop->type); } else if (needs_coercion - && seen_type_mask != ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type))) { + && seen_type_mask != ZEND_TYPE_PURE_MASK_WITHOUT_NULL(prop->type)) { zend_throw_conflicting_coercion_error(seen_prop, prop, zv); return 0; } @@ -3143,13 +3146,13 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert if (result < 0) { zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val)); - if (ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop_info->type)) - != ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(ref_prop->type))) { + if (ZEND_TYPE_PURE_MASK_WITHOUT_NULL(prop_info->type) + != ZEND_TYPE_PURE_MASK_WITHOUT_NULL(ref_prop->type)) { /* Invalid due to conflicting coercion */ zend_throw_ref_type_error_type(ref_prop, prop_info, val); return 0; } - if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_MASK(prop_info->type), val)) { + if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop_info->type), val)) { return 1; } } diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index b0e35a9552fb9..2cf9f22fd7ffd 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -348,7 +348,7 @@ static inheritance_status zend_perform_covariant_type_check( } return unlinked_instanceof(fe_ce, proto_ce) ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; - } else if (ZEND_TYPE_MASK(proto_type) & MAY_BE_ITERABLE) { + } else if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_ITERABLE) { if (ZEND_TYPE_IS_CLASS(fe_type)) { zend_string *fe_class_name = resolve_class_name(fe, ZEND_TYPE_NAME(fe_type)); zend_class_entry *fe_ce = lookup_class(fe, fe_class_name); @@ -360,9 +360,9 @@ static inheritance_status zend_perform_covariant_type_check( ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } - return ZEND_TYPE_MASK(fe_type) & (MAY_BE_ARRAY|MAY_BE_ITERABLE) + return ZEND_TYPE_FULL_MASK(fe_type) & (MAY_BE_ARRAY|MAY_BE_ITERABLE) ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; - } else if (ZEND_TYPE_MASK(proto_type) & MAY_BE_OBJECT) { + } else if (ZEND_TYPE_FULL_MASK(proto_type) & MAY_BE_OBJECT) { if (ZEND_TYPE_IS_CLASS(fe_type)) { /* Currently, any class name would be allowed here. We still perform a class lookup * for forward-compatibility reasons, as we may have named types in the future that @@ -376,10 +376,10 @@ static inheritance_status zend_perform_covariant_type_check( return INHERITANCE_SUCCESS; } - return ZEND_TYPE_MASK(fe_type) & MAY_BE_OBJECT ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; + return ZEND_TYPE_FULL_MASK(fe_type) & MAY_BE_OBJECT + ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } else { - return ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(fe_type)) - == ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(proto_type)) + return ZEND_TYPE_PURE_MASK_WITHOUT_NULL(fe_type) == ZEND_TYPE_PURE_MASK_WITHOUT_NULL(proto_type) ? INHERITANCE_SUCCESS : INHERITANCE_ERROR; } } @@ -486,7 +486,7 @@ static inheritance_status zend_do_perform_implementation_check( } /* by-ref constraints on arguments are invariant */ - if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(fe_arg_info) != ZEND_ARG_SEND_MODE(proto_arg_info)) { return INHERITANCE_ERROR; } } @@ -557,11 +557,11 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function for (i = 0; i < num_args;) { zend_append_type_hint(&str, fptr, arg_info, 0); - if (arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(arg_info)) { smart_str_appendc(&str, '&'); } - if (arg_info->is_variadic) { + if (ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(&str, "..."); } @@ -578,7 +578,7 @@ static ZEND_COLD zend_string *zend_get_function_declaration(const zend_function smart_str_append_unsigned(&str, i); } - if (i >= required && !arg_info->is_variadic) { + if (i >= required && !ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(&str, " = "); if (fptr->type == ZEND_USER_FUNCTION) { zend_op *precv = NULL; @@ -859,7 +859,8 @@ zend_string* zend_resolve_property_type(zend_string *type, zend_class_entry *sco zend_bool property_types_compatible(zend_property_info *parent_info, zend_property_info *child_info) { zend_string *parent_name, *child_name; zend_class_entry *parent_type_ce, *child_type_ce; - if (parent_info->type == child_info->type) { + if (ZEND_TYPE_PURE_MASK(parent_info->type) == ZEND_TYPE_PURE_MASK(child_info->type) + && ZEND_TYPE_NAME(parent_info->type) == ZEND_TYPE_NAME(child_info->type)) { return 1; } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 8d2726a14c551..26d3470d733d8 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -106,87 +106,106 @@ typedef void (*copy_ctor_func_t)(zval *pElement); * It shouldn't be used directly. Only through ZEND_TYPE_* macros. * * ZEND_TYPE_IS_SET() - checks if type-hint exists - * ZEND_TYPE_IS_MASK() - checks if type-hint refer to standard type + * ZEND_TYPE_IS_ONLY_MASK() - checks if type-hint refer to standard type * ZEND_TYPE_IS_CLASS() - checks if type-hint refer to some class * ZEND_TYPE_IS_CE() - checks if type-hint refer to some class by zend_class_entry * * ZEND_TYPE_IS_NAME() - checks if type-hint refer to some class by zend_string * * * ZEND_TYPE_NAME() - returns referenced class name * ZEND_TYPE_CE() - returns referenced class entry - * ZEND_TYPE_MASK() - returns MAY_BE_* type mask + * ZEND_TYPE_PURE_MASK() - returns MAY_BE_* type mask + * ZEND_TYPE_FULL_MASK() - returns MAY_BE_* type mask together with other flags * * ZEND_TYPE_ALLOW_NULL() - checks if NULL is allowed * - * ZEND_TYPE_ENCODE_*() should be used for construction. + * ZEND_TYPE_INIT_*() should be used for construction. */ -typedef uintptr_t zend_type; - -#define _ZEND_TYPE_CODE_MAX ((Z_L(1)<<(IS_VOID+1))-1) -#define _ZEND_TYPE_FLAG_MASK Z_L(0x3) -#define _ZEND_TYPE_CE_BIT Z_L(0x1) +typedef struct { + /* Not using a union here, because there's no good way to initialize them + * in a way that is supported in both C and C++ (designated initializers + * are only supported since C++20). */ + void *ptr; + uint32_t type_mask; + /* TODO: We could use the extra 32-bit of padding on 64-bit systems. */ +} zend_type; + +#define _ZEND_TYPE_EXTRA_FLAGS_SHIFT 24 +#define _ZEND_TYPE_MASK ((1u << 24) - 1) +#define _ZEND_TYPE_MAY_BE_MASK ((1u << (IS_VOID+1)) - 1) +#define _ZEND_TYPE_CE_BIT (1u << 22) +#define _ZEND_TYPE_NAME_BIT (1u << 23) /* Must have same value as MAY_BE_NULL */ -#define _ZEND_TYPE_NULLABLE_BIT Z_L(0x2) +#define _ZEND_TYPE_NULLABLE_BIT 0x2 #define ZEND_TYPE_IS_SET(t) \ - ((t) != 0) - -#define ZEND_TYPE_IS_MASK(t) \ - ((t) != 0 && (t) <= _ZEND_TYPE_CODE_MAX) + (((t).type_mask & _ZEND_TYPE_MASK) != 0) #define ZEND_TYPE_IS_CLASS(t) \ - ((t) > _ZEND_TYPE_CODE_MAX) + (((t.type_mask) & (_ZEND_TYPE_NAME_BIT|_ZEND_TYPE_CE_BIT)) != 0) #define ZEND_TYPE_IS_CE(t) \ - (((t) & _ZEND_TYPE_CE_BIT) != 0) + (((t.type_mask) & _ZEND_TYPE_CE_BIT) != 0) #define ZEND_TYPE_IS_NAME(t) \ - (ZEND_TYPE_IS_CLASS(t) && !ZEND_TYPE_IS_CE(t)) + (((t.type_mask) & _ZEND_TYPE_NAME_BIT) != 0) + +#define ZEND_TYPE_IS_ONLY_MASK(t) \ + (ZEND_TYPE_IS_SET(t) && (t).ptr == NULL) #define ZEND_TYPE_NAME(t) \ - ((zend_string*)((t) & ~_ZEND_TYPE_FLAG_MASK)) + ((zend_string *) (t).ptr) + +#define ZEND_TYPE_LITERAL_NAME(t) \ + ((const char *) (t).ptr) #define ZEND_TYPE_CE(t) \ - ((zend_class_entry*)((t) & ~_ZEND_TYPE_FLAG_MASK)) + ((zend_class_entry *) (t).ptr) -#define ZEND_TYPE_MASK(t) \ - (t) +#define ZEND_TYPE_SET_PTR(t, _ptr) \ + ((t).ptr = (_ptr)) + +/* FULL_MASK() includes the MAY_BE_* type mask, the CE/NAME bits, as well as extra reserved bits. + * The PURE_MASK() only includes the MAY_BE_* type mask. */ +#define ZEND_TYPE_FULL_MASK(t) \ + ((t).type_mask) + +#define ZEND_TYPE_PURE_MASK(t) \ + ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK) + +#define ZEND_TYPE_FULL_MASK_WITHOUT_NULL(t) \ + ((t).type_mask & ~_ZEND_TYPE_NULLABLE_BIT) + +#define ZEND_TYPE_PURE_MASK_WITHOUT_NULL(t) \ + ((t).type_mask & _ZEND_TYPE_MAY_BE_MASK & ~_ZEND_TYPE_NULLABLE_BIT) #define ZEND_TYPE_CONTAINS_CODE(t, code) \ - (((t) & (1 << (code))) != 0) + (((t).type_mask & (1u << (code))) != 0) #define ZEND_TYPE_ALLOW_NULL(t) \ - (((t) & _ZEND_TYPE_NULLABLE_BIT) != 0) - -#define ZEND_TYPE_WITHOUT_NULL(t) \ - ((t) & ~_ZEND_TYPE_NULLABLE_BIT) + (((t).type_mask & _ZEND_TYPE_NULLABLE_BIT) != 0) -#define ZEND_TYPE_ENCODE_NONE() \ - (0) +#define ZEND_TYPE_INIT_NONE(extra_flags) \ + { NULL, (extra_flags) } -#define ZEND_TYPE_ENCODE_MASK(maybe_code) \ - (maybe_code) +#define ZEND_TYPE_INIT_MASK(_type_mask) \ + { NULL, (_type_mask) } -#define ZEND_TYPE_ENCODE_CODE(code, allow_null) \ - (((code) == _IS_BOOL ? (MAY_BE_FALSE|MAY_BE_TRUE) : (1 << (code))) \ - | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0))) +#define ZEND_TYPE_INIT_CODE(code, allow_null, extra_flags) \ + ZEND_TYPE_INIT_MASK(((code) == _IS_BOOL ? (MAY_BE_FALSE|MAY_BE_TRUE) : (1 << (code))) \ + | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags)) -#define ZEND_TYPE_ENCODE_CE(ce, allow_null) \ - (((uintptr_t)(ce)) | _ZEND_TYPE_CE_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0))) +#define ZEND_TYPE_INIT_CE(_ce, allow_null, extra_flags) \ + { (void *) (_ce), \ + _ZEND_TYPE_CE_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } -#define ZEND_TYPE_ENCODE_CLASS(class_name, allow_null) \ - (((uintptr_t)(class_name)) | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : Z_L(0x0))) +#define ZEND_TYPE_INIT_CLASS(class_name, allow_null, extra_flags) \ + { (void *) (class_name), \ + _ZEND_TYPE_NAME_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } -#define ZEND_TYPE_ENCODE_CLASS_CONST_0(class_name) \ - ((zend_type) class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_1(class_name) \ - ((zend_type) "?" class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_Q2(macro, class_name) \ - macro(class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) \ - ZEND_TYPE_ENCODE_CLASS_CONST_Q2(ZEND_TYPE_ENCODE_CLASS_CONST_ ##allow_null, class_name) -#define ZEND_TYPE_ENCODE_CLASS_CONST(class_name, allow_null) \ - ZEND_TYPE_ENCODE_CLASS_CONST_Q1(allow_null, class_name) +#define ZEND_TYPE_INIT_CLASS_CONST(class_name, allow_null, extra_flags) \ + { (void *) (class_name), \ + _ZEND_TYPE_NAME_BIT | ((allow_null) ? _ZEND_TYPE_NULLABLE_BIT : 0) | (extra_flags) } typedef union _zend_value { zend_long lval; /* long value */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 3b059f392029c..2d1f2b694acb0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4278,7 +4278,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV } if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && !(ZEND_TYPE_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)) && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) && retval_ref != retval_ptr) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 34a1a1b96e581..58b702d86b38b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -9079,7 +9079,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && !(ZEND_TYPE_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)) && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) && retval_ref != retval_ptr) @@ -19481,7 +19481,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && !(ZEND_TYPE_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)) && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) && retval_ref != retval_ptr) @@ -27502,7 +27502,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && !(ZEND_TYPE_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)) && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) && retval_ref != retval_ptr) @@ -34607,7 +34607,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && !(ZEND_TYPE_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)) && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) && retval_ref != retval_ptr) @@ -46711,7 +46711,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } if (UNEXPECTED(!ZEND_TYPE_IS_CLASS(ret_info->type) - && !(ZEND_TYPE_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) + && !(ZEND_TYPE_FULL_MASK(ret_info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)) && !(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) && retval_ref != retval_ptr) diff --git a/ext/com_dotnet/com_com.c b/ext/com_dotnet/com_com.c index f9d88603c7bc4..e236337a5c004 100644 --- a/ext/com_dotnet/com_com.c +++ b/ext/com_dotnet/com_com.c @@ -498,7 +498,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_function * if (f->arg_info) { for (i = 0; i < nargs; i++) { - if (f->arg_info[nargs - i - 1].pass_by_reference) { + if (ZEND_ARG_SEND_MODE(&f->arg_info[nargs - i - 1])) { byref_count++; } } @@ -507,7 +507,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_function * if (byref_count) { byref_vals = (VARIANT*)safe_emalloc(sizeof(VARIANT), byref_count, 0); for (j = 0, i = 0; i < nargs; i++) { - if (f->arg_info[nargs - i - 1].pass_by_reference) { + if (ZEND_ARG_SEND_MODE(&f->arg_info[nargs - i - 1])) { /* put the value into byref_vals instead */ php_com_variant_from_zval(&byref_vals[j], &args[nargs - i - 1], obj->code_page); @@ -554,7 +554,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, zend_internal_function * if (f && f->arg_info) { for (i = 0, j = 0; i < nargs; i++) { /* if this was byref, update the zval */ - if (f->arg_info[nargs - i - 1].pass_by_reference) { + if (ZEND_ARG_SEND_MODE(&f->arg_info[nargs - i - 1])) { zval *arg = &args[nargs - i - 1]; ZVAL_DEREF(arg); diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index 092e65db57e64..f9a74820e0d99 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -319,10 +319,8 @@ static zend_function *com_method_get(zend_object **object_ptr, zend_string *name f.arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info)); for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) { - f.arg_info[i].type = ZEND_TYPE_ENCODE_NONE(); - if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) { - f.arg_info[i].pass_by_reference = ZEND_SEND_BY_REF; - } + zend_bool by_ref = (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) != 0; + f.arg_info[i].type = (zend_type) ZEND_TYPE_INIT_NONE(_ZEND_ARG_INFO_FLAGS(by_ref, 0)); } f.num_args = bindptr.lpfuncdesc->cParams; diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 5ea77759217c3..686832af085b5 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -324,8 +324,7 @@ static inline zend_bool can_elide_return_type_check( } /* These types are not represented exactly */ - if (ZEND_TYPE_IS_MASK(info->type) - && (ZEND_TYPE_MASK(info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE))) { + if (ZEND_TYPE_FULL_MASK(info->type) & (MAY_BE_CALLABLE|MAY_BE_ITERABLE)) { return 0; } diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index ae707a24097c0..1057a53716223 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -116,7 +116,7 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o for (i = 0; i < num_args; i++) { /* Don't inline functions with by-reference arguments. This would require * correct handling of INDIRECT arguments. */ - if (func->op_array.arg_info[i].pass_by_reference) { + if (ZEND_ARG_SEND_MODE(&func->op_array.arg_info[i])) { return; } } diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 2e308570136c8..c8552d2bdf3be 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -1420,21 +1420,19 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int } else if (op_array->arg_info && opline->op1.num <= op_array->num_args) { zend_type type = op_array->arg_info[opline->op1.num-1].type; - if (ZEND_TYPE_IS_MASK(type)) { - uint32_t mask = ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(type)); - if (mask == MAY_BE_LONG) { - tmp->underflow = 0; - tmp->min = ZEND_LONG_MIN; - tmp->max = ZEND_LONG_MAX; - tmp->overflow = 0; - return 1; - } else if (mask == (MAY_BE_FALSE|MAY_BE_TRUE)) { - tmp->underflow = 0; - tmp->min = 0; - tmp->max = 1; - tmp->overflow = 0; - return 1; - } + uint32_t mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(type); + if (mask == MAY_BE_LONG) { + tmp->underflow = 0; + tmp->min = ZEND_LONG_MIN; + tmp->max = ZEND_LONG_MAX; + tmp->overflow = 0; + return 1; + } else if (mask == (MAY_BE_FALSE|MAY_BE_TRUE)) { + tmp->underflow = 0; + tmp->min = 0; + tmp->max = 1; + tmp->overflow = 0; + return 1; } } } @@ -2237,42 +2235,36 @@ static inline zend_class_entry *get_class_entry(const zend_script *script, zend_ } static uint32_t zend_convert_type_declaration_mask(uint32_t type_mask) { + uint32_t result_mask = type_mask & MAY_BE_ANY; if (type_mask & MAY_BE_VOID) { - type_mask &= ~MAY_BE_VOID; - type_mask |= MAY_BE_NULL; + result_mask |= MAY_BE_NULL; } if (type_mask & MAY_BE_CALLABLE) { - type_mask &= ~MAY_BE_CALLABLE; - type_mask |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + result_mask |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; } if (type_mask & MAY_BE_ITERABLE) { - type_mask &= ~MAY_BE_ITERABLE; - type_mask |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + result_mask |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; } if (type_mask & MAY_BE_ARRAY) { - type_mask |= MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + result_mask |= MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; } - return type_mask; + return result_mask; } uint32_t zend_fetch_arg_info_type(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce) { - uint32_t tmp = 0; + uint32_t tmp; + if (!ZEND_TYPE_IS_SET(arg_info->type)) { + return MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_RC1|MAY_BE_RCN; + } + tmp = zend_convert_type_declaration_mask(ZEND_TYPE_PURE_MASK(arg_info->type)); *pce = NULL; if (ZEND_TYPE_IS_CLASS(arg_info->type)) { - // class type hinting... zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(arg_info->type)); tmp |= MAY_BE_OBJECT; *pce = get_class_entry(script, lcname); zend_string_release_ex(lcname, 0); - } else if (ZEND_TYPE_IS_MASK(arg_info->type)) { - tmp |= zend_convert_type_declaration_mask(ZEND_TYPE_MASK(arg_info->type)); - } else { - tmp |= MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; - } - if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) { - tmp |= MAY_BE_NULL; } if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) { tmp |= MAY_BE_RC1 | MAY_BE_RCN; @@ -2371,7 +2363,7 @@ static uint32_t zend_fetch_prop_type(const zend_script *script, zend_property_in if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) { uint32_t type = ZEND_TYPE_IS_CLASS(prop_info->type) ? MAY_BE_OBJECT - : zend_convert_type_declaration_mask(ZEND_TYPE_MASK(prop_info->type)); + : zend_convert_type_declaration_mask(ZEND_TYPE_PURE_MASK(prop_info->type)); if (ZEND_TYPE_ALLOW_NULL(prop_info->type)) { type |= MAY_BE_NULL; @@ -3109,7 +3101,7 @@ static int zend_update_type_info(const zend_op_array *op_array, ce = NULL; if (arg_info) { tmp = zend_fetch_arg_info_type(script, arg_info, &ce); - if (arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(arg_info)) { tmp |= MAY_BE_REF; } } else { diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 7bac2d7538cc4..bde02c678b505 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -656,9 +656,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, } case ZEND_VERIFY_RETURN_TYPE: { zend_arg_info *ret_info = op_array->arg_info - 1; - if (ZEND_TYPE_IS_CLASS(ret_info->type) - || (ZEND_TYPE_IS_MASK(ret_info->type) - && !ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(val))) + if (!ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(val)) || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { return 0; } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index ac72df2ec0563..3883009a64b2a 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -602,8 +602,8 @@ static void accel_copy_permanent_strings(zend_new_interned_string_func_t new_int } for (i = 0 ; i < num_args; i++) { if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { - zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(arg_info[i].type); - arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(new_interned_string(ZEND_TYPE_NAME(arg_info[i].type)), allow_null); + ZEND_TYPE_SET_PTR(arg_info[i].type, + new_interned_string(ZEND_TYPE_NAME(arg_info[i].type))); } } } @@ -3580,7 +3580,7 @@ static zend_bool preload_try_resolve_property_types(zend_class_entry *ce) } zend_string_release(name); - prop->type = ZEND_TYPE_ENCODE_CE(p, ZEND_TYPE_ALLOW_NULL(prop->type)); + prop->type = (zend_type) ZEND_TYPE_INIT_CE(p, ZEND_TYPE_ALLOW_NULL(prop->type), 0); } ZEND_HASH_FOREACH_END(); } diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 54b888a132f3b..06d4a1be5a34b 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1156,7 +1156,7 @@ static void ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_op_array *op_ goto err; } - type_mask = ZEND_TYPE_MASK(arg_info->type); + type_mask = ZEND_TYPE_FULL_MASK(arg_info->type); if (type_mask & MAY_BE_CALLABLE) { if (zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) == 0) { goto err; @@ -1167,7 +1167,7 @@ static void ZEND_FASTCALL zend_jit_verify_arg_slow(zval *arg, zend_op_array *op_ } } else { if (Z_ISUNDEF_P(arg) || - zend_verify_scalar_type_hint(ZEND_TYPE_MASK(arg_info->type), arg, ZEND_ARG_USES_STRICT_TYPES(), /* is_internal */ 0) == 0) { + zend_verify_scalar_type_hint(type_mask, arg, ZEND_ARG_USES_STRICT_TYPES(), /* is_internal */ 0) == 0) { goto err; } } @@ -1323,7 +1323,7 @@ static zend_property_info *zend_jit_get_prop_not_accepting_double(zend_reference { zend_property_info *prop; ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) { - if (!ZEND_TYPE_IS_MASK(prop->type) || !(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) { + if (!(ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_DOUBLE)) { return prop; } } ZEND_REF_FOREACH_TYPE_SOURCES_END(); diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 410a6d0ed91fe..e5d9fd129c623 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -7019,8 +7019,8 @@ static uint32_t skip_valid_arguments(zend_op_array *op_array, zend_ssa *ssa, zen zend_arg_info *arg_info = func->op_array.arg_info + num_args; if (ZEND_TYPE_IS_SET(arg_info->type)) { - if (ZEND_TYPE_IS_MASK(arg_info->type)) { - uint32_t type_mask = ZEND_TYPE_MASK(arg_info->type); + if (ZEND_TYPE_IS_ONLY_MASK(arg_info->type)) { + uint32_t type_mask = ZEND_TYPE_PURE_MASK(arg_info->type); uint32_t info = _ssa_op1_info(op_array, ssa, call_info->arg_info[num_args].opline); if ((info & (MAY_BE_ANY|MAY_BE_UNDEF)) & ~type_mask) { break; @@ -8962,12 +8962,12 @@ static int zend_jit_recv(dasm_State **Dst, const zend_op *opline, zend_op_array zend_jit_addr res_addr = zend_jit_decode_op(op_array, opline->result_type, opline->result, opline, NULL, -1); | LOAD_ZVAL_ADDR r0, res_addr - if (arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(arg_info)) { | GET_Z_PTR r0, r0 | add r0, offsetof(zend_reference, val) } if (!ZEND_TYPE_IS_CLASS(type)) { - uint32_t type_mask = ZEND_TYPE_MASK(type); + uint32_t type_mask = ZEND_TYPE_PURE_MASK(type); if (is_power_of_two(type_mask)) { uint32_t type_code = concrete_type(type_mask); | cmp byte [r0 + 8], type_code @@ -9116,7 +9116,7 @@ static int zend_jit_recv_init(dasm_State **Dst, const zend_op *opline, zend_op_a | LOAD_ZVAL_ADDR r0, res_addr | ZVAL_DEREF r0, MAY_BE_REF if (!ZEND_TYPE_IS_CLASS(arg_info->type)) { - uint32_t type_mask = ZEND_TYPE_MASK(arg_info->type); + uint32_t type_mask = ZEND_TYPE_PURE_MASK(arg_info->type); if (is_power_of_two(type_mask)) { uint32_t type_code = concrete_type(type_mask); | cmp byte [r0 + 8], type_code diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index be927f6447986..362c0629dccbe 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -237,7 +237,7 @@ static void zend_hash_clone_prop_info(HashTable *ht) zend_class_entry *ce = ZEND_TYPE_CE(prop_info->type); if (IN_ARENA(ce)) { ce = ARENA_REALLOC(ce); - prop_info->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop_info->type)); + ZEND_TYPE_SET_PTR(prop_info->type, ce); } } } diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 663f511bc17c8..8def75c434687 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -499,14 +499,9 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra SERIALIZE_STR(p->name); } if (ZEND_TYPE_IS_CLASS(p->type)) { - zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(p->type); zend_string *type_name = ZEND_TYPE_NAME(p->type); - SERIALIZE_STR(type_name); - p->type = - (Z_UL(1) << (sizeof(zend_type)*8-1)) | /* type is class */ - (allow_null ? (Z_UL(1) << (sizeof(zend_type)*8-2)) : Z_UL(0)) | /* type allow null */ - (zend_type)type_name; + ZEND_TYPE_SET_PTR(p->type, type_name); } p++; } @@ -577,16 +572,14 @@ static void zend_file_cache_serialize_prop_info(zval *zv, SERIALIZE_STR(prop->doc_comment); } } - if (prop->type) { - if (ZEND_TYPE_IS_NAME(prop->type)) { - zend_string *name = ZEND_TYPE_NAME(prop->type); - SERIALIZE_STR(name); - prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type)); - } else if (ZEND_TYPE_IS_CE(prop->type)) { - zend_class_entry *ce = ZEND_TYPE_CE(prop->type); - SERIALIZE_PTR(ce); - prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type)); - } + if (ZEND_TYPE_IS_NAME(prop->type)) { + zend_string *name = ZEND_TYPE_NAME(prop->type); + SERIALIZE_STR(name); + ZEND_TYPE_SET_PTR(prop->type, name); + } else if (ZEND_TYPE_IS_CE(prop->type)) { + zend_class_entry *ce = ZEND_TYPE_CE(prop->type); + SERIALIZE_PTR(ce); + ZEND_TYPE_SET_PTR(prop->type, ce); } } } @@ -1202,12 +1195,10 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr if (!IS_UNSERIALIZED(p->name)) { UNSERIALIZE_STR(p->name); } - if (p->type & (Z_UL(1) << (sizeof(zend_type)*8-1))) { /* type is class */ - zend_bool allow_null = (p->type & (Z_UL(1) << (sizeof(zend_type)*8-2))) != 0; /* type allow null */ - zend_string *type_name = (zend_string*)(p->type & ~(((Z_UL(1) << (sizeof(zend_type)*8-1))) | ((Z_UL(1) << (sizeof(zend_type)*8-2))))); - + if (ZEND_TYPE_IS_CLASS(p->type)) { + zend_string *type_name = ZEND_TYPE_NAME(p->type); UNSERIALIZE_STR(type_name); - p->type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null); + ZEND_TYPE_SET_PTR(p->type, type_name); } p++; } @@ -1278,16 +1269,14 @@ static void zend_file_cache_unserialize_prop_info(zval *zv, UNSERIALIZE_STR(prop->doc_comment); } } - if (prop->type) { - if (ZEND_TYPE_IS_NAME(prop->type)) { - zend_string *name = ZEND_TYPE_NAME(prop->type); - UNSERIALIZE_STR(name); - prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type)); - } else if (ZEND_TYPE_IS_CE(prop->type)) { - zend_class_entry *ce = ZEND_TYPE_CE(prop->type); - UNSERIALIZE_PTR(ce); - prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type)); - } + if (ZEND_TYPE_IS_NAME(prop->type)) { + zend_string *name = ZEND_TYPE_NAME(prop->type); + UNSERIALIZE_STR(name); + ZEND_TYPE_SET_PTR(prop->type, name); + } else if (ZEND_TYPE_IS_CE(prop->type)) { + zend_class_entry *ce = ZEND_TYPE_CE(prop->type); + UNSERIALIZE_PTR(ce); + ZEND_TYPE_SET_PTR(prop->type, ce); } } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index a2fb94d7f6a3a..935f8063bd022 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -501,10 +501,8 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { zend_string *type_name = ZEND_TYPE_NAME(arg_info[i].type); - zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(arg_info[i].type); - zend_accel_store_interned_string(type_name); - arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null); + ZEND_TYPE_SET_PTR(arg_info[i].type, type_name); } } if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { @@ -664,7 +662,7 @@ static void zend_persist_property_info(zval *zv) if (ZEND_TYPE_IS_NAME(prop->type)) { zend_string *class_name = ZEND_TYPE_NAME(prop->type); zend_accel_store_interned_string(class_name); - prop->type = ZEND_TYPE_ENCODE_CLASS(class_name, ZEND_TYPE_ALLOW_NULL(prop->type)); + ZEND_TYPE_SET_PTR(prop->type, class_name); } } @@ -944,7 +942,7 @@ static void zend_update_parent_ce(zend_class_entry *ce) if (ce->type == ZEND_USER_CLASS) { ce = zend_shared_alloc_get_xlat_entry(ce); if (ce) { - prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type)); + ZEND_TYPE_SET_PTR(prop->type, ce); } } } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index cc798b27de050..62a3deaea0053 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -224,10 +224,8 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) } if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) { zend_string *type_name = ZEND_TYPE_NAME(arg_info[i].type); - zend_bool allow_null = ZEND_TYPE_ALLOW_NULL(arg_info[i].type); - ADD_INTERNED_STRING(type_name); - arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(type_name, allow_null); + ZEND_TYPE_SET_PTR(arg_info[i].type, type_name); } } } @@ -307,7 +305,7 @@ static void zend_persist_property_info_calc(zval *zv) if (ZEND_TYPE_IS_NAME(prop->type)) { zend_string *class_name = ZEND_TYPE_NAME(prop->type); ADD_INTERNED_STRING(class_name); - prop->type = ZEND_TYPE_ENCODE_CLASS(class_name, ZEND_TYPE_ALLOW_NULL(prop->type)); + ZEND_TYPE_SET_PTR(prop->type, class_name); } if (ZCG(accel_directives).save_comments && prop->doc_comment) { ADD_STRING(prop->doc_comment); diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 436da5a4385e9..2786450e4025d 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1294,10 +1294,10 @@ int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) } else { func.required_num_args = info->required_num_args; } - if (info->return_reference) { + if (ZEND_ARG_SEND_MODE(info)) { func.fn_flags |= ZEND_ACC_RETURN_REFERENCE; } - if (funcs->arg_info[funcs->num_args].is_variadic) { + if (ZEND_ARG_IS_VARIADIC(&funcs->arg_info[funcs->num_args])) { func.fn_flags |= ZEND_ACC_VARIADIC; /* Don't count the variadic argument */ func.num_args--; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 5c775ed926d15..f25c870773cf2 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -587,10 +587,10 @@ static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_ smart_str_append_printf(str, "%s ", ZSTR_VAL(type_str)); zend_string_release(type_str); } - if (arg_info->pass_by_reference) { + if (ZEND_ARG_SEND_MODE(arg_info)) { smart_str_appendc(str, '&'); } - if (arg_info->is_variadic) { + if (ZEND_ARG_IS_VARIADIC(arg_info)) { smart_str_appends(str, "..."); } if (arg_info->name) { @@ -2551,15 +2551,15 @@ ZEND_METHOD(reflection_parameter, isArray) { reflection_object *intern; parameter_reference *param; - zend_type type; + uint32_t type_mask; if (zend_parse_parameters_none() == FAILURE) { return; } GET_REFLECTION_OBJECT_PTR(param); - type = ZEND_TYPE_WITHOUT_NULL(param->arg_info->type); - RETVAL_BOOL(ZEND_TYPE_MASK(type) == MAY_BE_ARRAY); + type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(param->arg_info->type); + RETVAL_BOOL(type_mask == MAY_BE_ARRAY); } /* }}} */ @@ -2569,15 +2569,15 @@ ZEND_METHOD(reflection_parameter, isCallable) { reflection_object *intern; parameter_reference *param; - zend_type type; + uint32_t type_mask; if (zend_parse_parameters_none() == FAILURE) { return; } GET_REFLECTION_OBJECT_PTR(param); - type = ZEND_TYPE_WITHOUT_NULL(param->arg_info->type); - RETVAL_BOOL(ZEND_TYPE_MASK(type) == MAY_BE_CALLABLE); + type_mask = ZEND_TYPE_PURE_MASK_WITHOUT_NULL(param->arg_info->type); + RETVAL_BOOL(type_mask == MAY_BE_CALLABLE); } /* }}} */ @@ -2610,7 +2610,7 @@ ZEND_METHOD(reflection_parameter, isPassedByReference) } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(param->arg_info->pass_by_reference); + RETVAL_BOOL(ZEND_ARG_SEND_MODE(param->arg_info)); } /* }}} */ @@ -2627,7 +2627,7 @@ ZEND_METHOD(reflection_parameter, canBePassedByValue) GET_REFLECTION_OBJECT_PTR(param); /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */ - RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF); + RETVAL_BOOL(ZEND_ARG_SEND_MODE(param->arg_info) != ZEND_SEND_BY_REF); } /* }}} */ @@ -2788,7 +2788,7 @@ ZEND_METHOD(reflection_parameter, isVariadic) } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(param->arg_info->is_variadic); + RETVAL_BOOL(ZEND_ARG_IS_VARIADIC(param->arg_info)); } /* }}} */ @@ -2808,6 +2808,11 @@ ZEND_METHOD(reflection_type, allowsNull) } /* }}} */ +static zend_string *zend_type_to_string_without_null(zend_type type) { + ZEND_TYPE_FULL_MASK(type) &= ~MAY_BE_NULL; + return zend_type_to_string(type); +} + /* {{{ proto public string ReflectionType::__toString() Return the text of the type hint */ ZEND_METHOD(reflection_type, __toString) @@ -2820,7 +2825,8 @@ ZEND_METHOD(reflection_type, __toString) } GET_REFLECTION_OBJECT_PTR(param); - RETURN_STR(zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(param->type))); + /* TODO: We should remove the "without null" special-casing here. */ + RETURN_STR(zend_type_to_string_without_null(param->type)); } /* }}} */ @@ -2836,7 +2842,7 @@ ZEND_METHOD(reflection_named_type, getName) } GET_REFLECTION_OBJECT_PTR(param); - RETURN_STR(zend_type_to_string(ZEND_TYPE_WITHOUT_NULL(param->type))); + RETURN_STR(zend_type_to_string_without_null(param->type)); } /* }}} */ @@ -2852,7 +2858,7 @@ ZEND_METHOD(reflection_named_type, isBuiltin) } GET_REFLECTION_OBJECT_PTR(param); - RETVAL_BOOL(ZEND_TYPE_IS_MASK(param->type)); + RETVAL_BOOL(ZEND_TYPE_IS_ONLY_MASK(param->type)); } /* }}} */ diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 2b1813ee4780f..0dae132fbe731 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -219,7 +219,8 @@ PHP_MINIT_FUNCTION(zend_test) zval val; ZVAL_LONG(&val, 123); zend_declare_typed_property( - zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, ZEND_TYPE_ENCODE_CODE(IS_LONG, 0)); + zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, + (zend_type) ZEND_TYPE_INIT_CODE(IS_LONG, 0, 0)); zend_string_release(name); } @@ -230,7 +231,7 @@ PHP_MINIT_FUNCTION(zend_test) ZVAL_NULL(&val); zend_declare_typed_property( zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, - ZEND_TYPE_ENCODE_CLASS(class_name, 1)); + (zend_type) ZEND_TYPE_INIT_CLASS(class_name, 1, 0)); zend_string_release(name); } @@ -240,7 +241,7 @@ PHP_MINIT_FUNCTION(zend_test) ZVAL_LONG(&val, 123); zend_declare_typed_property( zend_test_class, name, &val, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, NULL, - ZEND_TYPE_ENCODE_CODE(IS_LONG, 0)); + (zend_type) ZEND_TYPE_INIT_CODE(IS_LONG, 0, 0)); zend_string_release(name); } diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index 912089ea2303d..2fcac243eaef0 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -231,7 +231,7 @@ static void phpdbg_dump_prototype(zval *tmp) /* {{{ */ } if (!is_variadic) { - is_variadic = arginfo ? arginfo[j].is_variadic : 0; + is_variadic = arginfo ? ZEND_ARG_IS_VARIADIC(&arginfo[j]) : 0; } phpdbg_xml(" variadic=\"%s\" name=\"%s\">", is_variadic ? "variadic" : "", arg_name ? arg_name : "");