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;
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);
}
} 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);
}
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));
}
}
}
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));
}
/* }}} */
#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 */
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 ? "<optional>" : "<required>"));
} 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);
|| 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) {
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,
}
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;
}
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++;
}
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);
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 {
const char *correct_name;
zend_string *orig_name = zend_ast_get_str(ast);
}
}
- return ZEND_TYPE_ENCODE_CLASS(class_name, allow_null);
+ return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null, 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) {
+ if ((ZEND_TYPE_FULL_MASK(type) & MAY_BE_DOUBLE) && Z_TYPE_P(value) == IS_LONG) {
/* Integers are allowed as initializers for floating-point values. */
convert_to_double(value);
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;
/* 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 {
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");
}
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 */
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",
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,
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 {
#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 */
}
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) \
*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";
*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;
+ }
}
}
}
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;
}
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);
}
}
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) {
zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
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;
zend_arg_info *ret_info = zf->common.arg_info - 1;
// TODO: Eliminate this!
+ zend_class_entry *ce = NULL;
if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
if (UNEXPECTED(!*cache_slot)) {
zend_class_entry *ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
{
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();
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;
}
/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
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);
}
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;
}
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;
}
}
}
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->common.scope, ZEND_TYPE_NAME(fe_type));
? 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
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;
}
}
}
/* 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;
}
}
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, "...");
}
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;
const zend_property_info *parent_info, const 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 INHERITANCE_SUCCESS;
}
* 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 */
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
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++;
}
}
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);
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);
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;
}
/* 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;
}
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;
}
}
} 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;
}
}
}
}
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;
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;
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 {
}
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;
}
}
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)));
}
}
}
}
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();
}
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;
}
} 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;
}
}
{
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();
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;
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
| 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
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);
}
}
}
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++;
}
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);
}
}
}
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++;
}
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);
}
}
}
}
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) {
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);
}
}
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);
}
}
}
}
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);
}
}
}
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);
} 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--;
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) {
{
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);
}
/* }}} */
{
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);
}
/* }}} */
}
GET_REFLECTION_OBJECT_PTR(param);
- RETVAL_BOOL(param->arg_info->pass_by_reference);
+ RETVAL_BOOL(ZEND_ARG_SEND_MODE(param->arg_info));
}
/* }}} */
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);
}
/* }}} */
}
GET_REFLECTION_OBJECT_PTR(param);
- RETVAL_BOOL(param->arg_info->is_variadic);
+ RETVAL_BOOL(ZEND_ARG_IS_VARIADIC(param->arg_info));
}
/* }}} */
}
/* }}} */
+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)
}
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));
}
/* }}} */
}
GET_REFLECTION_OBJECT_PTR(param);
- RETVAL_BOOL(ZEND_TYPE_IS_MASK(param->type));
+ RETVAL_BOOL(ZEND_TYPE_IS_ONLY_MASK(param->type));
}
/* }}} */
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);
}
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);
}
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);
}
}
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 : "");