Re: [RFC PATCH 05/13] list.h: Fix parentheses around macro pointer parameter use

From: Mathieu Desnoyers
Date: Mon May 08 2023 - 09:46:46 EST


On 2023-05-08 08:16, Andy Shevchenko wrote:
On Thu, May 04, 2023 at 04:05:19PM -0400, Mathieu Desnoyers wrote:
Add missing parentheses around use of macro argument "pos" in those
patterns to ensure operator precedence behaves as expected:

- typeof(*pos)
- pos->member
- "x = y" is changed for "x = (y)", because "y" can be an expression
containing a comma if it is the result of the expansion of a macro such
as #define eval(...) __VA_ARGS__, which would cause unexpected operator
precedence. This use-case is far-fetched, but we have to choose one
way or the other (with or without parentheses) for consistency,
- x && y is changed for (x) && (y).

Remove useless parentheses around use of macro parameter (head) in the
following pattern:

- list_is_head(pos, (head))

Because comma is the lowest priority operator already, so the extra pair
of parentheses is redundant.

But strictly speaking it might be something like

list_...(..., (a, b))

where (a, b) is the head. No?

The following case still works after removing the extra parentheses around "head" because the parentheses are present where the macro is used:

LIST_HEAD(testlist);

int f2(void)
{
return 1;
}

void f(void)
{
struct list_head *pos;

list_for_each(pos, (f2(), &testlist)) {
//...
}
}

The only use I found that would break is as follows:

LIST_HEAD(testlist);

int f2(void)
{
return 1;
}

#define eval(...) __VA_ARGS__

void f(void)
{
struct list_head *pos;

list_for_each(pos, eval(f2(), &testlist)) {
//...
}
}

Because "eval()" will evaluate "f(), &testlist" with comma and all, without enclosing parentheses.

So the question is: do we want to support this kind-of-odd macro evaluation, considering that it requires adding parentheses around pretty much all macro parameters when used as expressions between commas?

Thanks,

Mathieu

--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com