From d92af899b8aa513b77f756da76332b5cec7d21dc Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Fri, 16 Oct 2026 12:45:37 +0100 Subject: [PATCH 1/2] Zend: add type polymorphism to add_{next_}index_TYPE() functions As it is ridiculous that we only have convenient APIs to add types for HashTables wrapped in zvals but not HashTables directly. But now that we require C11 it means we can rely on _Generic to exist. However C's _Generic is an infuriating mess to use as every single branch must be semantically valid even if it is discarded. Not at all confusing behaviour with terrible compiler errors, it took me a while to understand why the "obvious" ways of writing the generics did not work. Until I managed to stumble upon [1] (thank Kagi as Google/DDG have been useless) that explains the observed behaviour. It is possible for us to have parametric genericity because we are branching on pointers. The trick is to create dummy functions that take void* arguments and return a HashTable* rather than trying to use a macro. The C++ side is simple function overloading. [1] https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/#bigbug --- Zend/zend_API.c | 88 +++++++------- Zend/zend_API.h | 46 ++++---- Zend/zend_API_generic.h | 252 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+), 66 deletions(-) create mode 100644 Zend/zend_API_generic.h diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 28439b6e3015..d8b6a5aae399 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2108,201 +2108,201 @@ ZEND_API void add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval } /* }}} */ -ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */ +ZEND_API void add_index_long_ex(HashTable *arg, zend_ulong index, zend_long n) /* {{{ */ { zval tmp; ZVAL_LONG(&tmp, n); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_null(zval *arg, zend_ulong index) /* {{{ */ +ZEND_API void add_index_null_ex(HashTable *arg, zend_ulong index) /* {{{ */ { zval tmp; ZVAL_NULL(&tmp); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_bool(zval *arg, zend_ulong index, bool b) /* {{{ */ +ZEND_API void add_index_bool_ex(HashTable *arg, zend_ulong index, bool b) /* {{{ */ { zval tmp; ZVAL_BOOL(&tmp, b); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */ +ZEND_API void add_index_resource_ex(HashTable *arg, zend_ulong index, zend_resource *r) /* {{{ */ { zval tmp; ZVAL_RES(&tmp, r); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */ +ZEND_API void add_index_double_ex(HashTable *arg, zend_ulong index, double d) /* {{{ */ { zval tmp; ZVAL_DOUBLE(&tmp, d); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */ +ZEND_API void add_index_str_ex(HashTable *arg, zend_ulong index, zend_string *str) /* {{{ */ { zval tmp; ZVAL_STR(&tmp, str); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */ +ZEND_API void add_index_string_ex(HashTable *arg, zend_ulong index, const char *str) /* {{{ */ { zval tmp; ZVAL_STRING(&tmp, str); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */ +ZEND_API void add_index_stringl_ex(HashTable *arg, zend_ulong index, const char *str, size_t length) /* {{{ */ { zval tmp; ZVAL_STRINGL(&tmp, str, length); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_array(zval *arg, zend_ulong index, zend_array *arr) /* {{{ */ +ZEND_API void add_index_array_ex(HashTable *arg, zend_ulong index, zend_array *arr) /* {{{ */ { zval tmp; ZVAL_ARR(&tmp, arr); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_object(zval *arg, zend_ulong index, zend_object *obj) /* {{{ */ +ZEND_API void add_index_object_ex(HashTable *arg, zend_ulong index, zend_object *obj) /* {{{ */ { zval tmp; ZVAL_OBJ(&tmp, obj); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API void add_index_reference(zval *arg, zend_ulong index, zend_reference *ref) /* {{{ */ +ZEND_API void add_index_reference_ex(HashTable *arg, zend_ulong index, zend_reference *ref) /* {{{ */ { zval tmp; ZVAL_REF(&tmp, ref); - zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp); + zend_hash_index_update(arg, index, &tmp); } /* }}} */ -ZEND_API zend_result add_next_index_long(zval *arg, zend_long n) /* {{{ */ +ZEND_API zend_result add_next_index_long_ex(HashTable *arg, zend_long n) /* {{{ */ { zval tmp; ZVAL_LONG(&tmp, n); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_null(zval *arg) /* {{{ */ +ZEND_API zend_result add_next_index_null_ex(HashTable *arg) /* {{{ */ { zval tmp; ZVAL_NULL(&tmp); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_bool(zval *arg, bool b) /* {{{ */ +ZEND_API zend_result add_next_index_bool_ex(HashTable *arg, bool b) /* {{{ */ { zval tmp; ZVAL_BOOL(&tmp, b); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */ +ZEND_API zend_result add_next_index_resource_ex(HashTable *arg, zend_resource *r) /* {{{ */ { zval tmp; ZVAL_RES(&tmp, r); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_double(zval *arg, double d) /* {{{ */ +ZEND_API zend_result add_next_index_double_ex(HashTable *arg, double d) /* {{{ */ { zval tmp; ZVAL_DOUBLE(&tmp, d); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str) /* {{{ */ +ZEND_API zend_result add_next_index_str_ex(HashTable *arg, zend_string *str) /* {{{ */ { zval tmp; ZVAL_STR(&tmp, str); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_string(zval *arg, const char *str) /* {{{ */ +ZEND_API zend_result add_next_index_string_ex(HashTable *arg, const char *str) /* {{{ */ { zval tmp; ZVAL_STRING(&tmp, str); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */ +ZEND_API zend_result add_next_index_stringl_ex(HashTable *arg, const char *str, size_t length) /* {{{ */ { zval tmp; ZVAL_STRINGL(&tmp, str, length); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_array(zval *arg, zend_array *arr) /* {{{ */ +ZEND_API zend_result add_next_index_array_ex(HashTable *arg, zend_array *arr) /* {{{ */ { zval tmp; ZVAL_ARR(&tmp, arr); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_object(zval *arg, zend_object *obj) /* {{{ */ +ZEND_API zend_result add_next_index_object_ex(HashTable *arg, zend_object *obj) /* {{{ */ { zval tmp; ZVAL_OBJ(&tmp, obj); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ -ZEND_API zend_result add_next_index_reference(zval *arg, zend_reference *ref) /* {{{ */ +ZEND_API zend_result add_next_index_reference_ex(HashTable *arg, zend_reference *ref) /* {{{ */ { zval tmp; ZVAL_REF(&tmp, ref); - return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE; + return zend_hash_next_index_insert(arg, &tmp) ? SUCCESS : FAILURE; } /* }}} */ diff --git a/Zend/zend_API.h b/Zend/zend_API.h index d1064970dcd5..a679698e2d41 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -634,34 +634,34 @@ static zend_always_inline void add_assoc_zval(zval *arg, const char *key, zval * add_assoc_zval_ex(arg, key, strlen(key), value); } -ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n); -ZEND_API void add_index_null(zval *arg, zend_ulong index); -ZEND_API void add_index_bool(zval *arg, zend_ulong index, bool b); -ZEND_API void add_index_resource(zval *arg, zend_ulong index, zend_resource *r); -ZEND_API void add_index_double(zval *arg, zend_ulong index, double d); -ZEND_API void add_index_str(zval *arg, zend_ulong index, zend_string *str); -ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str); -ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length); -ZEND_API void add_index_array(zval *arg, zend_ulong index, zend_array *arr); -ZEND_API void add_index_object(zval *arg, zend_ulong index, zend_object *obj); -ZEND_API void add_index_reference(zval *arg, zend_ulong index, zend_reference *ref); +ZEND_API void add_index_long_ex(HashTable *arg, zend_ulong index, zend_long n); +ZEND_API void add_index_null_ex(HashTable *arg, zend_ulong index); +ZEND_API void add_index_bool_ex(HashTable *arg, zend_ulong index, bool b); +ZEND_API void add_index_resource_ex(HashTable *arg, zend_ulong index, zend_resource *r); +ZEND_API void add_index_double_ex(HashTable *arg, zend_ulong index, double d); +ZEND_API void add_index_str_ex(HashTable *arg, zend_ulong index, zend_string *str); +ZEND_API void add_index_string_ex(HashTable *arg, zend_ulong index, const char *str); +ZEND_API void add_index_stringl_ex(HashTable *arg, zend_ulong index, const char *str, size_t length); +ZEND_API void add_index_array_ex(HashTable *arg, zend_ulong index, zend_array *arr); +ZEND_API void add_index_object_ex(HashTable *arg, zend_ulong index, zend_object *obj); +ZEND_API void add_index_reference_ex(HashTable *arg, zend_ulong index, zend_reference *ref); static zend_always_inline zend_result add_index_zval(zval *arg, zend_ulong index, zval *value) { return zend_hash_index_update(Z_ARRVAL_P(arg), index, value) ? SUCCESS : FAILURE; } -ZEND_API zend_result add_next_index_long(zval *arg, zend_long n); -ZEND_API zend_result add_next_index_null(zval *arg); -ZEND_API zend_result add_next_index_bool(zval *arg, bool b); -ZEND_API zend_result add_next_index_resource(zval *arg, zend_resource *r); -ZEND_API zend_result add_next_index_double(zval *arg, double d); -ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str); -ZEND_API zend_result add_next_index_string(zval *arg, const char *str); -ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length); -ZEND_API zend_result add_next_index_array(zval *arg, zend_array *arr); -ZEND_API zend_result add_next_index_object(zval *arg, zend_object *obj); -ZEND_API zend_result add_next_index_reference(zval *arg, zend_reference *ref); +ZEND_API zend_result add_next_index_long_ex(HashTable *arg, zend_long n); +ZEND_API zend_result add_next_index_null_ex(HashTable *arg); +ZEND_API zend_result add_next_index_bool_ex(HashTable *arg, bool b); +ZEND_API zend_result add_next_index_resource_ex(HashTable *arg, zend_resource *r); +ZEND_API zend_result add_next_index_double_ex(HashTable *arg, double d); +ZEND_API zend_result add_next_index_str_ex(HashTable *arg, zend_string *str); +ZEND_API zend_result add_next_index_string_ex(HashTable *arg, const char *str); +ZEND_API zend_result add_next_index_stringl_ex(HashTable *arg, const char *str, size_t length); +ZEND_API zend_result add_next_index_array_ex(HashTable *arg, zend_array *arr); +ZEND_API zend_result add_next_index_object_ex(HashTable *arg, zend_object *obj); +ZEND_API zend_result add_next_index_reference_ex(HashTable *arg, zend_reference *ref); static zend_always_inline zend_result add_next_index_zval(zval *arg, zval *value) { @@ -2696,4 +2696,6 @@ static zend_always_inline bool zend_parse_arg_obj_or_str( END_EXTERN_C() +#include "zend_API_generic.h" + #endif /* ZEND_API_H */ diff --git a/Zend/zend_API_generic.h b/Zend/zend_API_generic.h new file mode 100644 index 000000000000..060793500589 --- /dev/null +++ b/Zend/zend_API_generic.h @@ -0,0 +1,252 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright © Zend Technologies Ltd., a subsidiary company of | + | Perforce Software, Inc., and Contributors. | + +----------------------------------------------------------------------+ + | This source file is subject to the Modified BSD License that is | + | bundled with this package in the file LICENSE, and is available | + | through the World Wide Web at . | + | | + | SPDX-License-Identifier: BSD-3-Clause | + +----------------------------------------------------------------------+ +*/ +#ifndef ZEND_API_HELPER_H +#define ZEND_API_HELPER_H + +/* Overloaded functions in C++ or _Generic parametric polymorphism in C */ +#if __cplusplus +static inline void add_index_long(zval *arg, zend_ulong index, zend_long n) { + add_index_long_ex(Z_ARR_P(arg), index, n); +} +static inline void add_index_long(HashTable *arg, zend_ulong index, zend_long n) { + add_index_long_ex(arg, index, n); +} + +static inline void add_index_null(zval *arg, zend_ulong index) { + add_index_null_ex(Z_ARR_P(arg), index); +} +static inline void add_index_null(HashTable *arg, zend_ulong index) { + add_index_null_ex(arg, index); +} + +static inline void add_index_bool(zval *arg, zend_ulong index, bool b) { + add_index_bool_ex(Z_ARR_P(arg), index, b); +} +static inline void add_index_bool(HashTable *arg, zend_ulong index, bool b) { + add_index_bool_ex(arg, index, b); +} + +static inline void add_index_resource(zval *arg, zend_ulong index, zend_resource *r) { + add_index_resource_ex(Z_ARR_P(arg), index, r); +} +static inline void add_index_resource(HashTable *arg, zend_ulong index, zend_resource *r) { + add_index_resource_ex(arg, index, r); +} + +static inline void add_index_double(zval *arg, zend_ulong index, double d) { + add_index_double_ex(Z_ARR_P(arg), index, d); +} +static inline void add_index_double(HashTable *arg, zend_ulong index, double d) { + add_index_double_ex(arg, index, d); +} + +static inline void add_index_str(zval *arg, zend_ulong index, zend_string *str) { + add_index_str_ex(Z_ARR_P(arg), index, str); +} +static inline void add_index_str(HashTable *arg, zend_ulong index, zend_string *str) { + add_index_str_ex(arg, index, str); +} + +static inline void add_index_string(zval *arg, zend_ulong index, const char *str) { + add_index_string_ex(Z_ARR_P(arg), index, str); +} +static inline void add_index_string(HashTable *arg, zend_ulong index, const char *str) { + add_index_string_ex(arg, index, str); +} + +static inline void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) { + add_index_stringl_ex(Z_ARR_P(arg), index, str, length); +} +static inline void add_index_stringl(HashTable *arg, zend_ulong index, const char *str, size_t length) { + add_index_stringl_ex(arg, index, str, length); +} + +static inline void add_index_array(zval *arg, zend_ulong index, zend_array *arr) { + add_index_array_ex(Z_ARR_P(arg), index, arr); +} +static inline void add_index_array(HashTable *arg, zend_ulong index, zend_array *arr) { + add_index_array_ex(arg, index, arr); +} + +static inline void add_index_object(zval *arg, zend_ulong index, zend_object *obj) { + add_index_object_ex(Z_ARR_P(arg), index, obj); +} +static inline void add_index_object(HashTable *arg, zend_ulong index, zend_object *obj) { + add_index_object_ex(arg, index, obj); +} + +static inline void add_index_reference(zval *arg, zend_ulong index, zend_reference *ref) { + add_index_reference_ex(Z_ARR_P(arg), index, ref); +} +static inline void add_index_reference(HashTable *arg, zend_ulong index, zend_reference *ref) { + add_index_reference_ex(arg, index, ref); +} + +static inline zend_result add_next_index_long(zval *arg, zend_long n) { + return add_next_index_long_ex(Z_ARR_P(arg), n); +} +static inline zend_result add_next_index_long(HashTable *arg, zend_long n) { + return add_next_index_long_ex(arg, n); +} + +static inline zend_result add_next_index_null(zval *arg) { + return add_next_index_null_ex(Z_ARR_P(arg)); +} +static inline zend_result add_next_index_null(HashTable *arg) { + return add_next_index_null_ex(arg); +} + +static inline zend_result add_next_index_bool(zval *arg, bool b) { + return add_next_index_bool_ex(Z_ARR_P(arg), b); +} +static inline zend_result add_next_index_bool(HashTable *arg, bool b) { + return add_next_index_bool_ex(arg, b); +} + +static inline zend_result add_next_index_resource(zval *arg, zend_resource *r) { + return add_next_index_resource_ex(Z_ARR_P(arg), r); +} +static inline zend_result add_next_index_resource(HashTable *arg, zend_resource *r) { + return add_next_index_resource_ex(arg, r); +} + +static inline zend_result add_next_index_double(zval *arg, double d) { + return add_next_index_double_ex(Z_ARR_P(arg), d); +} +static inline zend_result add_next_index_double(HashTable *arg, double d) { + return add_next_index_double_ex(arg, d); +} + +static inline zend_result add_next_index_str(zval *arg, zend_string *str) { + return add_next_index_str_ex(Z_ARR_P(arg), str); +} +static inline zend_result add_next_index_str(HashTable *arg, zend_string *str) { + return add_next_index_str_ex(arg, str); +} + +static inline zend_result add_next_index_string(zval *arg, const char *str) { + return add_next_index_string_ex(Z_ARR_P(arg), str); +} +static inline zend_result add_next_index_string(HashTable *arg, const char *str) { + return add_next_index_string_ex(arg, str); +} + +static inline zend_result add_next_index_stringl(zval *arg, const char *str, size_t length) { + return add_next_index_stringl_ex(Z_ARR_P(arg), str, length); +} +static inline zend_result add_next_index_stringl(HashTable *arg, const char *str, size_t length) { + return add_next_index_stringl_ex(arg, str, length); +} + +static inline zend_result add_next_index_array(zval *arg, zend_array *arr) { + return add_next_index_array_ex(Z_ARR_P(arg), arr); +} +static inline zend_result add_next_index_array(HashTable *arg, zend_array *arr) { + return add_next_index_array_ex(arg, arr); +} + +static inline zend_result add_next_index_object(zval *arg, zend_object *obj) { + return add_next_index_object_ex(Z_ARR_P(arg), obj); +} +static inline zend_result add_next_index_object(HashTable *arg, zend_object *obj) { + return add_next_index_object_ex(arg, obj); +} + +static inline zend_result add_next_index_reference(zval *arg, zend_reference *ref) { + return add_next_index_reference_ex(Z_ARR_P(arg), ref); +} +static inline zend_result add_next_index_reference(HashTable *arg, zend_reference *ref) { + return add_next_index_reference_ex(arg, ref); +} + +#else + +BEGIN_EXTERN_C() +/* One might expect C _Generic to properly branch on parameters of function so that one can do something like: +#define add_index_long(a, i, val) \ + add_index_long_ex( \ + _Generic((a), HashTable *: a, zval *: Z_ARR_P(a) ), \ + i, val) + * or +#define add_index_long(a, val) \ + _Generic( \ + (a), \ + HashTable *: add_index_long_ex((a), (val)), \ + zval *: add_index_long_ex(Z_ARR_P(a), (val))) + + * to work, however it turns out this is not possible as explained in [1] "the discarded expressions still + * have to be semantically valid" which is not possible as a zval* is not a HashTable* + * and a HashTable* is not compatible with the Z_ARR_P macro. + * To have semantically correct branches of *all* generic expressions we create helper functions + * that take a void* and return a HashTable*. + * [1] https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/#bigbug + */ + +static inline HashTable *htid(void *ptr) { return ptr; } +static inline HashTable *z2h(void *ptr) { return Z_ARR_P((zval*)ptr); } + +#define give_me_a_ht(ptr) _Generic(ptr, HashTable* : htid, zval* : z2h) (ptr) + +#define add_index_long(a, i, val) \ + add_index_long_ex(give_me_a_ht(a), i, val) +#define add_index_null(a, i) \ + add_index_null_ex(give_me_a_ht(a), i) +#define add_index_bool(a, i, val) \ + add_index_bool_ex(give_me_a_ht(a), i, val) +#define add_index_resource(a, i, val) \ + add_index_resource_ex(give_me_a_ht(a), i, val) +#define add_index_double(a, i, val) \ + add_index_double_ex(give_me_a_ht(a), i, val) +#define add_index_str(a, i, val) \ + add_index_str_ex(give_me_a_ht(a), i, val) +#define add_index_string(a, i, val) \ + add_index_string_ex(give_me_a_ht(a), i, val) +#define add_index_stringl(a, i, val, len) \ + add_index_stringl_ex(give_me_a_ht(a), i, val, len) +#define add_index_array(a, i, val) \ + add_index_array_ex(give_me_a_ht(a), i, val) +#define add_index_object(a, i, val) \ + add_index_object_ex(give_me_a_ht(a), i, val) +#define add_index_reference(a, i, val) \ + add_index_reference_ex(give_me_a_ht(a), i, val) + +#define add_next_index_long(a, val) \ + add_next_index_long_ex(give_me_a_ht(a), val) +#define add_next_index_null(a) \ + add_next_index_null_ex(give_me_a_ht(a)) +#define add_next_index_bool(a, val) \ + add_next_index_bool_ex(give_me_a_ht(a), val) +#define add_next_index_resource(a, val) \ + add_next_index_resource_ex(give_me_a_ht(a), val) +#define add_next_index_double(a, val) \ + add_next_index_double_ex(give_me_a_ht(a), val) +#define add_next_index_str(a, val) \ + add_next_index_str_ex(give_me_a_ht(a), val) +#define add_next_index_string(a, val) \ + add_next_index_string_ex(give_me_a_ht(a), val) +#define add_next_index_stringl(a, val, len) \ + add_next_index_stringl_ex(give_me_a_ht(a), val, len) +#define add_next_index_array(a, val) \ + add_next_index_array_ex(give_me_a_ht(a), val) +#define add_next_index_object(a, val) \ + add_next_index_object_ex(give_me_a_ht(a), val) +#define add_next_index_reference(a, val) \ + add_next_index_reference_ex(give_me_a_ht(a), val) + +END_EXTERN_C() + +#endif + +#endif From 3cbc1a34b1260d4bda1a1dd80ccf95f31b36289a Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 24 Oct 2026 00:52:57 +0100 Subject: [PATCH 2/2] Show new generic API works in C and C++ mode --- ext/dom/element.c | 4 ++-- ext/intl/collator/collator_convert.cpp | 28 +++++++++----------------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/ext/dom/element.c b/ext/dom/element.c index 5fcffaf42055..8fd9544ba430 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -374,8 +374,8 @@ PHP_METHOD(DOMElement, getAttributeNames) } for (xmlAttrPtr attr = nodep->properties; attr; attr = attr->next) { - ZVAL_STR(&tmp, dom_node_get_node_name_attribute_or_element((const xmlNode *) attr, false)); - zend_hash_next_index_insert(ht, &tmp); + zend_string *name = dom_node_get_node_name_attribute_or_element((const xmlNode *) attr, false); + add_next_index_str(ht, name); } } /* }}} end DOMElement::getAttributeNames() */ diff --git a/ext/intl/collator/collator_convert.cpp b/ext/intl/collator/collator_convert.cpp index 7edfe61839e2..7f8fb1740e35 100644 --- a/ext/intl/collator/collator_convert.cpp +++ b/ext/intl/collator/collator_convert.cpp @@ -57,7 +57,6 @@ static void collator_convert_hash_item_from_utf8_to_utf16( { const char* old_val; size_t old_val_len; - zval znew_val; /* Process string values only. */ if( Z_TYPE_P( hashData ) != IS_STRING ) @@ -72,15 +71,12 @@ static void collator_convert_hash_item_from_utf8_to_utf16( return; /* Update current hash item with the converted value. */ - ZVAL_NEW_STR( &znew_val, zstr ); - - if( hashKey) - { + if (hashKey) { + zval znew_val; + ZVAL_NEW_STR( &znew_val, zstr ); zend_hash_update( hash, hashKey, &znew_val); - } - else /* hashKeyType == HASH_KEY_IS_LONG */ - { - zend_hash_index_update( hash, hashIndex, &znew_val); + } else /* hashKeyType == HASH_KEY_IS_LONG */ { + add_index_str(hash, hashIndex, zstr); } } /* }}} */ @@ -93,7 +89,6 @@ static void collator_convert_hash_item_from_utf16_to_utf8( const char* old_val; size_t old_val_len; zend_string* u8str; - zval znew_val; /* Process string values only. */ if( Z_TYPE_P( hashData ) != IS_STRING ) @@ -109,15 +104,12 @@ static void collator_convert_hash_item_from_utf16_to_utf8( return; /* Update current hash item with the converted value. */ - ZVAL_NEW_STR( &znew_val, u8str); - - if( hashKey ) - { + if (hashKey) { + zval znew_val; + ZVAL_NEW_STR( &znew_val, u8str ); zend_hash_update( hash, hashKey, &znew_val); - } - else /* hashKeyType == HASH_KEY_IS_LONG */ - { - zend_hash_index_update( hash, hashIndex, &znew_val); + } else /* hashKeyType == HASH_KEY_IS_LONG */ { + add_index_str(hash, hashIndex, u8str); } } /* }}} */