Skip to content

Commit 15b4c4f

Browse files
authored
Merge pull request #191 from sysprog21/list-typeof
Support C23 typeof operator
2 parents 1302947 + b56d64b commit 15b4c4f

File tree

2 files changed

+61
-46
lines changed

2 files changed

+61
-46
lines changed

list.h

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Linux-like doubly-linked list implementation */
1+
/* Linux-like circular doubly-linked list implementation */
22

33
#pragma once
44

@@ -8,11 +8,19 @@ extern "C" {
88

99
#include <stddef.h>
1010

11-
/* "typeof" is a GNU extension.
11+
/**
12+
* Feature detection for 'typeof':
13+
* - Supported as a GNU extension in GCC/Clang.
14+
* - Part of C23 standard (ISO/IEC 9899:2024).
15+
*
1216
* Reference: https://gcc.gnu.org/onlinedocs/gcc/Typeof.html
1317
*/
14-
#if defined(__GNUC__) || defined(__clang__)
18+
#if defined(__GNUC__) || defined(__clang__) || \
19+
(defined(__STDC__) && defined(__STDC_VERSION__) && \
20+
(__STDC_VERSION__ >= 202311L)) /* C23 ?*/
1521
#define __LIST_HAVE_TYPEOF 1
22+
#else
23+
#define __LIST_HAVE_TYPEOF 0
1624
#endif
1725

1826
/**
@@ -46,11 +54,11 @@ struct list_head {
4654
* Return: @type pointer of structure containing ptr
4755
*/
4856
#ifndef container_of
49-
#ifdef __LIST_HAVE_TYPEOF
50-
#define container_of(ptr, type, member) \
51-
__extension__({ \
52-
const __typeof__(((type *) 0)->member) *__pmember = (ptr); \
53-
(type *) ((char *) __pmember - offsetof(type, member)); \
57+
#if __LIST_HAVE_TYPEOF
58+
#define container_of(ptr, type, member) \
59+
__extension__({ \
60+
const typeof(((type *) 0)->member) *__pmember = (ptr); \
61+
(type *) ((char *) __pmember - offsetof(type, member)); \
5462
})
5563
#else
5664
#define container_of(ptr, type, member) \
@@ -379,54 +387,61 @@ static inline void list_move_tail(struct list_head *node,
379387
for (node = (head)->next; node != (head); node = node->next)
380388

381389
/**
382-
* list_for_each_entry - Iterate over list entries
383-
* @entry: pointer used as iterator
384-
* @head: pointer to the head of the list
385-
* @member: name of the list_head member variable in struct type of @entry
386-
*
387-
* The nodes and the head of the list must be kept unmodified while
388-
* iterating through it. Any modifications to the the list will cause undefined
389-
* behavior.
390-
*
391-
* FIXME: remove dependency of __typeof__ extension
390+
* list_for_each_entry - Iterate over a list of entries
391+
* @entry: Pointer to the structure type, used as the loop iterator.
392+
* @head: Pointer to the list_head structure representing the list head.
393+
* @member: Name of the list_head member within the structure type of @entry.
394+
*
395+
* Iterates over a circular doubly-linked list, starting from the first node
396+
* after @head until reaching @head again. The macro assumes the list structure
397+
* remains unmodified during iteration; any changes (e.g., adding/removing
398+
* nodes) may result in undefined behavior.
392399
*/
393-
#ifdef __LIST_HAVE_TYPEOF
394-
#define list_for_each_entry(entry, head, member) \
395-
for (entry = list_entry((head)->next, __typeof__(*entry), member); \
396-
&entry->member != (head); \
397-
entry = list_entry(entry->member.next, __typeof__(*entry), member))
400+
#if __LIST_HAVE_TYPEOF
401+
#define list_for_each_entry(entry, head, member) \
402+
for (entry = list_entry((head)->next, typeof(*entry), member); \
403+
&entry->member != (head); \
404+
entry = list_entry(entry->member.next, typeof(*entry), member))
398405
#endif
399406

400407
/**
401-
* list_for_each_safe - Iterate over list nodes and allow deletions
402-
* @node: list_head pointer used as iterator
403-
* @safe: list_head pointer used to store info for next entry in list
404-
* @head: pointer to the head of the list
405-
*
406-
* The current node (iterator) is allowed to be removed from the list. Any
407-
* other modifications to the the list will cause undefined behavior.
408+
* list_for_each_safe - Iterate over list nodes, allowing removal
409+
* @node: Pointer to a list_head structure, used as the loop iterator.
410+
* @safe: Pointer to a list_head structure, storing the next node for safe
411+
* iteration.
412+
* @head: Pointer to the list_head structure representing the list head.
413+
*
414+
* Iterates over a circular doubly-linked list, starting from the first node
415+
* after @head and continuing until reaching @head again. This macro allows
416+
* safe removal of the current node (@node) during iteration by pre-fetching
417+
* the next node into @safe. Other modifications to the list structure (e.g.,
418+
* adding nodes or altering @head) may result in undefined behavior.
408419
*/
409420
#define list_for_each_safe(node, safe, head) \
410421
for (node = (head)->next, safe = node->next; node != (head); \
411422
node = safe, safe = node->next)
412423

413424
/**
414-
* list_for_each_entry_safe - Iterate over list entries and allow deletes
415-
* @entry: pointer used as iterator
416-
* @safe: @type pointer used to store info for next entry in list
417-
* @head: pointer to the head of the list
418-
* @member: name of the list_head member variable in struct type of @entry
419-
*
420-
* The current node (iterator) is allowed to be removed from the list. Any
421-
* other modifications to the the list will cause undefined behavior.
422-
*
423-
* FIXME: remove dependency of __typeof__ extension
425+
* list_for_each_entry_safe - Iterate over a list, allowing node removal
426+
* @entry: Pointer to the structure type, used as the loop iterator.
427+
* @safe: Pointer to the structure type, storing the next entry for safe
428+
* iteration.
429+
* @head: Pointer to the list_head structure representing the list head.
430+
* @member: Name of the list_head member within the structure type of @entry.
431+
*
432+
* Iterates over a circular doubly-linked list, starting from the first node
433+
* after @head and continuing until reaching @head again. This macro permits
434+
* safe removal of the current node (@entry) during iteration by pre-fetching
435+
* the next node into @safe. Other modifications to the list structure (e.g.,
436+
* adding nodes or altering @head) may result in undefined behavior.
424437
*/
425-
#define list_for_each_entry_safe(entry, safe, head, member) \
426-
for (entry = list_entry((head)->next, __typeof__(*entry), member), \
427-
safe = list_entry(entry->member.next, __typeof__(*entry), member); \
428-
&entry->member != (head); entry = safe, \
429-
safe = list_entry(safe->member.next, __typeof__(*entry), member))
438+
#if __LIST_HAVE_TYPEOF
439+
#define list_for_each_entry_safe(entry, safe, head, member) \
440+
for (entry = list_entry((head)->next, typeof(*entry), member), \
441+
safe = list_entry(entry->member.next, typeof(*entry), member); \
442+
&entry->member != (head); entry = safe, \
443+
safe = list_entry(safe->member.next, typeof(*entry), member))
444+
#endif
430445

431446
#undef __LIST_HAVE_TYPEOF
432447

scripts/checksums

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
db6784ff3917888db4d1dceaa0570d99ed40e762 queue.h
2-
bfb6df45d64356868c86a7173455d39970bd0270 list.h
2+
53de5d72c52d63b706c7060c6020077f5ac59663 list.h
33
3bb0192cee08d165fd597a9f6fbb404533e28fcf scripts/check-commitlog.sh

0 commit comments

Comments
 (0)