diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2024-09-26 18:13:07 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2024-09-30 11:34:10 -0400 |
commit | 90791fc54affb18119e8403efc9320a2a59c9d09 (patch) | |
tree | 9ffcef51a03c1eeab769dc39f0d2afe0e8a91f1f /src | |
parent | e456c6e18ce47279d429b38f0b348e1a5f2b2beb (diff) | |
download | bfs-90791fc54affb18119e8403efc9320a2a59c9d09.tar.xz |
list: Make SLIST_REMOVE() more type-safe
This avoids what might be a strict aliasing violation in some models.
Link: https://github.com/llvm/llvm-project/pull/108385#issuecomment-2352938645
Diffstat (limited to 'src')
-rw-r--r-- | src/list.h | 45 |
1 files changed, 20 insertions, 25 deletions
@@ -82,9 +82,11 @@ #ifndef BFS_LIST_H #define BFS_LIST_H +#include "bfs.h" #include "diag.h" #include <stddef.h> +#include <stdint.h> #include <string.h> /** @@ -372,20 +374,25 @@ #define SLIST_REMOVE_(list, cursor, ...) \ SLIST_REMOVE__((list), (cursor), LIST_NEXT_(__VA_ARGS__)) -#define SLIST_REMOVE__(list, cursor, next) \ - (list->tail = (*cursor)->next ? list->tail : cursor, \ - slist_remove_impl(*cursor, cursor, &(*cursor)->next, sizeof(*cursor))) - -// Helper for SLIST_REMOVE() -static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_t size) { - // ret = *cursor; - // *cursor = ret->next; - memcpy(cursor, next, size); - // ret->next = NULL; - memset(next, 0, size); - return ret; +// Scratch variables for the type-safe SLIST_REMOVE() implementation. +// Not a pointer type due to https://github.com/llvm/llvm-project/issues/109718. +_maybe_unused +static thread_local uintptr_t _slist_prev, _slist_next; + +/** Suppress -Wunused-value. */ +_maybe_unused +static inline void *_slist_cast(uintptr_t ptr) { + return (void *)ptr; } +#define SLIST_REMOVE__(list, cursor, next) \ + (_slist_prev = (uintptr_t)(void *)*cursor, \ + _slist_next = (uintptr_t)(void *)(*cursor)->next, \ + (*cursor)->next = NULL, \ + *cursor = (void *)_slist_next, \ + list->tail = *cursor ? list->tail : cursor, \ + _slist_cast(_slist_prev)) + /** * Pop the head off a singly-linked list. * @@ -441,19 +448,7 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_ * If specified, use head->node.next rather than head->next. */ #define drain_slist(type, item, ...) \ - drain_slist_(type, item, __VA_ARGS__, ) - -#define drain_slist_(type, item, list, ...) \ - drain_slist__(type, item, (list), LIST_NEXT_(__VA_ARGS__)) - -#define drain_slist__(type, item, list, next) \ - for (type *item = list->head; item && \ - (SLIST_CHECK_(list), \ - list->head = item->next, \ - list->tail = list->head ? list->tail : &list->head, \ - item->next = NULL, \ - true); \ - item = list->head) + for (type *item; (item = SLIST_POP(__VA_ARGS__));) /** * Initialize a doubly-linked list. |