#include <os/alloc_util.h>
os/alloc_util.h
@macro os_is_ptr_like
@abstract
Tell whether the given expression resembles a pointer.
@discussion
When pointer bounds are enabled, only types that are actually classified
as pointers will be considered pointer-like. Otherwise, any pointer-sized
type will be considered pointer-like.
@param P the expression to be checked
macroos_is_ptr_like
#define os_is_ptr_like(P) /* NOLINTNEXTLINE(bugprone-sizeof-expression) */ (sizeof(P) == sizeof(void *))
macroos_ptr_load_and_erase
@macro os_ptr_load_and_erase
@abstract Load the value of @c elem into a temporary, set @c elem to NULL, and
return the value.
@param elem the pointer whose value will be taken, and which will
be set to NULL.
#define os_ptr_load_and_erase(elem) ({
_Static_assert(os_is_ptr_like(elem),
"elem isn't pointer sized");
__auto_type *__single __eptr = &(elem);
__auto_type __elem = *__eptr;
_Pragma("clang diagnostic push")
_Pragma("clang diagnostic ignored \"-Wold-style-cast\"")
*__eptr = (__typeof__(__elem))NULL;
_Pragma("clang diagnostic pop")
__elem;
})macroos_get_pointee_type
The reason we're using the compiler builtins is that those are able to
properly deal with __ptrauth-qualified pointers, unlike template
specializations. Moreover, template specializations would require forwarding
type definitions, and currently __attribute__((xnu_usage_semantics(...)))
annotations are not carried over across typedefs.
It is safe to assume that if the compiler does not support such builtins,
it also does not implement D150875, and we can therefore safely dereference
void pointers.
#define os_get_pointee_type(ptr) __remove_pointer(__remove_reference_t(__typeof__(ptr)))