[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 5 May 2023 10:23:57 -0400
From: Mathieu Desnoyers <mathieu.desnoyers@...icios.com>
To: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: "Huang, Ying" <ying.huang@...el.com>,
Andrew Morton <akpm@...ux-foundation.org>,
linux-kernel@...r.kernel.org, Peter Zijlstra <peterz@...radead.org>
Subject: Re: [RFC PATCH 4/4] llist.h: Fix parentheses around macro pointer
parameter use
On 2023-05-04 13:16, Linus Torvalds wrote:
> On Thu, May 4, 2023 at 7:54 AM Mathieu Desnoyers
> <mathieu.desnoyers@...icios.com> wrote:
>> +#define list_prepare_entry(pos, head, member) \
>> + ((pos) ? : list_entry(head, typeof(*pos), member))
>>
>> So even though the fact that "pos" is used as an lvalue specifically in
>> llist_for_each_entry_safe() makes it so that the parentheses are not
>> strictly required around "pos" in typeof(*pos), I argue that we should
>> still add those for consistency.
>
> Ack. It may not matter in reality because of how 'pos' is supposed to
> be just a local variable name, but I agree that for consistency our
> macros should still follow the usual pattern.
>
> Of course, *because* of how 'pos' is not some random expression, and
> is supposed to be that local variable, and because of how it is used,
> it must always violate the whole "only use once" usual pattern,.
>
> Exactly the same way the member name is also typically used multiple
> times because of how it's not an expression, but really a "part of the
> syntax".
>
> So an alternative might be that we should use a different syntax for
> those things and make it clear that they are not normal expressions.
> Some people use upper-case names for special things like that to make
> them stand out as "not normal" (kind of the same way upper-case macros
> themselves were a warning that they weren't normal and might evaluate
> arguments multiple times).
Is a list iteration position absolutely required to be a local variable,
or can it be a dereferenced pointer ?
Let's say we take "list_for_each()" as example:
#define list_for_each(pos, head) \
for (pos = (head)->next; !list_is_head(pos, head); pos = pos->next)
and turn "pos" into "POS" to make it clearer that it is used as an lvalue:
#define list_for_each(POS, head) \
for (POS = (head)->next; !list_is_head(POS, head); pos = POS->next)
The following usage pattern is still broken:
struct list_head list;
void f(struct list_head **ppos)
{
list_for_each(*ppos, &list) {
//...
}
}
Because ->next has higher operator precedence than "*", which is unexpected.
I would argue that even if we choose to capitalize the macro special arguments used
as lvalues and as member names so they stand out, it does not eliminate the need to
be careful about proper use of parentheses around those parameters when they are also
used as rvalues.
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com
Powered by blists - more mailing lists