diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-01-06 16:06:51 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-01-12 10:14:41 +0100 |
commit | 973138f39da192b3948b981b442401c30c8b80bc (patch) | |
tree | 63b8736562bd830ebb988bcda942083c9dac6e08 /Zend/zend_API.c | |
parent | bc0f78a2dae1dd3191440883c4f5b06f9bc03901 (diff) | |
download | php-git-973138f39da192b3948b981b442401c30c8b80bc.tar.gz |
Add support for union types for internal functions
This closes the last hole in the supported types for internal
function arginfo types. It's now possible to represent unions of
multiple classes. This is done by storing them as TypeA|TypeB and
PHP will then convert this into an appropriate union type list.
Closes GH-6581.
Diffstat (limited to 'Zend/zend_API.c')
-rw-r--r-- | Zend/zend_API.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 58b743e641..11760d50f0 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2455,10 +2455,40 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend for (i = 0; i < num_args; i++) { if (ZEND_TYPE_HAS_CLASS(new_arg_info[i].type)) { ZEND_ASSERT(ZEND_TYPE_HAS_NAME(new_arg_info[i].type) - && "Only simple classes are currently supported"); + && "Should be stored as simple name"); 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)); + + size_t num_types = 1; + const char *p = class_name; + while ((p = strchr(p, '|'))) { + num_types++; + p++; + } + + if (num_types == 1) { + /* Simple class type */ + ZEND_TYPE_SET_PTR(new_arg_info[i].type, + zend_string_init_interned(class_name, strlen(class_name), 1)); + } else { + /* Union type */ + zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types)); + list->num_types = num_types; + ZEND_TYPE_SET_LIST(new_arg_info[i].type, list); + + const char *start = class_name; + uint32_t j = 0; + while (true) { + const char *end = strchr(start, '|'); + zend_string *str = + zend_string_init(start, end ? end - start : strlen(start), 1); + list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0); + if (!end) { + break; + } + start = end + 1; + j++; + } + } } } } |