Sun, 08 Feb 2026 14:22:13 +0100
incorrect nonnull-attribute for various list.h functions - fixes #796
| CHANGELOG | file | annotate | diff | comparison | revisions | |
| docs/Writerside/topics/about.md | file | annotate | diff | comparison | revisions | |
| src/cx/list.h | file | annotate | diff | comparison | revisions | |
| src/list.c | file | annotate | diff | comparison | revisions |
--- a/CHANGELOG Wed Jan 21 22:47:18 2026 +0100 +++ b/CHANGELOG Sun Feb 08 14:22:13 2026 +0100 @@ -1,7 +1,8 @@ -Version 4.0.1 - tbd +Version 4.0.1 - 2026-02-08 -------------------------- * fixes compilation errors when using a C++ compiler and a high warning level + * fixes incorrect nonnull-attribute for various list.h functions Version 4.0.0 - 2025-12-31 --------------------------
--- a/docs/Writerside/topics/about.md Wed Jan 21 22:47:18 2026 +0100 +++ b/docs/Writerside/topics/about.md Sun Feb 08 14:22:13 2026 +0100 @@ -26,9 +26,10 @@ ## Changelog -### Version 4.0.1 - preview {collapsible="true"} +### Version 4.0.1 - 2026-02-08 {collapsible="true"} * fixes compilation errors when using a C++ compiler and a high warning level +* fixes incorrect nonnull-attribute for various list.h functions ### Version 4.0.0 - 2025-12-31 {collapsible="true"}
--- a/src/cx/list.h Wed Jan 21 22:47:18 2026 +0100 +++ b/src/cx/list.h Sun Feb 08 14:22:13 2026 +0100 @@ -344,6 +344,9 @@ /** * Adds an item to the end of the list. * + * If the list is not storing pointers and a @c NULL pointer is passed as the + * @c elem, this function returns non-zero and sets @c errno to EINVAL. + * * @param list the list * @param elem a pointer to the element to add * @retval zero success @@ -351,7 +354,7 @@ * @see cxListAddArray() * @see cxListEmplace() */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) int cxListAdd(CxList *list, const void *elem); /** @@ -379,6 +382,9 @@ * * If the @p index equals the list @c size, this is effectively cxListAdd(). * + * If the list is not storing pointers and a @c NULL pointer is passed as the + * @c elem, this function returns non-zero and sets @c errno to EINVAL. + * * @param list the list * @param index the index the element shall have * @param elem a pointer to the element to add @@ -388,7 +394,7 @@ * @see cxListInsertBefore() * @see cxListEmplaceAt() */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) int cxListInsert(CxList *list, size_t index, const void *elem); /** @@ -463,12 +469,15 @@ * * If the list is not sorted already, the behavior is undefined. * + * If the list is not storing pointers and a @c NULL pointer is passed as the + * @c elem, this function returns non-zero and sets @c errno to EINVAL. + * * @param list the list * @param elem a pointer to the element to add * @retval zero success * @retval non-zero memory allocation failure */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) int cxListInsertSorted(CxList *list, const void *elem); /** @@ -479,12 +488,15 @@ * It is strongly recommended to use this function only on sorted lists, where * the element, if it is not contained, is inserted at the correct position. * + * If the list is not storing pointers and a @c NULL pointer is passed as the + * @c elem, this function returns non-zero and sets @c errno to EINVAL. + * * @param list the list * @param elem a pointer to the element to add * @retval zero success (also when the element was already in the list) * @retval non-zero memory allocation failure */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) int cxListInsertUnique(CxList *list, const void *elem); /** @@ -576,6 +588,9 @@ * If @p iter is not a list iterator, the behavior is undefined. * If @p iter is a past-the-end iterator, the new element gets appended to the list. * + * If the list is not storing pointers and a @c NULL pointer is passed as the + * @c elem, this function returns non-zero and sets @c errno to EINVAL. + * * @param iter an iterator * @param elem the element to insert * @retval zero success @@ -583,7 +598,7 @@ * @see cxListInsert() * @see cxListInsertBefore() */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) int cxListInsertAfter(CxIterator *iter, const void *elem); /** @@ -595,6 +610,9 @@ * If @p iter is not a list iterator, the behavior is undefined. * If @p iter is a past-the-end iterator, the new element gets appended to the list. * + * If the list is not storing pointers and a @c NULL pointer is passed as the + * @c elem, this function returns non-zero and sets @c errno to EINVAL. + * * @param iter an iterator * @param elem the element to insert * @retval zero success @@ -602,7 +620,7 @@ * @see cxListInsert() * @see cxListInsertAfter() */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) int cxListInsertBefore(CxIterator *iter, const void *elem); /** @@ -879,7 +897,7 @@ * @see cxListIndexValid() * @see cxListContains() */ -CX_EXTERN CX_NONNULL CX_NODISCARD +CX_EXTERN CX_NONNULL_ARG(1) CX_NODISCARD size_t cxListFind(const CxList *list, const void *elem); /** @@ -893,7 +911,7 @@ * @retval false if the element is not contained * @see cxListFind() */ -CX_EXTERN CX_NONNULL CX_NODISCARD +CX_EXTERN CX_NONNULL_ARG(1) CX_NODISCARD bool cxListContains(const CxList* list, const void* elem); /** @@ -918,7 +936,7 @@ * when the element is not found or could not be removed * @see cxListIndexValid() */ -CX_EXTERN CX_NONNULL +CX_EXTERN CX_NONNULL_ARG(1) size_t cxListFindRemove(CxList *list, const void *elem); /**
--- a/src/list.c Wed Jan 21 22:47:18 2026 +0100 +++ b/src/list.c Sun Feb 08 14:22:13 2026 +0100 @@ -29,6 +29,7 @@ #include "cx/list.h" #include <string.h> +#include <errno.h> #include <assert.h> // we don't want to include the full array_list.h. @@ -418,6 +419,10 @@ int cxListAdd(CxList *list, const void *elem) { list->collection.sorted = false; + if (!cxCollectionStoresPointers(list) && elem == NULL) { + errno = EINVAL; + return 1; + } return list->cl->insert_element(list, list->collection.size, cx_ref(list, elem)) == NULL; } @@ -428,6 +433,10 @@ int cxListInsert(CxList *list, size_t index, const void *elem) { list->collection.sorted = false; + if (!cxCollectionStoresPointers(list) && elem == NULL) { + errno = EINVAL; + return 1; + } return list->cl->insert_element(list, index, cx_ref(list, elem)) == NULL; } @@ -465,12 +474,20 @@ int cxListInsertSorted(CxList *list, const void *elem) { assert(cxCollectionSorted(list)); list->collection.sorted = true; + if (!cxCollectionStoresPointers(list) && elem == NULL) { + errno = EINVAL; + return 1; + } return list->cl->insert_sorted(list, cx_ref(list, elem), 1) == 0; } int cxListInsertUnique(CxList *list, const void *elem) { if (cxCollectionSorted(list)) { list->collection.sorted = true; + if (!cxCollectionStoresPointers(list) && elem == NULL) { + errno = EINVAL; + return 1; + } return list->cl->insert_unique(list, cx_ref(list, elem), 1) == 0; } else { if (cxListContains(list, elem)) { @@ -515,12 +532,20 @@ int cxListInsertAfter(CxIterator *iter, const void *elem) { CxList* list = iter->src_handle; list->collection.sorted = false; + if (!cxCollectionStoresPointers(list) && elem == NULL) { + errno = EINVAL; + return 1; + } return list->cl->insert_iter(iter, cx_ref(list, elem), 0); } int cxListInsertBefore(CxIterator *iter, const void *elem) { CxList* list = iter->src_handle; list->collection.sorted = false; + if (!cxCollectionStoresPointers(list) && elem == NULL) { + errno = EINVAL; + return 1; + } return list->cl->insert_iter(iter, cx_ref(list, elem), 1); } @@ -626,10 +651,16 @@ } size_t cxListFind(const CxList *list, const void *elem) { + if (!cxCollectionStoresPointers(list) && elem == NULL) { + return list->collection.size; + } return list->cl->find_remove((CxList*)list, cx_ref(list, elem), false); } bool cxListContains(const CxList* list, const void* elem) { + if (!cxCollectionStoresPointers(list) && elem == NULL) { + return false; + } return list->cl->find_remove((CxList*)list, cx_ref(list, elem), false) < list->collection.size; } @@ -638,6 +669,9 @@ } size_t cxListFindRemove(CxList *list, const void *elem) { + if (!cxCollectionStoresPointers(list) && elem == NULL) { + return list->collection.size; + } return list->cl->find_remove(list, cx_ref(list, elem), true); }