[PATCH v3] assert: Support assert as variadic macro for C++26 [PR27276]

Tomasz Kaminski tkaminsk@redhat.com
Tue Feb 17 10:00:53 GMT 2026


On Mon, Feb 16, 2026 at 11:04 PM Paul Eggert <eggert@cs.ucla.edu> wrote:

> On 2026-02-09 03:27, Tomasz Kamiński wrote:
>
> > Mainly for testing purposes we allow enabling/disabling variadic assert
> > regardless of version of C or C++, by defining __ASSERT_VARIADIC to
> > 1/0 respectively before inclusion of <assert>
>
> I don't see the need for this extra complexity in this patch. People who
> want to do that sort of testing can do it in other ways. If there is a
> need, this part of the patch should be separated out into a different
> patch.
>
I would really appreciate guidance on how I could test this in other ways,
in a robust manner. I was simply considering guarding the content
test-assert-c++-variadic.cc with appropriate __cplusplus value,
but this led to de-facto dead-test.

The problem I am facing is that the test would need to be compiled with
"-std=c++26", but that is not supported by all versions of GCC that glibc
targets. I have looked into how C23 is tested, to see how to conditionally
pass --std=c23 flag, but they seem to rely on defining ISOC23_SOURCES.



> > +   Similary C++26 makes assert a variadic macro and allows expressions
> > +   containing template argument lists, lambda captures, and many others
> > +   that include commas, without requiring extra parentheses.
>
> "Similarly" is misspelled. Plus, this comment talks about the wrong
> things. The key question (which the containing comment already answers
> for C) is which versions of the language standard and of GCC support the
> proposed implementation of variadic assert for C++. That's what the
> comment should talk about, not about which features of C++ can use the
> proposed patch. Or maybe it's simpler to just remove this comment
> entirely, if all versions of the standard and GCC support it.
>
It is supported in all versions of GCC that support C++26 standard, so I
will
simply remove it.

>
> > +#  if (__GLIBC_USE (ISOC23)                                          \
> > +       && (defined __GNUC__                                          \
> > +        ? __GNUC_PREREQ (3, 0)                                       \
> > +        : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)   \
> > +       || (defined __cplusplus && __cplusplus >= 202302L))
>
> Parenthesis are missing around the first disjunct.
>
The first disjunct is directly placed inside if, i.e. is enclosed by
outermost
parenthesis. Do you want me to add a second pair?

>
> More importantly, that "__cplusplus >= 202302L" looks wrong. This is a
> C++26 feature, right? Shouldn't it be "__cplusplus > 202302L"? Using
> ">=" would cause g++ to not diagnose some invalid C++23 programs, even
> in pedantic mode.
>
I have double checked, and the feature was voted in C++26. I will fix the
above. Thank you!

>
> > +#   define __ASSERT_VARIADIC 1
> > +#  else
> > +#    define __ASSERT_VARIADIC 0
> > +#  endif
> >   #endif
> >
> >   /* void assert (int expression);
> > @@ -108,7 +112,7 @@ extern void __assert (const char *__assertion, const
> char *__file, int __line)
> >        __THROW __attribute__ ((__noreturn__)) __COLD;
> >   __cplusplus >= 202302L
> >
> > -# if __ASSERT_VARIADIC
> > +# if __ASSERT_VARIADIC && !defined __cplusplus
> >   /* This function is not defined and is not called outside of an
> >      unevaluated sizeof, but serves to verify that the argument to
> >      assert is a single expression.  */
> > @@ -131,11 +135,19 @@ __END_DECLS
> >   #   define __ASSERT_FILE __FILE__
> >   #   define __ASSERT_LINE __LINE__
> >   #  endif
> > -#  define assert(expr)
>      \
> > +#  if __ASSERT_VARIADIC
> > +#    define assert(...)
>       \
> > +     ((__VA_ARGS__)                                                  \
> > +      ? (void)(1 ? 1 : bool(__VA_ARGS__))                            \
> > +      : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE,   \
> > +                       __ASSERT_FUNCTION))
>
> The proposed spacing near parens doesn't conform to the usual glibc style.
>
> Why use '(void)(...) rather than 'void (...)' as the other arm does?
>
I will double check if there is a difference (we already found subtle
differences
between the syntaxes), if not I will switch to the proposed syntax.

>
> More importantly, can't we simplify things by avoiding one repetition of
> __VA_ARGS__ and doing something like the following instead?
>
As I have mentioned in the commit message, and also glibc PR/27276 [2],
use of bool(__VA_ARGS__) is non-conforming according to C++ standard,
as it accepts expression of types that are explicitly convertible, but not
contextually convertible to bool. In particular this includes scoped
enumerations.

This is why I believe having a dedicated and functioning c++ variadic test
is
very valuable, and I am hesitant to remove __ASSERT_VARIADIC change,
if we do not have a good alternative.

Regards,
Tomasz


>
>   #define assert(...) \
>     (bool (__VA_ARGS__) \
>      ? void (0) \
>      : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE, \
>                       __ASSERT_FUNCTION))
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20260217/23d3fb36/attachment-0001.htm>


More information about the Libc-alpha mailing list