From: Al Viro <viro@zeniv.linux.org.uk>
To: Eric Zhang <zxh@xh-zhang.com>
Cc: linux-sparse@vger.kernel.org, dan.carpenter@linaro.org,
chriscli@google.com, ben.dooks@codethink.co.uk,
rf@opensource.cirrus.com, torvalds@linux-foundation.org
Subject: Re: [RFC PATCH] pre-process: add __VA_OPT__ support
Date: Wed, 25 Feb 2026 22:18:51 +0000 [thread overview]
Message-ID: <20260225221851.GE1762976@ZenIV> (raw)
In-Reply-To: <20260225081413.2480484-1-zxh@xh-zhang.com>
On Wed, Feb 25, 2026 at 12:14:12AM -0800, Eric Zhang wrote:
> For # __VA_OPT__(), a stringify flag on TOKEN_VA_OPT_START could
> signal substitute() to stringify or produce "" depending on whether
> varargs are empty.
IMO it's better to turn that into
TOKEN_VA_OPT[<token-list>]
and
TOKEN_QUOTED_VA_OPT[<token-list>]
with list hanging off the cannibalized token. Interpreter (substitute())
can easily keep track of where it is.
FWIW, the way they patched __VA_OPT__ into 10.5.1 is unfortunate -
I can understand wanting to keep the changes localized, but it ends
up very convoluted ;-/ In part it's due to the way ## and # evaluation
order is left unspecified, but... ouch.
Basically, #__VA_OPT__(<token-list>) is treated the following way:
it's "" if va-opt is suppressed, otherwise we
* do argument substitution in <token-list>
* [unspecified, but everyone does that] process # and ##
in the token-list.
* do *NOT* remove placemaker tokens
* do *NOT* rescan
* stringify the resulting token list, same way we would if
that token list had been passed as an argument and we were processing
#<that argument> (as per 6.10.5.2[3]).
## vs. __VA_OPT__ is similar; the tricky part is placemaker treatment.
For normal arguments it's either a non-empty list or a solitary placemaker;
here we might have placemakers with non-empty list.
#define F1(X, Y, ...) Y ## __VA_OPT__(X X) ## Y
#define F2(X, Y, ...) Y ## __VA_OPT__(X) ## Y
F1(,a,_)
F2(,a,_)
We get a ## placemaker placemaker ## a (i.e. a a) or a ## placemaker
## a (i.e. aa) respectively. Approach without explicit ## tokens
at expansion time is easy to adapt to that - we just interpret the
translated token-list hanging off __VA_OPT__, then return to the rest
of the body; state is updated as usual. Quoted __VA_OPT__ == run the
interpreter (starting from Normal) on the token-list, then feed that
to stringify() and use the result as if it came from quoted argument
(note that concatenation with previous token *is* possible -
L ## #__VA_OPT__(something) is not invalid).
Since __VA_OPT__ can't nest, it's easy to save the body->next into a
local variable, set body to body->va_opt_list and, after the main loop
check if that local variable is non-NULL. In that case we just set body
to that, clear that variable and go back to the beginning of the loop.
Quoted ones get a recursive call...
NOTE: substitute() is the second hottest loop in the entire thing; only
tokenizer is hotter. And gcc is too enthusiastic about the inlining
around that function, ending up with bad register spills, along with
a bunch of stalls. Worse, decisions are sensitive to minor changes in
places textually far away, making it a real bitch to deal with.
Makes for fun reordering the commits in local queue... ;-/
> > Another problem is that having no __VA_ARGS__ in the body should
> > *not* be treated as "vararg is empty"
>
> Missed in the test case, but it seems like it can work in the current
> version.
AFAICS you won't even try to expand it at expand_arguments(), so the
reference will remain NULL.
next prev parent reply other threads:[~2026-02-25 22:16 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1771930766.git.dan.carpenter@linaro.org>
2026-02-24 11:07 ` [PATCH] sparse: add support for __VA_OPT__ Dan Carpenter
2026-02-24 11:16 ` Ben Dooks
2026-02-24 11:56 ` Dan Carpenter
2026-02-24 12:42 ` Richard Fitzgerald
2026-02-24 13:15 ` Ben Dooks
2026-02-25 2:39 ` Chris Li
2026-02-25 3:36 ` Al Viro
2026-02-25 5:29 ` [RFC PATCH] pre-process: add __VA_OPT__ support Eric Zhang
2026-02-25 6:40 ` Al Viro
2026-02-25 7:27 ` Al Viro
2026-02-25 8:14 ` Eric Zhang
2026-02-25 22:18 ` Al Viro [this message]
2026-02-26 7:29 ` Al Viro
2026-03-16 6:56 ` Al Viro
2026-03-16 7:03 ` [PATCH 01/21] split copy() into "need to copy" and "can move in place" cases Al Viro
2026-03-16 7:03 ` [PATCH 02/21] expand and simplify the call of dup_token() in copy() Al Viro
2026-03-16 7:03 ` [PATCH 03/21] more dup_token() optimizations Al Viro
2026-03-16 7:03 ` [PATCH 04/21] parsing #define: saner handling of argument count, part 1 Al Viro
2026-03-16 7:03 ` [PATCH 05/21] simplify collect_arguments() and fix error handling there Al Viro
2026-03-16 7:04 ` [PATCH 06/21] try_arg(): don't use arglist for argument name lookups Al Viro
2026-03-16 7:04 ` [PATCH 07/21] make expand_has_...() responsible for expanding its argument Al Viro
2026-03-16 7:04 ` [PATCH 08/21] preparing to change argument number encoding for TOKEN_..._ARGUMENT Al Viro
2026-03-16 7:04 ` [PATCH 09/21] steal 2 bits from argnum for argument kind Al Viro
2026-03-16 7:04 ` [PATCH 10/21] on-demand argument expansion Al Viro
2026-03-16 7:04 ` [PATCH 11/21] kill create_arglist() Al Viro
2026-03-16 7:04 ` [PATCH 12/21] stop mangling arglist, get rid of TOKEN_ARG_COUNT Al Viro
2026-03-16 7:04 ` [PATCH 13/21] deal with ## on arguments separately Al Viro
2026-03-16 7:04 ` [PATCH 14/21] preparations for __VA_OPT__ support: reshuffle argument slot assignments Al Viro
2026-03-16 7:04 ` [PATCH 15/21] pre-process.c: split try_arg() Al Viro
2026-03-16 7:04 ` [PATCH 16/21] __VA_OPT__: parsing Al Viro
2026-05-04 11:56 ` Dan Carpenter
2026-03-16 7:04 ` [PATCH 17/21] expansion-time va_opt handling Al Viro
2026-03-16 7:04 ` [PATCH 18/21] merge(): saner handling of ->noexpand Al Viro
2026-03-16 7:04 ` [PATCH 19/21] simplify the calling conventions of collect_arguments() Al Viro
2026-03-16 7:04 ` [PATCH 20/21] make expand_one_symbol() inline Al Viro
2026-03-16 7:04 ` [PATCH 21/21] substitute(): convert switch() into cascade of ifs Al Viro
2026-03-16 16:42 ` [RFC PATCH] pre-process: add __VA_OPT__ support Linus Torvalds
2026-03-19 3:53 ` Al Viro
2026-03-19 4:07 ` Linus Torvalds
2026-03-19 5:34 ` Al Viro
2026-03-17 7:41 ` Chris Li
2026-03-18 6:35 ` Eric Zhang
2026-03-31 8:06 ` Al Viro
2026-03-31 8:07 ` [PATCH 1/6] nextchar(): get rid of special[] Al Viro
2026-03-31 8:07 ` [PATCH 2/6] simplify the inlined side of nextchar() Al Viro
2026-03-31 8:07 ` [PATCH 3/6] tokenize_stream(): don't bother with isspace() Al Viro
2026-03-31 8:07 ` [PATCH 4/6] TOKEN_DIRECTIVE: recognize directive-introducing # in tokenizer Al Viro
2026-03-31 8:07 ` [PATCH 5/6] saner collect_arg() code generation Al Viro
2026-03-31 8:07 ` [PATCH 6/6] try to get whitespaces right Al Viro
2026-04-01 10:39 ` [RFC PATCH] pre-process: add __VA_OPT__ support Al Viro
2026-04-01 16:18 ` Linus Torvalds
2026-04-01 19:52 ` Al Viro
2026-04-01 20:22 ` Al Viro
2026-02-25 7:05 ` [PATCH] sparse: add support for __VA_OPT__ Chris Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260225221851.GE1762976@ZenIV \
--to=viro@zeniv.linux.org.uk \
--cc=ben.dooks@codethink.co.uk \
--cc=chriscli@google.com \
--cc=dan.carpenter@linaro.org \
--cc=linux-sparse@vger.kernel.org \
--cc=rf@opensource.cirrus.com \
--cc=torvalds@linux-foundation.org \
--cc=zxh@xh-zhang.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.