} ZEND_HASH_FOREACH_END();
}
- if (ZEND_TYPE_IS_NAME(prop->type)) {
+ #ifdef ZEND_WIN32
+ static void preload_check_windows_restriction(zend_class_entry *scope, zend_class_entry *ce) {
+ if (ce && ce->type == ZEND_INTERNAL_CLASS) {
+ zend_error_noreturn(E_ERROR,
+ "Class %s uses internal class %s during preloading, which is not supported on Windows",
+ ZSTR_VAL(scope->name), ZSTR_VAL(ce->name));
+ }
+ }
+
+ static void preload_check_windows_restrictions(zend_class_entry *scope) {
+ uint32_t i;
+
+ preload_check_windows_restriction(scope, scope->parent);
+
+ for (i = 0; i < scope->num_interfaces; i++) {
+ preload_check_windows_restriction(scope, scope->interfaces[i]);
+ }
+ }
+ #endif
+
+ static zend_class_entry *preload_load_prop_type(zend_property_info *prop, zend_string *name) {
+ zend_class_entry *ce;
+ if (zend_string_equals_literal_ci(name, "self")) {
+ ce = prop->ce;
+ } else if (zend_string_equals_literal_ci(name, "parent")) {
+ ce = prop->ce->parent;
+ } else {
+ ce = zend_lookup_class(name);
+ }
+ if (ce) {
+ return ce;
+ }
+
+ zend_error_noreturn(E_ERROR,
+ "Failed to load class %s used by typed property %s::$%s during preloading",
+ ZSTR_VAL(name), ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name));
+ return ce;
+ }
+
+ static void preload_ensure_classes_loadable() {
+ /* Run this in a loop, because additional classes may be loaded while updating constants etc. */
+ uint32_t checked_classes_idx = 0;
+ while (1) {
+ zend_class_entry *ce;
+ uint32_t num_classes = zend_hash_num_elements(EG(class_table));
+ if (num_classes == checked_classes_idx) {
+ return;
+ }
+
+ ZEND_HASH_REVERSE_FOREACH_PTR(EG(class_table), ce) {
+ if (ce->type == ZEND_INTERNAL_CLASS || _idx == checked_classes_idx) {
+ break;
+ }
+
+ if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
+ /* Only require that already linked classes are loadable, we'll properly check
+ * things when linking additional classes. */
+ continue;
+ }
+
+ #ifdef ZEND_WIN32
+ preload_check_windows_restrictions(ce);
+ #endif
+
+ if (!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
+ int result = SUCCESS;
+ zend_try {
+ result = zend_update_class_constants(ce);
+ } zend_catch {
+ /* Provide some context for the generated error. */
+ zend_error_noreturn(E_ERROR,
+ "Error generated while resolving initializers of class %s during preloading",
+ ZSTR_VAL(ce->name));
+ } zend_end_try();
+ if (result == FAILURE) {
+ /* Just present to be safe: We generally always throw some
+ * other fatal error as part of update_class_constants(). */
+ zend_error_noreturn(E_ERROR,
+ "Failed to resolve initializers of class %s during preloading",
+ ZSTR_VAL(ce->name));
+ }
+ ZEND_ASSERT(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED);
+ }
+
+ if (!(ce->ce_flags & ZEND_ACC_PROPERTY_TYPES_RESOLVED)) {
+ if (ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS) {
+ zend_property_info *prop;
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
- prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
++ if (ZEND_TYPE_HAS_LIST(prop->type)) {
++ void **entry;
++ ZEND_TYPE_LIST_FOREACH_PTR(ZEND_TYPE_LIST(prop->type), entry) {
++ if (ZEND_TYPE_LIST_IS_NAME(*entry)) {
++ zend_class_entry *ce = preload_load_prop_type(
++ prop, ZEND_TYPE_LIST_GET_NAME(*entry));
++ *entry = ZEND_TYPE_LIST_ENCODE_CE(ce);
++ }
++ } ZEND_TYPE_LIST_FOREACH_END();
++ } else if (ZEND_TYPE_HAS_NAME(prop->type)) {
+ zend_class_entry *ce =
+ preload_load_prop_type(prop, ZEND_TYPE_NAME(prop->type));
++ ZEND_TYPE_SET_CE(prop->type, ce);
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ ce->ce_flags |= ZEND_ACC_PROPERTY_TYPES_RESOLVED;
+ }
+ } ZEND_HASH_FOREACH_END();
+ checked_classes_idx = num_classes;
+ }
+ }
+
static zend_string *preload_resolve_path(zend_string *filename)
{
if (is_stream_path(ZSTR_VAL(filename))) {