Skip to content

C++23 <stdatomic.h> is incompatible with libdispatch's _Atomic shim #940

Description

@bc-lee

I was using swift-corelibs-libdispatch as part of a broader Bazel-based
system. While porting that project from C++20 to C++23, I found a problem with
the way libdispatch uses <stdatomic.h>.

Steps to validate (in standalone swift-corelibs-libdispatch)

  1. Edit CMakeLists.txt and set CMAKE_CXX_STANDARD to 23.
  2. Build swift-corelibs-libdispatch.
  3. Check whether the build succeeds.

Expected

Build succeeds.

Actual

Build fails with both libstdc++ and libc++.

With libstdc++, the failure looks like:

In file included from /path/to/swift-corelibs-libdispatch/src/block.cpp:31:
In file included from /path/to/swift-corelibs-libdispatch/src/internal.h:667:
In file included from /path/to/swift-corelibs-libdispatch/src/shims.h:220:
In file included from /path/to/swift-corelibs-libdispatch/src/shims/atomic.h:41:
In file included from /usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/stdatomic.h:36:
In file included from /usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/atomic:52:
In file included from /usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/atomic_base.h:38:
/usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/new:230:3: error: templates must have C++ linkage
  230 |   template<typename _Tp>
      |   ^~~~~~~~~~~~~~~~~~~~~~
/path/to/swift-corelibs-libdispatch/src/internal.h:326:1: note: extern "C" language linkage specification begins here
  326 | __BEGIN_DECLS
      | ^
/usr/include/sys/cdefs.h:140:24: note: expanded from macro '__BEGIN_DECLS'
  140 | # define __BEGIN_DECLS  extern "C" {
      |                         ^
In file included from /path/to/swift-corelibs-libdispatch/src/block.cpp:31:
In file included from /path/to/swift-corelibs-libdispatch/src/internal.h:667:
In file included from /path/to/swift-corelibs-libdispatch/src/shims.h:220:
In file included from /path/to/swift-corelibs-libdispatch/src/shims/atomic.h:41:
In file included from /usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/stdatomic.h:36:
In file included from /usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/atomic:52:
In file included from /usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/atomic_base.h:40:
/usr/lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/move.h:49:3: error: templates must have C++ linkage
   49 |   template<typename _Tp>
      |   ^~~~~~~~~~~~~~~~~~~~~~

With libc++, the failure looks like:

In file included from /path/to/swift-corelibs-libdispatch/src/block.cpp:31:
In file included from /path/to/swift-corelibs-libdispatch/src/internal.h:667:
In file included from /path/to/swift-corelibs-libdispatch/src/shims.h:220:
In file included from /path/to/swift-corelibs-libdispatch/src/shims/atomic.h:41:
In file included from /usr/include/c++/v1/stdatomic.h:131:
In file included from /usr/include/c++/v1/atomic:605:
In file included from /usr/include/c++/v1/__atomic/aliases.h:12:
In file included from /usr/include/c++/v1/__atomic/atomic.h:12:
In file included from /usr/include/c++/v1/__atomic/atomic_sync.h:12:
In file included from /usr/include/c++/v1/__atomic/contention_t.h:12:
In file included from /usr/include/c++/v1/__atomic/support.h:108:
In file included from /usr/include/c++/v1/__atomic/support/c11.h:12:
In file included from /usr/include/c++/v1/__atomic/memory_order.h:13:
/usr/include/c++/v1/__type_traits/is_same.h:21:1: error: templates must have C++ linkage
   21 | template <class _Tp, class _Up>
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/path/to/swift-corelibs-libdispatch/src/internal.h:326:1: note: extern "C" language linkage specification begins here
  326 | __BEGIN_DECLS
      | ^

Environment

Tested on Linux x86_64 (Fedora 43) with:

  • swift-corelibs-libdispatch at 330412f
  • Clang 21
  • C++23
  • libstdc++ repro: clang++ using GCC 15 C++ headers
  • libc++ repro: clang++ -stdlib=libc++ using /usr/include/c++/v1

Root cause

src/shims/atomic.h contains an internal shim built around Clang C _Atomic
storage and C11 atomic operations.

In C++23, both libstdc++ and libc++ implement <stdatomic.h> in C++ mode
using the C++ atomics model instead of the old C11-style interface that
libdispatch's shim expects.

That does not match what libdispatch's shim expects. In practice, this causes
src/block.cpp to fail to compile through the include chain:

src/block.cpp -> src/internal.h -> src/shims.h -> src/shims/atomic.h -> <stdatomic.h>

Possible solution

One possible fix would be to make src/shims/atomic.h use private libdispatch
atomic aliases instead of directly relying on the public atomic_* names from
<stdatomic.h>.

For C and older C++ modes, those aliases could continue to map to
<stdatomic.h>.

For C++23 and newer, they could instead map directly to Clang
__c11_atomic_* builtins and __ATOMIC_* memory-order constants. That would
preserve the shim's current _Atomic-based model without depending on the
C++23 std::atomic-based behavior of <stdatomic.h>.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions