Skip to content

Make zend_type into a struct with pointer + type_mask #4728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions Zend/zend.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be better to name macro ZEND_TYPE_SET_CLASS_NAME()

}
}
func->common.arg_info = new_arg_info + 1;
Expand Down Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how modern C implements dynamic structure initializes.
I would recommend to use old style explicit macro initializers (like ZEND_LONG).

ZEND_TYPE_INIT_CE(rop_info->type, prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type), 0);

zend_string_release(lc_type_name);
zend_string_release(type_name);
}
Expand Down
25 changes: 7 additions & 18 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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));
}
}
}
Expand Down Expand Up @@ -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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"big" structure is passed by value. This is not efficient.

}
/* }}} */

Expand Down
37 changes: 24 additions & 13 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)) },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's OK to use static initializers for constants.


#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 */
Expand Down
6 changes: 3 additions & 3 deletions Zend/zend_closures.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ? "<optional>" : "<required>"));
Expand Down
45 changes: 20 additions & 25 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}
Expand Down Expand Up @@ -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++;
Expand All @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return "big" structure by value is not efficient.

} else {
zend_string *class_name = zend_ast_get_str(ast);
zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
Expand All @@ -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) {
Expand All @@ -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);
}
}
}
Expand All @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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");
}

Expand All @@ -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 */
Expand Down Expand Up @@ -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",
Expand Down
16 changes: 9 additions & 7 deletions Zend/zend_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 {
Expand Down Expand Up @@ -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 */

Expand All @@ -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) \
Expand Down
Loading