Re: [PATCH] sparse: add support for __VA_OPT__
Al Viro <[email protected]> Wed, 25 Feb 2026 03:36:39 +0000
| Newsgroups | org.kernel.vger.linux-sparse |
|---|---|
| Message-ID | <20260225033639.GA2924820@ZenIV> |
On Tue, Feb 24, 2026 at 06:39:57PM -0800, Chris Li wrote:
> > I guess if you wanted instead of a comma then you could have an empty
> > __VA_OPT__() or you could pass random things like __VA_OPT__(a b c). I
> > don't know why you would do that. In this case, "a" is a macro argument
> > so that has to be expanded out.
<sarcasm>
Then perhaps reading the standard might prove enlightening - possibly
due to examples that might be in there, or seeing the actual description
of semantics? https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
is there and searching for __VA_OPT__ would immediately get you this:
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
SDEF(foo); // replaced by S foo;
SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };
Would that answer your question?
</sarcasm>
> One idea is to add an expand function expand___VA_OPT__, similar to
> expand_has_feature(). Register it in the dynamic expand macro array.
> That way you get the collect_arguments() for free and it behaves just
> like a builtin macro expansion. Just duplicate the collected arg list
> to the current token, if there are extra arguments.
Sorry, no go; for one thing, #__VA_OPT__() won't be dealt with that way,
for another there's fun with foo ## __VA_OPT__(arg) (argument is expanded
*and* subjected to ## - yes, it's possible now).
I have something resembling a workable approach, but there's nasty corner
case when you mix it with the side effects; that's impossible in standard
C, but gcc has the sodding __COUNTER__ thing and _that_ makes life really
interesting.
If there's __VA_OPT__ in the body, we want to expand vararg whether it
occurs in the body or not.
We want to expand each argument that is present in the body.
Question: should we expand an argument that occurs *only* under __VA_OPT__?
Note that "expand and discard" is *not* a no-op - expansion of __COUNTER__
will have visible side effects. What's more, gcc and clang diverge there.
Another kind of side effect is possible in standard C: argument substitution
might fail when attempted. And gcc is arguably broken there - see
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123325 for fun details.
clang handles that one sanely...
I got stalled waiting for gcc folks to respond, then sidetracked to other
stuff. I'll resurrect that stuff later this week.