incorrect nonnull-attribute for various list.h functions - fixes #796 default tip

Sun, 08 Feb 2026 14:22:13 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 08 Feb 2026 14:22:13 +0100
changeset 1705
4df57f540e52
parent 1704
7bc94a96a621

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);
 }
 

mercurial