Skip to content

[clang-tidy] bugprone-macro-repeated-side-effects false positive with assert() in glibc 2.44 #233597

Description

@nikola-benes

In glibc 2.44, the definition of the assert() macro changed to accommodate the C++26 feature that allows non-parenthesised commas within assertions. The relevant part is this:

#    define assert(...)                                                 \
     ((__VA_ARGS__)                                                     \
      ? void (1 ? 1 : bool (__VA_ARGS__))                               \
      : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE,      \
                       __ASSERT_FUNCTION))

(source: https://sourceware.org/git/?p=glibc.git;a=blob;f=assert/assert.h;hb=ea37298b65bd67f94c3c2640e91ec5865a5019ad#l137)

Note that __VA_ARGS__ is only evaluated once, even though it appears twice. Unfortunately, this makes clang-tidy produce the bugprone-macro-repeated-side-effects warning in code like this, even if bugprone-assert-side-effect is not enabled:

#include <cassert>
int main() {
    int x = 0;
    assert(++x == 1);
    assert(++x == 1);
}

The result:

warning: side effects in the 1st macro argument '__VA_ARGS__' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
    4 |         assert( ++x == 1 );
      |                 ^
/usr/include/assert.h:137:13: note: macro 'assert' defined here
  137 | #    define assert(...)                                                 \
      |             ^
warning: side effects in the 1st macro argument '__VA_ARGS__' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
    5 |         assert( ++x == 2 );
      |                 ^
/usr/include/assert.h:137:13: note: macro 'assert' defined here
  137 | #    define assert(...)                                                 \
      |             ^

Perhaps the bugprone-macro-repeated-side-effects could specifically ignore the assert() macro; or, even better, it could be configurable with an option to ignore specific macros.

Activity

  1. llvmorg-github-actions commented on Oct 19, 2026

    @llvmorg-github-actions

    @llvm/issue-subscribers-clang-tidy

    Author: Nikola Beneš (nikola-benes)

    Details In glibc 2.44, the definition of the `assert()` macro changed to accommodate the C++26 feature that allows non-parenthesised commas within assertions. The relevant part is this:
    #    define assert(...)                                                 \
         ((__VA_ARGS__)                                                     \
          ? void (1 ? 1 : bool (__VA_ARGS__))                               \
          : __assert_fail (#__VA_ARGS__, __ASSERT_FILE, __ASSERT_LINE,      \
                           __ASSERT_FUNCTION))

    (source: https://sourceware.org/git/?p=glibc.git;a=blob;f=assert/assert.h;hb=ea37298b65bd67f94c3c2640e91ec5865a5019ad#l137)

    Note that __VA_ARGS__ is only evaluated once, even though it appears twice. Unfortunately, this makes clang-tidy produce the bugprone-macro-repeated-side-effects warning in code like this, even if bugprone-assert-side-effect is not enabled:

    #include &lt;cassert&gt;
    int main() {
        int x = 0;
        assert(++x == 1);
        assert(++x == 1);
    }

    The result:

    warning: side effects in the 1st macro argument '__VA_ARGS__' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
        4 |         assert( ++x == 1 );
          |                 ^
    /usr/include/assert.h:137:13: note: macro 'assert' defined here
      137 | #    define assert(...)                                                 \
          |             ^
    warning: side effects in the 1st macro argument '__VA_ARGS__' are repeated in macro expansion [bugprone-macro-repeated-side-effects]
        5 |         assert( ++x == 2 );
          |                 ^
    /usr/include/assert.h:137:13: note: macro 'assert' defined here
      137 | #    define assert(...)                                                 \
          |             ^
    

    Perhaps the bugprone-macro-repeated-side-effects could specifically ignore the assert macro; or, even better, it could be configurable with an option to ignore specific macros.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions