} ZEND_HASH_FOREACH_END();
}
-static zend_bool preload_all_types_known(zend_class_entry *ce);
+static zend_bool preload_needed_types_known(zend_class_entry *ce);
static void get_unlinked_dependency(zend_class_entry *ce, const char **kind, const char **name) {
zend_class_entry *p;
*kind = "Unknown reason";
}
}
- if (!preload_all_types_known(ce)) {
+ if (!preload_needed_types_known(ce)) {
*kind = "Unknown type dependencies";
return;
}
return known;
}
-static zend_bool preload_all_types_known(zend_class_entry *ce) {
+static zend_bool preload_is_method_maybe_override(zend_class_entry *ce, zend_string *lcname) {
+ zend_class_entry *p;
+ if (ce->trait_aliases || ce->trait_precedences) {
+ return 1;
+ }
+
+ if (ce->parent_name) {
+ zend_string *key = zend_string_tolower(ce->parent_name);
+ p = zend_hash_find_ptr(EG(class_table), key);
+ zend_string_release(key);
+ if (zend_hash_exists(&p->function_table, lcname)) {
+ return 1;
+ }
+ }
+
+ if (ce->num_interfaces) {
+ uint32_t i;
+ for (i = 0; i < ce->num_interfaces; i++) {
+ zend_class_entry *p = zend_hash_find_ptr(EG(class_table), ce->interface_names[i].lc_name);
+ if (zend_hash_exists(&p->function_table, lcname)) {
+ return 1;
+ }
+ }
+ }
+
+ if (ce->num_traits) {
+ uint32_t i;
+ for (i = 0; i < ce->num_traits; i++) {
+ zend_class_entry *p = zend_hash_find_ptr(EG(class_table), ce->trait_names[i].lc_name);
+ if (zend_hash_exists(&p->function_table, lcname)) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static zend_bool preload_needed_types_known(zend_class_entry *ce) {
zend_function *fptr;
- ZEND_HASH_FOREACH_PTR(&ce->function_table, fptr) {
+ zend_string *lcname;
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, lcname, fptr) {
uint32_t i;
if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
- if (!preload_is_type_known(ce, fptr->common.arg_info[-1].type)) {
+ if (!preload_is_type_known(ce, fptr->common.arg_info[-1].type) &&
+ preload_is_method_maybe_override(ce, lcname)) {
return 0;
}
}
for (i = 0; i < fptr->common.num_args; i++) {
- if (!preload_is_type_known(ce, fptr->common.arg_info[i].type)) {
+ if (!preload_is_type_known(ce, fptr->common.arg_info[i].type) &&
+ preload_is_method_maybe_override(ce, lcname)) {
return 0;
}
}
* know the types for covariant checks, but don't need them if we can ensure
* compatibility through a simple string comparison. We could improve this using
* a more general version of zend_can_early_bind(). */
- if (!preload_all_types_known(ce)) {
+ if (!preload_needed_types_known(ce)) {
continue;
}