Re: [PATCH 2/6] treewide: remove using list iterator after loop body as a ptr

From: Xiaomeng Tong
Date: Thu Mar 03 2022 - 03:30:42 EST


> I think this would make sense, it would mean you only assign the containing
> element on valid elements.
>
> I was thinking something along the lines of:
>
> #define list_for_each_entry(pos, head, member) \
> for (struct list_head *list = head->next, typeof(pos) pos; \
> list == head ? 0 : (( pos = list_entry(pos, list, member), 1)); \
> list = list->next)
>
> Although the initialization block of the for loop is not valid C, I'm
> not sure there is any way to declare two variables of a different type
> in the initialization part of the loop.

It can be done using a *nested loop*, like this:

#define list_for_each_entry(pos, head, member) \
for (struct list_head *list = head->next, cond = (struct list_head *)-1; cond == (struct list_head *)-1; cond = NULL) \
for (typeof(pos) pos; \
list == head ? 0 : (( pos = list_entry(pos, list, member), 1)); \
list = list->next)

>
> I believe all this does is get rid of the &pos->member == (head) check
> to terminate the list.

Indeed, although the original way is harmless.

> It alone will not fix any of the other issues that using the iterator
> variable after the loop currently has.

Yes, but I stick with the list_for_each_entry_inside(pos, type, head, member)
way to make the iterator invisiable outside the loop (before and after the loop).
It is maintainable longer-term than "type(pos) pos" one and perfect.
see my explain:
https://lore.kernel.org/lkml/20220302093106.8402-1-xiam0nd.tong@xxxxxxxxx/
and list_for_each_entry_inside(pos, type, head, member) patch here:
https://lore.kernel.org/lkml/20220301075839.4156-3-xiam0nd.tong@xxxxxxxxx/

--
Xiaomeng Tong