diff --git a/include/grass/defs/gis.h b/include/grass/defs/gis.h index 8bacb260cc2..a3573b7fae5 100644 --- a/include/grass/defs/gis.h +++ b/include/grass/defs/gis.h @@ -81,10 +81,55 @@ int G_adjust_window_ll(struct Cell_head *cellhd); #define G_incr_void_ptr(ptr, size) \ ((void *)((const unsigned char *)(ptr) + (size))) -void *G__malloc(const char *, int, size_t); -void *G__calloc(const char *, int, size_t, size_t); -void *G__realloc(const char *, int, void *, size_t); -void G_free(void *); +// Improve diagnostic capabilities for compilers and/or static analyzers + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#if __has_attribute(malloc) && defined(__GNUC__) && (__GNUC__ >= 11) +#define G_ATTR_MALLOC __attribute__((malloc, malloc(G_free, 1))) +#elif __has_attribute(malloc) +#define G_ATTR_MALLOC __attribute__((malloc)) +#else +#define G_ATTR_MALLOC +#endif + +#if __has_attribute(returns_nonnull) +#define G_ATTR_RET_NONNULL __attribute__((returns_nonnull)) +#else +#define G_ATTR_RET_NONNULL +#endif + +#if __has_attribute(alloc_size) +#define G_ATTR_ALLOC_SIZE1(N) __attribute__((alloc_size(N))) +#define G_ATTR_ALLOC_SIZE2(N, M) __attribute__((alloc_size(N, M))) +#else +#define G_ATTR_ALLOC_SIZE1(N) +#define G_ATTR_ALLOC_SIZE2(N, M) +#endif + +// Clang Static Analyzer ownership annotations +#if defined(__clang__) && __has_attribute(ownership_returns) && \ + __has_attribute(ownership_takes) +#define G_ATTR_OWNSHIP_RET __attribute__((ownership_returns(malloc))) +#define G_ATTR_OWNSHIP_TAKE __attribute__((ownership_takes(malloc, 1))) +#else +#define G_ATTR_OWNSHIP_RET +#define G_ATTR_OWNSHIP_TAKE +#endif + +#define G_MALLOC_ATTR \ + G_ATTR_MALLOC G_ATTR_ALLOC_SIZE1(3) G_ATTR_OWNSHIP_RET G_ATTR_RET_NONNULL +#define G_CALLOC_ATTR \ + G_ATTR_MALLOC G_ATTR_ALLOC_SIZE2(3, 4) G_ATTR_OWNSHIP_RET G_ATTR_RET_NONNULL +#define G_REALLOC_ATTR G_ATTR_ALLOC_SIZE1(4) G_ATTR_RET_NONNULL +#define G_FREE_ATTR G_ATTR_OWNSHIP_TAKE + +void G_free(void *) G_FREE_ATTR; +void *G__malloc(const char *, int, size_t) G_MALLOC_ATTR; +void *G__calloc(const char *, int, size_t, size_t) G_CALLOC_ATTR; +void *G__realloc(const char *, int, void *, size_t) G_REALLOC_ATTR; #ifndef G_incr_void_ptr void *G_incr_void_ptr(const void *, size_t);