@@ -838,8 +838,39 @@ static zend_class_entry *resolve_single_class_type(zend_string *name, zend_class
838
838
}
839
839
}
840
840
841
- // TODO Handle complex types when added
842
- // TODO Update to handle union and intersection in the same loop
841
+ // TODO better name
842
+ static zend_always_inline zend_class_entry * zend_resolve_ce (
843
+ zend_property_info * info , zend_type * type ) {
844
+ zend_class_entry * ce ;
845
+ if (UNEXPECTED (ZEND_TYPE_HAS_NAME (* type ))) {
846
+ zend_string * name = ZEND_TYPE_NAME (* type );
847
+
848
+ if (ZSTR_HAS_CE_CACHE (name )) {
849
+ ce = ZSTR_GET_CE_CACHE (name );
850
+ if (!ce ) {
851
+ ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
852
+ if (UNEXPECTED (!ce )) {
853
+ /* Cannot resolve */
854
+ return NULL ;
855
+ }
856
+ }
857
+ } else {
858
+ ce = resolve_single_class_type (name , info -> ce );
859
+ if (!ce ) {
860
+ /* Cannot resolve */
861
+ return NULL ;
862
+ }
863
+ if (!(info -> ce -> ce_flags & ZEND_ACC_IMMUTABLE )) {
864
+ zend_string_release (name );
865
+ ZEND_TYPE_SET_CE (* type , ce );
866
+ }
867
+ }
868
+ } else {
869
+ ce = ZEND_TYPE_CE (* type );
870
+ }
871
+ return ce ;
872
+ }
873
+
843
874
static bool zend_check_and_resolve_property_class_type (
844
875
zend_property_info * info , zend_class_entry * object_ce ) {
845
876
zend_class_entry * ce ;
@@ -848,62 +879,27 @@ static bool zend_check_and_resolve_property_class_type(
848
879
849
880
if (ZEND_TYPE_IS_INTERSECTION (info -> type )) {
850
881
ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (info -> type ), list_type ) {
851
- if (ZEND_TYPE_HAS_NAME (* list_type )) {
852
- zend_string * name = ZEND_TYPE_NAME (* list_type );
853
-
854
- if (ZSTR_HAS_CE_CACHE (name )) {
855
- ce = ZSTR_GET_CE_CACHE (name );
856
- if (!ce ) {
857
- ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
858
- if (UNEXPECTED (!ce )) {
859
- /* Cannot resolve */
860
- return false;
861
- }
862
- }
863
- } else {
864
- ce = resolve_single_class_type (name , info -> ce );
865
- if (!ce ) {
866
- /* Cannot resolve */
867
- return false;
868
- }
869
- if (!(info -> ce -> ce_flags & ZEND_ACC_IMMUTABLE )) {
870
- zend_string_release (name );
871
- ZEND_TYPE_SET_CE (* list_type , ce );
872
- }
873
- }
874
- } else {
875
- ce = ZEND_TYPE_CE (* list_type );
882
+ ce = zend_resolve_ce (info , list_type );
883
+
884
+ /* If we cannot resolve the CE we cannot check if it satisfies
885
+ * the type constraint, fail. */
886
+ if (ce == NULL ) {
887
+ return false;
876
888
}
889
+
877
890
if (!instanceof_function (object_ce , ce )) {
878
891
return false;
879
892
}
880
893
} ZEND_TYPE_LIST_FOREACH_END ();
881
894
return true;
882
895
} else {
883
896
ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (info -> type ), list_type ) {
884
- if (ZEND_TYPE_HAS_NAME (* list_type )) {
885
- zend_string * name = ZEND_TYPE_NAME (* list_type );
886
-
887
- if (ZSTR_HAS_CE_CACHE (name )) {
888
- ce = ZSTR_GET_CE_CACHE (name );
889
- if (!ce ) {
890
- ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
891
- if (UNEXPECTED (!ce )) {
892
- continue ;
893
- }
894
- }
895
- } else {
896
- ce = resolve_single_class_type (name , info -> ce );
897
- if (!ce ) {
898
- continue ;
899
- }
900
- if (!(info -> ce -> ce_flags & ZEND_ACC_IMMUTABLE )) {
901
- zend_string_release (name );
902
- ZEND_TYPE_SET_CE (* list_type , ce );
903
- }
904
- }
905
- } else {
906
- ce = ZEND_TYPE_CE (* list_type );
897
+ ce = zend_resolve_ce (info , list_type );
898
+
899
+ /* If we cannot resolve the CE we cannot check if it satisfies
900
+ * the type constraint, check the next one. */
901
+ if (ce == NULL ) {
902
+ continue ;
907
903
}
908
904
if (instanceof_function (object_ce , ce )) {
909
905
return true;
@@ -912,30 +908,14 @@ static bool zend_check_and_resolve_property_class_type(
912
908
return false;
913
909
}
914
910
} else {
915
- if (UNEXPECTED (ZEND_TYPE_HAS_NAME (info -> type ))) {
916
- zend_string * name = ZEND_TYPE_NAME (info -> type );
917
-
918
- if (ZSTR_HAS_CE_CACHE (name )) {
919
- ce = ZSTR_GET_CE_CACHE (name );
920
- if (!ce ) {
921
- ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
922
- if (UNEXPECTED (!ce )) {
923
- return 0 ;
924
- }
925
- }
926
- } else {
927
- ce = resolve_single_class_type (name , info -> ce );
928
- if (UNEXPECTED (!ce )) {
929
- return 0 ;
930
- }
931
- if (!(info -> ce -> ce_flags & ZEND_ACC_IMMUTABLE )) {
932
- zend_string_release (name );
933
- ZEND_TYPE_SET_CE (info -> type , ce );
934
- }
935
- }
936
- } else {
937
- ce = ZEND_TYPE_CE (info -> type );
911
+ ce = zend_resolve_ce (info , & info -> type );
912
+
913
+ /* If we cannot resolve the CE we cannot check if it satisfies
914
+ * the type constraint, fail. */
915
+ if (ce == NULL ) {
916
+ return false;
938
917
}
918
+
939
919
return instanceof_function (object_ce , ce );
940
920
}
941
921
}
@@ -1001,16 +981,6 @@ ZEND_API bool zend_value_instanceof_static(zval *zv) {
1001
981
return instanceof_function (Z_OBJCE_P (zv ), called_scope );
1002
982
}
1003
983
1004
- /* The cache_slot may only be NULL in debug builds, where arginfo verification of
1005
- * internal functions is enabled. Avoid unnecessary checks in release builds. */
1006
- #if ZEND_DEBUG
1007
- # define HAVE_CACHE_SLOT (cache_slot != NULL)
1008
- #else
1009
- # define HAVE_CACHE_SLOT 1
1010
- #endif
1011
-
1012
- // TODO Handle complex types when added
1013
- // TODO Update to handle union and intersection in the same loop
1014
984
static zend_always_inline bool zend_check_type_slow (
1015
985
zend_type * type , zval * arg , zend_reference * ref , void * * cache_slot , zend_class_entry * scope ,
1016
986
bool is_return_type , bool is_internal )
@@ -1022,28 +992,11 @@ static zend_always_inline bool zend_check_type_slow(
1022
992
zend_type * list_type ;
1023
993
if (ZEND_TYPE_IS_INTERSECTION (* type )) {
1024
994
ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (* type ), list_type ) {
1025
- if (HAVE_CACHE_SLOT && * cache_slot ) {
1026
- ce = * cache_slot ;
1027
- } else {
1028
- zend_string * name = ZEND_TYPE_NAME (* list_type );
1029
-
1030
- if (ZSTR_HAS_CE_CACHE (name )) {
1031
- ce = ZSTR_GET_CE_CACHE (name );
1032
- if (!ce ) {
1033
- ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
1034
- if (!ce ) {
1035
- /* Cannot resolve */
1036
- return false;
1037
- }
1038
- }
1039
- } else {
1040
- ce = zend_fetch_class (name ,
1041
- ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT );
1042
- if (!ce ) {
1043
- /* Cannot resolve */
1044
- return false;
1045
- }
1046
- }
995
+ ce = zend_fetch_ce_from_cache_slot (cache_slot , list_type );
996
+ /* If we cannot resolve the CE we cannot check if it satisfies
997
+ * the type constraint, fail. */
998
+ if (ce == NULL ) {
999
+ return false;
1047
1000
}
1048
1001
1049
1002
/* Perform actual type check */
@@ -1059,32 +1012,14 @@ static zend_always_inline bool zend_check_type_slow(
1059
1012
return true;
1060
1013
} else {
1061
1014
ZEND_TYPE_LIST_FOREACH (ZEND_TYPE_LIST (* type ), list_type ) {
1062
- if (HAVE_CACHE_SLOT && * cache_slot ) {
1063
- ce = * cache_slot ;
1064
- } else {
1065
- zend_string * name = ZEND_TYPE_NAME (* list_type );
1066
-
1067
- if (ZSTR_HAS_CE_CACHE (name )) {
1068
- ce = ZSTR_GET_CE_CACHE (name );
1069
- if (!ce ) {
1070
- ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
1071
- if (!ce ) {
1072
- if (HAVE_CACHE_SLOT ) {
1073
- cache_slot ++ ;
1074
- }
1075
- continue ;
1076
- }
1077
- }
1078
- } else {
1079
- ce = zend_fetch_class (name ,
1080
- ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT );
1081
- if (!ce ) {
1082
- if (HAVE_CACHE_SLOT ) {
1083
- cache_slot ++ ;
1084
- }
1085
- continue ;
1086
- }
1015
+ ce = zend_fetch_ce_from_cache_slot (cache_slot , list_type );
1016
+ /* If we cannot resolve the CE we cannot check if it satisfies
1017
+ * the type constraint, check the next one. */
1018
+ if (ce == NULL ) {
1019
+ if (HAVE_CACHE_SLOT ) {
1020
+ cache_slot ++ ;
1087
1021
}
1022
+ continue ;
1088
1023
}
1089
1024
1090
1025
/* Perform actual type check */
@@ -1098,30 +1033,13 @@ static zend_always_inline bool zend_check_type_slow(
1098
1033
} ZEND_TYPE_LIST_FOREACH_END ();
1099
1034
}
1100
1035
} else {
1101
- if (EXPECTED (HAVE_CACHE_SLOT && * cache_slot )) {
1102
- ce = (zend_class_entry * ) * cache_slot ;
1103
- } else {
1104
- zend_string * name = ZEND_TYPE_NAME (* type );
1105
-
1106
- if (ZSTR_HAS_CE_CACHE (name )) {
1107
- ce = ZSTR_GET_CE_CACHE (name );
1108
- if (!ce ) {
1109
- ce = zend_lookup_class_ex (name , NULL , ZEND_FETCH_CLASS_NO_AUTOLOAD );
1110
- if (UNEXPECTED (!ce )) {
1111
- goto builtin_types ;
1112
- }
1113
- }
1114
- } else {
1115
- ce = zend_fetch_class (name ,
1116
- ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT );
1117
- if (UNEXPECTED (!ce )) {
1118
- goto builtin_types ;
1119
- }
1120
- }
1121
- if (HAVE_CACHE_SLOT ) {
1122
- * cache_slot = (void * ) ce ;
1123
- }
1036
+ ce = zend_fetch_ce_from_cache_slot (cache_slot , type );
1037
+ /* If we cannot resolve the CE we cannot check if it satisfies
1038
+ * the type constraint, check if a standard type satisfies it. */
1039
+ if (ce == NULL ) {
1040
+ goto builtin_types ;
1124
1041
}
1042
+
1125
1043
if (instanceof_function (Z_OBJCE_P (arg ), ce )) {
1126
1044
return 1 ;
1127
1045
}
0 commit comments