diff --git a/src/color.h b/src/color.h index 89f562c3..6928c1ec 100644 --- a/src/color.h +++ b/src/color.h @@ -86,6 +86,6 @@ bool color_equals(const Color *clr, const Color *clr2) attr_nonnull(1, 2); char* color_str(const Color *clr) - attr_nonnull(1) attr_returns_nonnull attr_nodiscard; + attr_nonnull(1) attr_returns_allocated; #endif // IGUARD_color_h diff --git a/src/dialog.h b/src/dialog.h index 4534e424..f17fb3a1 100644 --- a/src/dialog.h +++ b/src/dialog.h @@ -61,7 +61,7 @@ typedef struct Dialog { } Dialog; Dialog *dialog_create(void) - attr_returns_nonnull attr_nodiscard; + attr_returns_allocated; void dialog_set_actor(Dialog *d, DialogSide side, DialogActor *actor) attr_nonnull(1); diff --git a/src/hashtable.inc.h b/src/hashtable.inc.h index d9408a05..1d6eed40 100644 --- a/src/hashtable.inc.h +++ b/src/hashtable.inc.h @@ -390,7 +390,7 @@ HT_DECLARE_FUNC(void, destroy, (HT_BASETYPE *ht)) * * Returns the allocated hashtable structure. */ -INLINE attr_returns_nonnull attr_nodiscard +INLINE attr_returns_allocated HT_DECLARE_FUNC(HT_BASETYPE*, new, (void)) { HT_BASETYPE *ht = calloc(1, sizeof(HT_BASETYPE)); HT_FUNC(create)(ht); diff --git a/src/list.h b/src/list.h index 6371319c..dd1ee3b0 100644 --- a/src/list.h +++ b/src/list.h @@ -92,7 +92,7 @@ void* alist_foreach(ListAnchor *list, ListAnchorForeachCallback callback, void * void* alist_callback_free_element(ListAnchor *list, List *elem, void *arg); void alist_free_all(ListAnchor *list) attr_nonnull(1); -ListContainer* list_wrap_container(void *data) attr_nodiscard; +ListContainer* list_wrap_container(void *data) attr_returns_allocated; // type-generic macros diff --git a/src/objectpool.h b/src/objectpool.h index 702db266..0b7fbf7a 100644 --- a/src/objectpool.h +++ b/src/objectpool.h @@ -37,9 +37,9 @@ struct ObjectPoolStats { #define OBJPOOL_ALLOC(typename,max_objects) objpool_alloc(sizeof(typename), max_objects, #typename) #define OBJPOOL_ACQUIRE(pool, type) CASTPTR_ASSUME_ALIGNED(objpool_acquire(pool), type) -ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag) attr_returns_nonnull attr_nodiscard attr_nonnull(3); +ObjectPool *objpool_alloc(size_t obj_size, size_t max_objects, const char *tag) attr_returns_allocated attr_nonnull(3); void objpool_free(ObjectPool *pool) attr_nonnull(1); -void *objpool_acquire(ObjectPool *pool) attr_returns_max_aligned attr_returns_nonnull attr_nodiscard attr_hot attr_nonnull(1); +void *objpool_acquire(ObjectPool *pool) attr_returns_allocated attr_hot attr_nonnull(1); void objpool_release(ObjectPool *pool, void *object) attr_hot attr_nonnull(1, 2); void objpool_get_stats(ObjectPool *pool, ObjectPoolStats *stats) attr_nonnull(1, 2); size_t objpool_object_size(ObjectPool *pool) attr_nonnull(1); diff --git a/src/taskmanager.h b/src/taskmanager.h index 310dd508..338a2c02 100644 --- a/src/taskmanager.h +++ b/src/taskmanager.h @@ -77,7 +77,7 @@ typedef struct TaskParams { * On failure, returns NULL. */ TaskManager* taskmgr_create(uint numthreads, SDL_ThreadPriority prio, const char *name) - attr_nodiscard attr_nonnull(3); + attr_nodiscard attr_returns_max_aligned attr_nonnull(3); /** * Submit a new task to [mgr] described by [params]. It is generally placed at the end of the @@ -94,7 +94,7 @@ TaskManager* taskmgr_create(uint numthreads, SDL_ThreadPriority prio, const char * On failure, returns NULL. */ Task* taskmgr_submit(TaskManager *mgr, TaskParams params) - attr_nonnull(1) attr_nodiscard; + attr_nonnull(1) attr_nodiscard attr_returns_max_aligned; /** * Returns the number of remaining tasks in [mgr]'s queue. diff --git a/src/util/compat.h b/src/util/compat.h index 0f4c28d6..3c8f1877 100644 --- a/src/util/compat.h +++ b/src/util/compat.h @@ -249,6 +249,10 @@ typedef complex max_align_t; #define attr_returns_max_aligned \ attr_returns_aligned(alignof(max_align_t)) +// Shorthand: always returns non-null pointer aligned to max_align_t; no discard. +#define attr_returns_allocated \ + attr_returns_nonnull attr_returns_max_aligned attr_nodiscard + // Structure must not be initialized with an implicit (non-designated) initializer. #if __has_attribute(designated_init) && defined(TAISEI_BUILDCONF_USE_DESIGNATED_INIT) #define attr_designated_init \ diff --git a/src/util/crap.h b/src/util/crap.h index 98a9e112..b294142a 100644 --- a/src/util/crap.h +++ b/src/util/crap.h @@ -13,8 +13,8 @@ #include -void* memdup(const void *src, size_t size); -void inherit_missing_pointers(uint num, void *dest[num], void *const base[num]); +void* memdup(const void *src, size_t size) attr_returns_allocated attr_nonnull(1); +void inherit_missing_pointers(uint num, void *dest[num], void *const base[num]) attr_nonnull(2, 3); bool is_main_thread(void); INLINE uint32_t float_to_bits(float f) { diff --git a/src/util/pixmap.h b/src/util/pixmap.h index 518682b4..282cfc3e 100644 --- a/src/util/pixmap.h +++ b/src/util/pixmap.h @@ -142,9 +142,9 @@ typedef struct Pixmap { PixmapOrigin origin; } Pixmap; -void* pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) attr_nodiscard; -void* pixmap_alloc_buffer_for_copy(const Pixmap *src) attr_nonnull(1) attr_nodiscard; -void* pixmap_alloc_buffer_for_conversion(const Pixmap *src, PixmapFormat format) attr_nonnull(1) attr_nodiscard; +void* pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) attr_returns_allocated; +void* pixmap_alloc_buffer_for_copy(const Pixmap *src) attr_nonnull(1) attr_returns_allocated; +void* pixmap_alloc_buffer_for_conversion(const Pixmap *src, PixmapFormat format) attr_nonnull(1) attr_returns_allocated; void pixmap_copy(const Pixmap *src, Pixmap *dst) attr_nonnull(1, 2); void pixmap_copy_alloc(const Pixmap *src, Pixmap *dst) attr_nonnull(1, 2); @@ -168,6 +168,6 @@ bool pixmap_load_stream(SDL_RWops *stream, Pixmap *dst) attr_nonnull(1, 2) attr_ bool pixmap_load_stream_tga(SDL_RWops *stream, Pixmap *dst) attr_nonnull(1, 2) attr_nodiscard; bool pixmap_check_filename(const char *path); -char* pixmap_source_path(const char *prefix, const char *path); +char* pixmap_source_path(const char *prefix, const char *path) attr_nodiscard; #endif // IGUARD_util_pixmap_h diff --git a/src/util/sha256.h b/src/util/sha256.h index 174e8114..191246c9 100644 --- a/src/util/sha256.h +++ b/src/util/sha256.h @@ -15,7 +15,7 @@ typedef struct SHA256State SHA256State; -SHA256State* sha256_new(void) attr_nodiscard; +SHA256State* sha256_new(void) attr_returns_allocated; void sha256_update(SHA256State *state, const uint8_t *data, size_t len) attr_nonnull(1, 2); void sha256_final(SHA256State *state, uint8_t hash[SHA256_BLOCK_SIZE], size_t hashlen) attr_nonnull(1, 2); void sha256_free(SHA256State *state); diff --git a/src/util/stringops.h b/src/util/stringops.h index 62afe7f1..392dd8ed 100644 --- a/src/util/stringops.h +++ b/src/util/stringops.h @@ -29,10 +29,9 @@ #undef strdup #define strdup _ts_strdup -INLINE attr_returns_max_aligned attr_nonnull(1) char *strdup(const char *str) { - char *s = malloc(strlen(str) + 1); - strcpy(s, str); - return s; +INLINE attr_returns_allocated attr_nonnull(1) char *strdup(const char *str) { + size_t sz = strlen(str) + 1; + return memcpy(malloc(sz), str, sz); } #undef strtok_r @@ -47,23 +46,23 @@ bool strstartswith(const char *s, const char *p) attr_pure; bool strendswith_any(const char *s, const char **earray) attr_pure; bool strstartswith_any(const char *s, const char **earray) attr_pure; void stralloc(char **dest, const char *src); -char* strjoin(const char *first, ...) attr_sentinel; -char* vstrfmt(const char *fmt, va_list args); -char* strfmt(const char *fmt, ...) attr_printf(1, 2); +char* strjoin(const char *first, ...) attr_sentinel attr_returns_allocated; +char* vstrfmt(const char *fmt, va_list args) attr_returns_allocated; +char* strfmt(const char *fmt, ...) attr_printf(1, 2) attr_returns_allocated; void strip_trailing_slashes(char *buf); char* strtok_r(char *str, const char *delim, char **nextp); char* strappend(char **dst, char *src); -char* strftimealloc(const char *fmt, const struct tm *timeinfo); +char* strftimealloc(const char *fmt, const struct tm *timeinfo) attr_returns_allocated; void expand_escape_sequences(char *str); uint32_t* ucs4chr(const uint32_t *ucs4, uint32_t chr); size_t ucs4len(const uint32_t *ucs4); void utf8_to_ucs4(const char *utf8, size_t bufsize, uint32_t buf[bufsize]) attr_nonnull(1, 3); -uint32_t* utf8_to_ucs4_alloc(const char *utf8) attr_nonnull(1) attr_returns_nonnull attr_nodiscard; +uint32_t* utf8_to_ucs4_alloc(const char *utf8) attr_nonnull(1) attr_returns_allocated attr_nonnull(1); void ucs4_to_utf8(const uint32_t *ucs4, size_t bufsize, char buf[bufsize]) attr_nonnull(1, 3); -char* ucs4_to_utf8_alloc(const uint32_t *ucs4) attr_nonnull(1) attr_returns_nonnull attr_nodiscard; +char* ucs4_to_utf8_alloc(const uint32_t *ucs4) attr_nonnull(1) attr_returns_allocated attr_nonnull(1); uint32_t utf8_getch(const char **src) attr_nonnull(1); diff --git a/src/vfs/private.h b/src/vfs/private.h index 62df4ec3..618d9495 100644 --- a/src/vfs/private.h +++ b/src/vfs/private.h @@ -58,16 +58,16 @@ VFSNode* vfs_locate(VFSNode *root, const char *path) attr_nonnull(1, 2) attr_nod // Light wrappers around the virtual functions, safe to call even on nodes that // don't implement the corresponding method. "free" is not included, there should // be no reason to call it. It wouldn't do what you'd expect anyway; use vfs_decref. -char* vfs_node_repr(VFSNode *node, bool try_syspath) attr_nonnull(1); -VFSInfo vfs_node_query(VFSNode *node) attr_nonnull(1) attr_nodiscard; -char* vfs_node_syspath(VFSNode *node) attr_nonnull(1) attr_nodiscard; +char* vfs_node_repr(VFSNode *node, bool try_syspath) attr_returns_allocated attr_nonnull(1); +VFSInfo vfs_node_query(VFSNode *node) attr_nonnull(1) attr_nodiscard attr_nonnull(1); +char* vfs_node_syspath(VFSNode *node) attr_nonnull(1) attr_returns_max_aligned attr_nodiscard attr_nonnull(1); bool vfs_node_mount(VFSNode *mountroot, const char *subname, VFSNode *mountee) attr_nonnull(1, 3); bool vfs_node_unmount(VFSNode *mountroot, const char *subname) attr_nonnull(1); VFSNode* vfs_node_locate(VFSNode *root, const char *path) attr_nonnull(1, 2) attr_nodiscard; const char* vfs_node_iter(VFSNode *node, void **opaque) attr_nonnull(1); void vfs_node_iter_stop(VFSNode *node, void **opaque) attr_nonnull(1); bool vfs_node_mkdir(VFSNode *parent, const char *subdir) attr_nonnull(1); -SDL_RWops* vfs_node_open(VFSNode *filenode, VFSOpenMode mode) attr_nonnull(1); +SDL_RWops* vfs_node_open(VFSNode *filenode, VFSOpenMode mode) attr_nonnull(1) attr_nodiscard; void vfs_hook_on_shutdown(VFSShutdownHandler, void *arg); void vfs_print_tree_recurse(SDL_RWops *dest, VFSNode *root, char *prefix, const char *name) attr_nonnull(1, 2, 3, 4);