--- a/src/cx/common.h Thu Nov 07 20:22:56 2024 +0100 +++ b/src/cx/common.h Thu Nov 07 22:46:58 2024 +0100 @@ -88,13 +88,166 @@ /** Version constant which ensures to increase monotonically. */ #define UCX_VERSION (((UCX_VERSION_MAJOR)<<16)|UCX_VERSION_MINOR) -// Common Includes +// --------------------------------------------------------------------------- +// Common includes +// --------------------------------------------------------------------------- #include <stdlib.h> #include <stddef.h> #include <stdbool.h> #include <stdint.h> +// --------------------------------------------------------------------------- +// Attribute definitions +// --------------------------------------------------------------------------- + +#ifndef __GNUC__ +/** + * Removes GNU C attributes where they are not supported. + */ +#define __attribute__(x) +#endif + +/** + * All pointer arguments must be non-NULL. + */ +#define cx_attr_nonnull __attribute__((__nonnull__)) + +/** + * The specified pointer arguments must be non-NULL. + */ +#define cx_attr_nonnull_arg(...) __attribute__((__nonnull__(__VA_ARGS__))) + +/** + * The returned value is guaranteed to be non-NULL. + */ +#define cx_attr_returns_nonnull __attribute__((__returns_nonnull__)) + +/** + * The attributed function always returns freshly allocated memory. + */ +#define cx_attr_malloc __attribute__((__malloc__)) + +#ifndef __clang__ +/** + * The pointer returned by the attributed function is supposed to be freed + * by \p freefunc. + * + * @param freefunc the function that shall be used to free the memory + * @param freefunc_arg the index of the pointer argument in \p freefunc + */ +#define cx_attr_dealloc(freefunc, freefunc_arg) \ + __attribute__((__malloc__(freefunc, freefunc_arg))) +#else +/** + * Not supported in clang. + */ +#define cx_attr_dealloc(...) +#endif // __clang__ + +/** + * Shortcut to specify #cxFree() as deallocator. + */ +#define cx_attr_dealloc_ucx cx_attr_dealloc(cxFree, 2) + +/** + * Specifies the parameters from which the allocation size is calculated. + */ +#define cx_attr_allocsize(...) __attribute__((__alloc_size__(__VA_ARGS__))) + + +#ifdef __clang__ +/** + * No support for \c null_terminated_string_arg in clang or GCC below 14. + */ +#define cx_attr_cstr_arg(idx) +/** + * No support for access attribute in clang. + */ +#define cx_attr_access(mode, ...) +#else +#if __GNUC__ < 10 +/** + * No support for access attribute in GCC < 10. + */ +#define cx_attr_access(mode, ...) +#else +/** + * Helper macro to define access macros. + */ +#define cx_attr_access(mode, ...) __attribute__((__access__(mode, __VA_ARGS__))) +#endif // __GNUC__ < 10 +#if __GNUC__ < 14 +/** + * No support for \c null_terminated_string_arg in clang or GCC below 14. + */ +#define cx_attr_cstr_arg(idx) +#else +/** + * The specified argument is expected to be a zero-terminated string. + * + * @param idx the index of the argument + */ +#define cx_attr_cstr_arg(idx) \ + __attribute__((__null_terminated_string_arg__(idx))) +#endif // __GNUC__ < 14 +#endif // __clang__ + + +/** + * Specifies that the function will only read through the given pointer. + * + * Takes one or two arguments: the index of the pointer and (optionally) the + * index of another argument specifying the maximum number of accessed bytes. + */ +#define cx_attr_access_r(...) cx_attr_access(__read_only__, __VA_ARGS__) + +/** + * Specifies that the function will read and write through the given pointer. + * + * Takes one or two arguments: the index of the pointer and (optionally) the + * index of another argument specifying the maximum number of accessed bytes. + */ +#define cx_attr_access_rw(...) cx_attr_access(__read_write__, __VA_ARGS__) + +/** + * Specifies that the function will only write through the given pointer. + * + * Takes one or two arguments: the index of the pointer and (optionally) the + * index of another argument specifying the maximum number of accessed bytes. + */ +#define cx_attr_access_w(...) cx_attr_access(__write_only__, __VA_ARGS__) + +#if __STDC_VERSION__ >= 202300L + +/** + * Do not warn about unused variable. + */ +#define cx_attr_unused [[maybe_unused]] + +/** + * Warn about discarded return value. + */ +#define cx_attr_nodiscard [[nodiscard]] + +#else // no C23 + +/** + * Do not warn about unused variable. + */ +#define cx_attr_unused __attribute__((__unused__)) + +/** + * Warn about discarded return value. + */ +#define cx_attr_nodiscard __attribute__((__warn_unused_result__)) + +#endif // __STDC_VERSION__ + +// --------------------------------------------------------------------------- +// Useful function pointers +// --------------------------------------------------------------------------- + /** * Function pointer compatible with fwrite-like functions. */ @@ -103,7 +256,7 @@ size_t, size_t, void * -); +) cx_attr_nonnull; /** * Function pointer compatible with fread-like functions. @@ -113,7 +266,11 @@ size_t, size_t, void * -); +) cx_attr_nonnull; + +// --------------------------------------------------------------------------- +// Utility macros +// --------------------------------------------------------------------------- /** * Determines the number of members in a static C array. @@ -126,7 +283,10 @@ */ #define cx_nmemb(arr) (sizeof(arr)/sizeof((arr)[0])) -// cx_szmul() definition +// --------------------------------------------------------------------------- +// szmul implementation +// --------------------------------------------------------------------------- + #if (__GNUC__ >= 5 || defined(__clang__)) && !defined(CX_NO_SZMUL_BUILTIN) #define CX_SZMUL_BUILTIN @@ -174,24 +334,18 @@ #endif // cx_szmul -// Compiler specific stuff -#ifndef __GNUC__ -/** - * Removes GNU C attributes where they are not supported. - */ -#define __attribute__(x) -#endif +// --------------------------------------------------------------------------- +// Fixes for MSVC incompatibilities +// --------------------------------------------------------------------------- #ifdef _MSC_VER - // fix missing ssize_t definition #include <BaseTsd.h> typedef SSIZE_T ssize_t; // fix missing _Thread_local support #define _Thread_local __declspec(thread) - -#endif +#endif // _MSC_VER #endif // UCX_COMMON_H