[PATCH] assert: Support assert as variadic macro for C++26 [PR27276]
Florian Weimer
fweimer@redhat.com
Thu Feb 5 16:13:06 GMT 2026
* Jonathan Wakely:
> On Thu, 5 Feb 2026 at 15:48, Jonathan Wakely <jwakely@redhat.com> wrote:
>>
>> On Thu, 5 Feb 2026 at 15:40, Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>> >
>> >
>> >
>> > On Thu, Feb 5, 2026 at 4:36 PM Florian Weimer <fweimer@redhat.com> wrote:
>> >>
>> >> * Tomasz Kamiński:
>> >>
>> >> > +# if __ASSERT_VARIADIC
>> >> > +# define assert(...) \
>> >> > + ((__VA_ARGS__) \
>> >> > + ? (void)(1 ? 1 : bool(__VA_ARGS__)) \
>> >> > + : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE, \
>> >> > + __ASSERT_FUNCTION))
>> >>
>> >> Doesn't this evaluate __VA_ARGS__ multiple times?
>> >
>> > I got the same question initially when I saw this solution, but
>> > the second bool(__VA_ARGS) is in the false branch of the ternary:
>> > 1 ? 1 : bool(__VA_ARGS__)
>> > So it is never evaluated.
>>
>> Right, it's never evaluated, it's only there to enforce that
>> __VA_ARGS__ expands to a single expression, because bool(x,y) is
>> ill-formed.
>
> Maybe it needs a comment explaining the logic, and saying "Be careful
> when touching this, every piece of it is load-bearing!" ;-)
>
> The key pieces are that this relies on the "contextually converted to
> bool" rule <https://wg21.link/conv.general#4>
>
> (__VA_ARGS__) ? expr : __assert_fail(...);
>
> This is a "weaker" form of conversion than casting to bool, and so
> prevents scoped enum types from being asserted on (they aren't
> convertible to integers, so they shouldn't be implicitly converted to
> 'true;' or 'false' in assertions).
>
> And as explained above, the (void)(1 ? 1 : bool(__VA_ARGS__)) part has
> no side effects but ensures that assert(x, y) is ill-formed, at least
> when NDEBUG is not defined.
The problem about the first (__VA_ARGS__) is that because it's extra
parentheses, it suppresses the warning we want for:
assert (x = 1);
The bool(__VA_ARGS__) part still warns. So that part has not one, but
two functions. I think I we ended up with static_cast<bool> (…) because
there is no such warning for (bool) (…), and I maybe I thought that was
too close to bool (…).
Thanks,
Florian
More information about the Libc-alpha
mailing list