Skip to content

Commit 9f44caa

Browse files
committed
Make zend_type a 2-field struct
1 parent fb60ccc commit 9f44caa

20 files changed

+171
-196
lines changed

Zend/zend.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -594,10 +594,7 @@ static void function_copy_ctor(zval *zv) /* {{{ */
594594
for (i = 0 ; i < num_args; i++) {
595595
if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
596596
zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1);
597-
598-
new_arg_info[i].type =
599-
ZEND_TYPE_ENCODE_CLASS(
600-
name, ZEND_TYPE_ALLOW_NULL(arg_info[i].type));
597+
ZEND_TYPE_SET_PTR(new_arg_info[i].type, name);
601598
}
602599
}
603600
func->common.arg_info = new_arg_info + 1;
@@ -968,7 +965,7 @@ static void zend_resolve_property_types(void) /* {{{ */
968965
zend_class_entry *prop_ce = zend_hash_find_ptr(CG(class_table), lc_type_name);
969966

970967
ZEND_ASSERT(prop_ce && prop_ce->type == ZEND_INTERNAL_CLASS);
971-
prop_info->type = ZEND_TYPE_ENCODE_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
968+
prop_info->type = (zend_type) ZEND_TYPE_INIT_CE(prop_ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
972969
zend_string_release(lc_type_name);
973970
zend_string_release(type_name);
974971
}

Zend/zend_API.c

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,11 +2062,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
20622062
}
20632063
if (ZEND_TYPE_IS_SET(info->type)) {
20642064
if (ZEND_TYPE_IS_CLASS(info->type)) {
2065-
const char *type_name = (const char*)info->type;
2066-
2067-
if (type_name[0] == '?') {
2068-
type_name++;
2069-
}
2065+
const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
20702066
if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
20712067
zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
20722068
}
@@ -2147,16 +2143,9 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
21472143
reg_function->common.arg_info = new_arg_info + 1;
21482144
for (i = 0; i < num_args; i++) {
21492145
if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) {
2150-
const char *class_name = (const char*)new_arg_info[i].type;
2151-
zend_bool allow_null = 0;
2152-
zend_string *str;
2153-
2154-
if (class_name[0] == '?') {
2155-
class_name++;
2156-
allow_null = 1;
2157-
}
2158-
str = zend_string_init_interned(class_name, strlen(class_name), 1);
2159-
new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null);
2146+
const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
2147+
ZEND_TYPE_SET_PTR(new_arg_info[i].type,
2148+
zend_string_init_interned(class_name, strlen(class_name), 1));
21602149
}
21612150
}
21622151
}
@@ -3719,7 +3708,7 @@ ZEND_API int zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, ze
37193708

37203709
ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
37213710
{
3722-
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, ZEND_TYPE_ENCODE_NONE());
3711+
return zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE());
37233712
}
37243713
/* }}} */
37253714

Zend/zend_API.h

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,34 +96,33 @@ typedef struct _zend_fcall_info_cache {
9696

9797
#define ZEND_FE_END { NULL, NULL, NULL, 0, 0 }
9898

99-
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 0},
100-
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, pass_by_ref, 0},
101-
#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 },
102-
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 },
103-
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_ENCODE_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 },
104-
#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 },
105-
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, 0, pass_by_ref, 1 },
106-
#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 },
107-
#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 },
99+
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, ZEND_TYPE_INIT_NONE(), pass_by_ref, 0},
100+
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null), pass_by_ref, 0 },
101+
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_INIT_CODE(IS_ARRAY, allow_null), pass_by_ref, 0 },
102+
#define ZEND_ARG_CALLABLE_INFO(pass_by_ref, name, allow_null) { #name, ZEND_TYPE_INIT_CODE(IS_CALLABLE, allow_null), pass_by_ref, 0 },
103+
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null), pass_by_ref, 0 },
104+
#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name) { #name, ZEND_TYPE_INIT_NONE(), pass_by_ref, 1 },
105+
#define ZEND_ARG_VARIADIC_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, ZEND_TYPE_INIT_CODE(type_hint, allow_null), pass_by_ref, 1 },
106+
#define ZEND_ARG_VARIADIC_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, ZEND_TYPE_INIT_CLASS_CONST(#classname, allow_null), pass_by_ref, 1 },
108107

109108
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \
110109
static const zend_internal_arg_info name[] = { \
111-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CLASS_CONST(#class_name, allow_null), return_reference, 0 },
110+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CLASS_CONST(#class_name, allow_null), return_reference, 0 },
112111

113112
#define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO(name, class_name, allow_null) \
114113
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, 0, -1, class_name, allow_null)
115114

116115
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, type, allow_null) \
117116
static const zend_internal_arg_info name[] = { \
118-
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_ENCODE_CODE(type, allow_null), return_reference, 0 },
117+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_CODE(type, allow_null), return_reference, 0 },
119118
#define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(name, type, allow_null) \
120119
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, 0, -1, type, allow_null)
121120

122121
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args) \
123122
static const zend_internal_arg_info name[] = { \
124-
{ (const char*)(zend_uintptr_t)(required_num_args), 0, return_reference, 0 },
123+
{ (const char*)(zend_uintptr_t)(required_num_args), ZEND_TYPE_INIT_NONE(), return_reference, 0 },
125124
#define ZEND_BEGIN_ARG_INFO(name, _unused) \
126-
ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1)
125+
ZEND_BEGIN_ARG_INFO_EX(name, {}, ZEND_RETURN_VALUE, -1)
127126
#define ZEND_END_ARG_INFO() };
128127

129128
/* Name macros */

Zend/zend_compile.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
10961096
} else if (ZEND_TYPE_IS_CE(type)) {
10971097
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
10981098
} else {
1099-
uint32_t type_mask = ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(type));
1099+
uint32_t type_mask = ZEND_TYPE_MASK_WITHOUT_NULL(type);
11001100
switch (type_mask) {
11011101
case MAY_BE_FALSE|MAY_BE_TRUE:
11021102
str = ZSTR_KNOWN(ZEND_STR_BOOL);
@@ -2123,7 +2123,7 @@ static void zend_emit_return_type_check(
21232123
zend_op *opline;
21242124

21252125
/* `return ...;` is illegal in a void function (but `return;` isn't) */
2126-
if (ZEND_TYPE_IS_MASK(type) && ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
2126+
if (ZEND_TYPE_CONTAINS_CODE(type, IS_VOID)) {
21272127
if (expr) {
21282128
if (expr->op_type == IS_CONST && Z_TYPE(expr->u.constant) == IS_NULL) {
21292129
zend_error_noreturn(E_COMPILE_ERROR,
@@ -2149,8 +2149,7 @@ static void zend_emit_return_type_check(
21492149
}
21502150

21512151
if (expr && expr->op_type == IS_CONST) {
2152-
if (ZEND_TYPE_IS_MASK(type)
2153-
&& ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
2152+
if (ZEND_TYPE_CONTAINS_CODE(type, Z_TYPE(expr->u.constant))) {
21542153
/* we don't need run-time check */
21552154
return;
21562155
}
@@ -5312,7 +5311,7 @@ static zend_type zend_compile_typename(zend_ast *ast, zend_bool force_allow_null
53125311
}
53135312

53145313
if (ast->kind == ZEND_AST_TYPE) {
5315-
return ZEND_TYPE_ENCODE_CODE(ast->attr, allow_null);
5314+
return (zend_type) ZEND_TYPE_INIT_CODE(ast->attr, allow_null);
53165315
} else {
53175316
zend_string *class_name = zend_ast_get_str(ast);
53185317
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
53265325
if (type == IS_VOID && allow_null) {
53275326
zend_error_noreturn(E_COMPILE_ERROR, "Void type cannot be nullable");
53285327
}
5329-
return ZEND_TYPE_ENCODE_CODE(type, allow_null);
5328+
return (zend_type) ZEND_TYPE_INIT_CODE(type, allow_null);
53305329
} else {
53315330
uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
53325331
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
53375336
zend_string_addref(class_name);
53385337
}
53395338

5340-
return ZEND_TYPE_ENCODE_CLASS(class_name, allow_null);
5339+
return (zend_type) ZEND_TYPE_INIT_CLASS(class_name, allow_null);
53415340
}
53425341
}
53435342
}
@@ -5453,7 +5452,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
54535452
arg_info->name = zend_string_copy(name);
54545453
arg_info->pass_by_reference = is_ref;
54555454
arg_info->is_variadic = is_variadic;
5456-
arg_info->type = ZEND_TYPE_ENCODE_NONE();
5455+
arg_info->type = (zend_type) ZEND_TYPE_INIT_NONE();
54575456

54585457
if (type_ast) {
54595458
uint32_t default_type = default_ast ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
@@ -5984,13 +5983,12 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags) /
59845983
zend_string *name = zval_make_interned_string(zend_ast_get_zval(name_ast));
59855984
zend_string *doc_comment = NULL;
59865985
zval value_zv;
5987-
zend_type type = ZEND_TYPE_ENCODE_NONE();
5986+
zend_type type = ZEND_TYPE_INIT_NONE();
59885987

59895988
if (type_ast) {
59905989
type = zend_compile_typename(type_ast, 0);
59915990

5992-
if (ZEND_TYPE_IS_MASK(type)
5993-
&& (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE))) {
5991+
if (ZEND_TYPE_MASK(type) & (MAY_BE_VOID|MAY_BE_CALLABLE)) {
59945992
zend_string *str = zend_type_to_string(type);
59955993
zend_error_noreturn(E_COMPILE_ERROR,
59965994
"Property %s::$%s cannot have type %s",

Zend/zend_execute.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -711,8 +711,8 @@ static ZEND_COLD void zend_verify_type_error_common(
711711
*need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type));
712712
}
713713
} else {
714-
zend_type type = ZEND_TYPE_WITHOUT_NULL(arg_info->type);
715-
switch (ZEND_TYPE_MASK(type)) {
714+
uint32_t type_mask = ZEND_TYPE_MASK_WITHOUT_NULL(arg_info->type);
715+
switch (type_mask) {
716716
case MAY_BE_OBJECT:
717717
*need_msg = "be an ";
718718
*need_kind = "object";
@@ -726,11 +726,15 @@ static ZEND_COLD void zend_verify_type_error_common(
726726
*need_kind = "";
727727
break;
728728
default:
729+
{
729730
/* TODO: The zend_type_to_string() result is guaranteed interned here.
730731
* It would be beter to switch all this code to use zend_string though. */
732+
zend_type type = arg_info->type;
733+
ZEND_TYPE_MASK(type) &= ~MAY_BE_NULL;
731734
*need_msg = "be of the type ";
732735
*need_kind = ZSTR_VAL(zend_type_to_string(type));
733736
break;
737+
}
734738
}
735739
}
736740

@@ -933,7 +937,7 @@ static zend_bool zend_resolve_class_type(zend_type *type, zend_class_entry *self
933937
}
934938

935939
zend_string_release(name);
936-
*type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
940+
*type = (zend_type) ZEND_TYPE_INIT_CE(ce, ZEND_TYPE_ALLOW_NULL(*type));
937941
return 1;
938942
}
939943

@@ -1193,7 +1197,7 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
11931197
zend_class_entry *ce = NULL;
11941198
void *dummy_cache_slot = NULL;
11951199

1196-
if (ZEND_TYPE_IS_MASK(ret_info->type) && (ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID)) {
1200+
if (ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID) {
11971201
if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
11981202
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
11991203
return 0;
@@ -1225,8 +1229,7 @@ static ZEND_COLD int zend_verify_missing_return_type(const zend_function *zf, vo
12251229
zend_arg_info *ret_info = zf->common.arg_info - 1;
12261230

12271231
if (ZEND_TYPE_IS_SET(ret_info->type)
1228-
&& (!ZEND_TYPE_IS_MASK(ret_info->type)
1229-
|| !(ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID))) {
1232+
&& !(ZEND_TYPE_MASK(ret_info->type) & MAY_BE_VOID)) {
12301233
zend_class_entry *ce = NULL;
12311234
if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
12321235
if (EXPECTED(*cache_slot)) {
@@ -1576,7 +1579,7 @@ static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *re
15761579
{
15771580
zend_property_info *prop;
15781581
ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop) {
1579-
if (!ZEND_TYPE_IS_MASK(prop->type) || !(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) {
1582+
if (!(ZEND_TYPE_MASK(prop->type) & MAY_BE_DOUBLE)) {
15801583
return prop;
15811584
}
15821585
} ZEND_REF_FOREACH_TYPE_SOURCES_END();
@@ -2545,7 +2548,7 @@ static zend_always_inline zend_bool check_type_array_assignable(zend_type type)
25452548
if (!ZEND_TYPE_IS_SET(type)) {
25462549
return 1;
25472550
}
2548-
return ZEND_TYPE_IS_MASK(type) && (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY));
2551+
return (ZEND_TYPE_MASK(type) & (MAY_BE_ITERABLE|MAY_BE_ARRAY)) != 0;
25492552
}
25502553

25512554
static zend_always_inline zend_bool check_type_stdClass_assignable(zend_type type) {
@@ -3074,9 +3077,9 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference
30743077
if (!seen_prop) {
30753078
seen_prop = prop;
30763079
seen_type_mask = ZEND_TYPE_IS_CLASS(prop->type)
3077-
? MAY_BE_OBJECT : ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type));
3080+
? MAY_BE_OBJECT : ZEND_TYPE_MASK_WITHOUT_NULL(prop->type);
30783081
} else if (needs_coercion
3079-
&& seen_type_mask != ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop->type))) {
3082+
&& seen_type_mask != ZEND_TYPE_MASK_WITHOUT_NULL(prop->type)) {
30803083
zend_throw_conflicting_coercion_error(seen_prop, prop, zv);
30813084
return 0;
30823085
}
@@ -3143,8 +3146,8 @@ ZEND_API zend_bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(zend_propert
31433146

31443147
if (result < 0) {
31453148
zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val));
3146-
if (ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(prop_info->type))
3147-
!= ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(ref_prop->type))) {
3149+
if (ZEND_TYPE_MASK_WITHOUT_NULL(prop_info->type)
3150+
!= ZEND_TYPE_MASK_WITHOUT_NULL(ref_prop->type)) {
31483151
/* Invalid due to conflicting coercion */
31493152
zend_throw_ref_type_error_type(ref_prop, prop_info, val);
31503153
return 0;

Zend/zend_inheritance.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -378,8 +378,7 @@ static inheritance_status zend_perform_covariant_type_check(
378378

379379
return ZEND_TYPE_MASK(fe_type) & MAY_BE_OBJECT ? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
380380
} else {
381-
return ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(fe_type))
382-
== ZEND_TYPE_MASK(ZEND_TYPE_WITHOUT_NULL(proto_type))
381+
return ZEND_TYPE_MASK_WITHOUT_NULL(fe_type) == ZEND_TYPE_MASK_WITHOUT_NULL(proto_type)
383382
? INHERITANCE_SUCCESS : INHERITANCE_ERROR;
384383
}
385384
}
@@ -859,7 +858,8 @@ zend_string* zend_resolve_property_type(zend_string *type, zend_class_entry *sco
859858
zend_bool property_types_compatible(zend_property_info *parent_info, zend_property_info *child_info) {
860859
zend_string *parent_name, *child_name;
861860
zend_class_entry *parent_type_ce, *child_type_ce;
862-
if (parent_info->type == child_info->type) {
861+
if (ZEND_TYPE_MASK(parent_info->type) == ZEND_TYPE_MASK(child_info->type)
862+
&& ZEND_TYPE_NAME(parent_info->type) == ZEND_TYPE_NAME(child_info->type)) {
863863
return 1;
864864
}
865865

0 commit comments

Comments
 (0)