fix(templates): generated array macros do not compile with C++
Some checks failed
CI / checks (push) Has been cancelled
CI / sanitize (push) Has been cancelled
CI / build (push) Has been cancelled
CI / check-wasm-stdlib (push) Has been cancelled
Deploy Docs / deploy-docs (push) Has been cancelled

Problem: A set of `array_*` macros (`array_push`, `array_extend`, etc) implicitly convert a `void*` into a different pointer type.  In environments that compile these headers as C++, this implicit conversion is an error.

Solution: This commit adds an `_array_cast` macro that uses `decltype` to cast the `void*` to the proper type when compiling as C++.
This commit is contained in:
Julia Hansbrough 2026-07-08 01:38:37 -07:00 committed by GitHub
parent cce7768b27
commit cc7be1fd47
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 46 additions and 34 deletions

View file

@ -50,12 +50,18 @@ extern "C" {
/// memory allocated for the array's contents.
#define array_clear(self) ((self)->size = 0)
#ifdef __cplusplus
#define _array__cast(self, expr) (decltype((self)->contents))(expr)
#else
#define _array__cast(self, expr) (expr)
#endif
/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
/// less than the array's current capacity, this function has no effect.
#define array_reserve(self, new_capacity) \
((self)->contents = _array__reserve( \
(void *)(self)->contents, &(self)->capacity, \
array_elem_size(self), new_capacity) \
#define array_reserve(self, new_capacity) \
((self)->contents = _array__cast(self, _array__reserve( \
(void *)(self)->contents, &(self)->capacity, \
array_elem_size(self), new_capacity)) \
)
/// Free any memory allocated for this array. Note that this does not free any
@ -71,10 +77,10 @@ extern "C" {
/// Push a new `element` onto the end of the array.
#define array_push(self, element) \
do { \
(self)->contents = _array__grow( \
(self)->contents = _array__cast(self, _array__grow( \
(void *)(self)->contents, (self)->size, &(self)->capacity, \
1, array_elem_size(self) \
); \
)); \
(self)->contents[(self)->size++] = (element); \
} while(0)
@ -83,10 +89,10 @@ extern "C" {
#define array_grow_by(self, count) \
do { \
if ((count) == 0) break; \
(self)->contents = _array__grow( \
(self)->contents = _array__cast(self, _array__grow( \
(self)->contents, (self)->size, &(self)->capacity, \
count, array_elem_size(self) \
); \
)); \
memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
(self)->size += (count); \
} while (0)
@ -98,26 +104,26 @@ extern "C" {
/// Append `count` elements to the end of the array, reading their values from the
/// `contents` pointer.
#define array_extend(self, count, other_contents) \
(self)->contents = _array__splice( \
((self)->contents = _array__cast(self, _array__splice( \
(void*)(self)->contents, &(self)->size, &(self)->capacity, \
array_elem_size(self), (self)->size, 0, count, other_contents \
)
)))
/// Remove `old_count` elements from the array starting at the given `index`. At
/// the same index, insert `new_count` new elements, reading their values from the
/// `new_contents` pointer.
#define array_splice(self, _index, old_count, new_count, new_contents) \
(self)->contents = _array__splice( \
((self)->contents = _array__cast(self, _array__splice( \
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
array_elem_size(self), _index, old_count, new_count, new_contents \
)
)))
/// Insert one `element` into the array at the given `index`.
#define array_insert(self, _index, element) \
(self)->contents = _array__splice( \
((self)->contents = _array__cast(self, _array__splice( \
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
array_elem_size(self), _index, 0, 1, &(element) \
)
)))
/// Remove one element from the array at the given `index`.
#define array_erase(self, _index) \
@ -128,17 +134,17 @@ extern "C" {
/// Assign the contents of one array to another, reallocating if necessary.
#define array_assign(self, other) \
(self)->contents = _array__assign( \
((self)->contents = _array__cast(self, _array__assign( \
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
(const void *)(other)->contents, (other)->size, array_elem_size(self) \
)
)))
/// Swap one array with another
#define array_swap(self, other) \
do { \
void *_array_swap_tmp = (void *)(self)->contents; \
(self)->contents = (other)->contents; \
(other)->contents = _array_swap_tmp; \
(other)->contents = _array__cast(other, _array_swap_tmp); \
_array__swap(&(self)->size, &(self)->capacity, \
&(other)->size, &(other)->capacity); \
} while (0)

View file

@ -50,12 +50,18 @@ extern "C" {
/// memory allocated for the array's contents.
#define array_clear(self) ((self)->size = 0)
#ifdef __cplusplus
#define _array__cast(self, expr) (decltype((self)->contents))(expr)
#else
#define _array__cast(self, expr) (expr)
#endif
/// Reserve `new_capacity` elements of space in the array. If `new_capacity` is
/// less than the array's current capacity, this function has no effect.
#define array_reserve(self, new_capacity) \
((self)->contents = _array__reserve( \
(void *)(self)->contents, &(self)->capacity, \
array_elem_size(self), new_capacity) \
#define array_reserve(self, new_capacity) \
((self)->contents = _array__cast(self, _array__reserve( \
(void *)(self)->contents, &(self)->capacity, \
array_elem_size(self), new_capacity)) \
)
/// Free any memory allocated for this array. Note that this does not free any
@ -71,10 +77,10 @@ extern "C" {
/// Push a new `element` onto the end of the array.
#define array_push(self, element) \
do { \
(self)->contents = _array__grow( \
(self)->contents = _array__cast(self, _array__grow( \
(void *)(self)->contents, (self)->size, &(self)->capacity, \
1, array_elem_size(self) \
); \
)); \
(self)->contents[(self)->size++] = (element); \
} while(0)
@ -83,10 +89,10 @@ extern "C" {
#define array_grow_by(self, count) \
do { \
if ((count) == 0) break; \
(self)->contents = _array__grow( \
(self)->contents = _array__cast(self, _array__grow( \
(self)->contents, (self)->size, &(self)->capacity, \
count, array_elem_size(self) \
); \
)); \
memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \
(self)->size += (count); \
} while (0)
@ -98,26 +104,26 @@ extern "C" {
/// Append `count` elements to the end of the array, reading their values from the
/// `contents` pointer.
#define array_extend(self, count, other_contents) \
(self)->contents = _array__splice( \
((self)->contents = _array__cast(self, _array__splice( \
(void*)(self)->contents, &(self)->size, &(self)->capacity, \
array_elem_size(self), (self)->size, 0, count, other_contents \
)
)))
/// Remove `old_count` elements from the array starting at the given `index`. At
/// the same index, insert `new_count` new elements, reading their values from the
/// `new_contents` pointer.
#define array_splice(self, _index, old_count, new_count, new_contents) \
(self)->contents = _array__splice( \
((self)->contents = _array__cast(self, _array__splice( \
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
array_elem_size(self), _index, old_count, new_count, new_contents \
)
)))
/// Insert one `element` into the array at the given `index`.
#define array_insert(self, _index, element) \
(self)->contents = _array__splice( \
((self)->contents = _array__cast(self, _array__splice( \
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
array_elem_size(self), _index, 0, 1, &(element) \
)
)))
/// Remove one element from the array at the given `index`.
#define array_erase(self, _index) \
@ -128,17 +134,17 @@ extern "C" {
/// Assign the contents of one array to another, reallocating if necessary.
#define array_assign(self, other) \
(self)->contents = _array__assign( \
((self)->contents = _array__cast(self, _array__assign( \
(void *)(self)->contents, &(self)->size, &(self)->capacity, \
(const void *)(other)->contents, (other)->size, array_elem_size(self) \
)
)))
/// Swap one array with another
#define array_swap(self, other) \
do { \
void *_array_swap_tmp = (void *)(self)->contents; \
(self)->contents = (other)->contents; \
(other)->contents = _array_swap_tmp; \
(other)->contents = _array__cast(other, _array_swap_tmp); \
_array__swap(&(self)->size, &(self)->capacity, \
&(other)->size, &(other)->capacity); \
} while (0)