diff --git a/src/include/c.h b/src/include/c.h index 367b32c5b6f..b285755e8c4 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -304,6 +304,21 @@ extern "C++" #define pg_attribute_nonnull(...) #endif +/* + * pg_attribute_returns_nonnull means the function never returns NULL. It + * must be placed in front of the declaration, which is where the MSVC + * annotation _Ret_notnull_ requires it to be. + * + * https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html#index-returns_005fnonnull + */ +#if __has_attribute (returns_nonnull) +#define pg_attribute_returns_nonnull __attribute__((returns_nonnull)) +#elif defined(_MSC_VER) +#define pg_attribute_returns_nonnull _Ret_notnull_ +#else +#define pg_attribute_returns_nonnull +#endif + /* * pg_attribute_target allows specifying different target options that the * function should be compiled with (e.g., for using special CPU instructions). diff --git a/src/include/common/fe_memutils.h b/src/include/common/fe_memutils.h index d5c6d37bb66..0db64ab4389 100644 --- a/src/include/common/fe_memutils.h +++ b/src/include/common/fe_memutils.h @@ -34,11 +34,11 @@ * "Safe" memory allocation functions --- these exit(1) on failure * (except pg_malloc_extended with MCXT_ALLOC_NO_OOM) */ -extern char *pg_strdup(const char *in); -extern void *pg_malloc(size_t size); -extern void *pg_malloc0(size_t size); +pg_attribute_returns_nonnull extern char *pg_strdup(const char *in); +pg_attribute_returns_nonnull extern void *pg_malloc(size_t size); +pg_attribute_returns_nonnull extern void *pg_malloc0(size_t size); extern void *pg_malloc_extended(size_t size, int flags); -extern void *pg_realloc(void *ptr, size_t size); +pg_attribute_returns_nonnull extern void *pg_realloc(void *ptr, size_t size); extern void pg_free(void *ptr); /* @@ -46,10 +46,10 @@ extern void pg_free(void *ptr); */ extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); -extern void *pg_malloc_mul(Size s1, Size s2); -extern void *pg_malloc0_mul(Size s1, Size s2); +pg_attribute_returns_nonnull extern void *pg_malloc_mul(Size s1, Size s2); +pg_attribute_returns_nonnull extern void *pg_malloc0_mul(Size s1, Size s2); extern void *pg_malloc_mul_extended(Size s1, Size s2, int flags); -extern void *pg_realloc_mul(void *p, Size s1, Size s2); +pg_attribute_returns_nonnull extern void *pg_realloc_mul(void *p, Size s1, Size s2); /* * Variants with easier notation and more type safety @@ -75,17 +75,17 @@ extern void *pg_realloc_mul(void *p, Size s1, Size s2); #define pg_realloc_array(pointer, type, count) ((type *) pg_realloc_mul(pointer, sizeof(type), count)) /* Equivalent functions, deliberately named the same as backend functions */ -extern char *pstrdup(const char *in); -extern char *pnstrdup(const char *in, Size size); -extern void *palloc(Size size); -extern void *palloc0(Size size); +pg_attribute_returns_nonnull extern char *pstrdup(const char *in); +pg_attribute_returns_nonnull extern char *pnstrdup(const char *in, Size size); +pg_attribute_returns_nonnull extern void *palloc(Size size); +pg_attribute_returns_nonnull extern void *palloc0(Size size); extern void *palloc_extended(Size size, int flags); -extern void *repalloc(void *pointer, Size size); +pg_attribute_returns_nonnull extern void *repalloc(void *pointer, Size size); extern void pfree(void *pointer); -extern void *palloc_mul(Size s1, Size s2); -extern void *palloc0_mul(Size s1, Size s2); +pg_attribute_returns_nonnull extern void *palloc_mul(Size s1, Size s2); +pg_attribute_returns_nonnull extern void *palloc0_mul(Size s1, Size s2); extern void *palloc_mul_extended(Size s1, Size s2, int flags); -extern void *repalloc_mul(void *p, Size s1, Size s2); +pg_attribute_returns_nonnull extern void *repalloc_mul(void *p, Size s1, Size s2); #define palloc_object(type) ((type *) palloc(sizeof(type))) #define palloc0_object(type) ((type *) palloc0(sizeof(type))) @@ -95,7 +95,7 @@ extern void *repalloc_mul(void *p, Size s1, Size s2); #define repalloc_array(pointer, type, count) ((type *) repalloc_mul(pointer, sizeof(type), count)) /* sprintf into a palloc'd buffer --- these are in psprintf.c */ -extern char *psprintf(const char *fmt, ...) pg_attribute_printf(1, 2); +pg_attribute_returns_nonnull extern char *psprintf(const char *fmt, ...) pg_attribute_printf(1, 2); extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0); #endif /* FE_MEMUTILS_H */ diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h index 0e934158b60..0c7452fe30d 100644 --- a/src/include/utils/palloc.h +++ b/src/include/utils/palloc.h @@ -68,21 +68,21 @@ extern PGDLLIMPORT MemoryContext CurrentMemoryContext; /* * Fundamental memory-allocation operations (more are in utils/memutils.h) */ -extern void *MemoryContextAlloc(MemoryContext context, Size size); -extern void *MemoryContextAllocZero(MemoryContext context, Size size); +pg_attribute_returns_nonnull extern void *MemoryContextAlloc(MemoryContext context, Size size); +pg_attribute_returns_nonnull extern void *MemoryContextAllocZero(MemoryContext context, Size size); extern void *MemoryContextAllocExtended(MemoryContext context, Size size, int flags); extern void *MemoryContextAllocAligned(MemoryContext context, Size size, Size alignto, int flags); -extern void *palloc(Size size); -extern void *palloc0(Size size); +pg_attribute_returns_nonnull extern void *palloc(Size size); +pg_attribute_returns_nonnull extern void *palloc0(Size size); extern void *palloc_extended(Size size, int flags); extern void *palloc_aligned(Size size, Size alignto, int flags); -pg_nodiscard extern void *repalloc(void *pointer, Size size); +pg_nodiscard pg_attribute_returns_nonnull extern void *repalloc(void *pointer, Size size); pg_nodiscard extern void *repalloc_extended(void *pointer, Size size, int flags); -pg_nodiscard extern void *repalloc0(void *pointer, Size oldsize, Size size); +pg_nodiscard pg_attribute_returns_nonnull extern void *repalloc0(void *pointer, Size oldsize, Size size); extern void pfree(void *pointer); /* @@ -90,10 +90,10 @@ extern void pfree(void *pointer); */ extern Size add_size(Size s1, Size s2); extern Size mul_size(Size s1, Size s2); -extern void *palloc_mul(Size s1, Size s2); -extern void *palloc0_mul(Size s1, Size s2); +pg_attribute_returns_nonnull extern void *palloc_mul(Size s1, Size s2); +pg_attribute_returns_nonnull extern void *palloc0_mul(Size s1, Size s2); extern void *palloc_mul_extended(Size s1, Size s2, int flags); -pg_nodiscard extern void *repalloc_mul(void *p, Size s1, Size s2); +pg_nodiscard pg_attribute_returns_nonnull extern void *repalloc_mul(void *p, Size s1, Size s2); pg_nodiscard extern void *repalloc_mul_extended(void *p, Size s1, Size s2, int flags); @@ -123,8 +123,8 @@ pg_nodiscard extern void *repalloc_mul_extended(void *p, Size s1, Size s2, #define repalloc_array_extended(pointer, type, count, flags) ((type *) repalloc_mul_extended(pointer, sizeof(type), count, flags)) /* Higher-limit allocators. */ -extern void *MemoryContextAllocHuge(MemoryContext context, Size size); -pg_nodiscard extern void *repalloc_huge(void *pointer, Size size); +pg_attribute_returns_nonnull extern void *MemoryContextAllocHuge(MemoryContext context, Size size); +pg_nodiscard pg_attribute_returns_nonnull extern void *repalloc_huge(void *pointer, Size size); /* * Although this header file is nominally backend-only, certain frontend @@ -154,14 +154,14 @@ extern void MemoryContextUnregisterResetCallback(MemoryContext context, * These are like standard strdup() except the copied string is * allocated in a context, not with malloc(). */ -extern char *MemoryContextStrdup(MemoryContext context, const char *string); -extern char *pstrdup(const char *in); -extern char *pnstrdup(const char *in, Size len); +pg_attribute_returns_nonnull extern char *MemoryContextStrdup(MemoryContext context, const char *string); +pg_attribute_returns_nonnull extern char *pstrdup(const char *in); +pg_attribute_returns_nonnull extern char *pnstrdup(const char *in, Size len); -extern char *pchomp(const char *in); +pg_attribute_returns_nonnull extern char *pchomp(const char *in); /* sprintf into a palloc'd buffer --- these are in psprintf.c */ -extern char *psprintf(const char *fmt, ...) pg_attribute_printf(1, 2); +pg_attribute_returns_nonnull extern char *psprintf(const char *fmt, ...) pg_attribute_printf(1, 2); extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0); #endif /* PALLOC_H */