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

Jonathan Wakely jwakely@redhat.com
Tue Feb 17 10:36:29 GMT 2026


On Tue, 17 Feb 2026 at 10:01, Tomasz Kaminski <tkaminsk@redhat.com> wrote:
>
>
>
> 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.

Another benefit of the __ASSERT_VARIADIC macro is that it would allow
libstdc++ to decide to enable the new definition of assert for
pre-C++26 as an extension (e.g. for non-strict -std=gnu++20 mode).

If Glibc supports that toggle, then libstdc++ can make use of it. If
glibc doesn't support that, then we need changes to Glibc to do that.



More information about the Libc-alpha mailing list