Skip to content

[libc++] macos: when -mmacosx-version-min < 11, std::latch compiles, although __cpp_lib_latch is undefined #138927

@asakovets

Description

@asakovets

This issue was discovered using Apple toolchain, but its roots is in the upstream.

Steps to reproduce:

Consider a code snippet:

#include <iostream>
#include <latch>
#include <version>

int main()
{
#if !__cpp_lib_latch
        std::latch this_must_not_compile {42};
        std::cout << "std::latch compiles, although __cpp_lib_latch is undefined\n";
#endif
}

Using Apple clang:

% xcrun clang++ --version
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: arm64-apple-darwin24.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
% xcrun clang++ -std=c++20 -mmacosx-version-min=10.15 latch.cpp
% ./a.out
std::latch compiles, although __cpp_lib_latch is undefined

Using upstream clang:
Reproducing the issue with upstream clang is not as straightforward. We must tell the compiler that vendor availability annotations are enabled (even if they are not). Passing -D_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS=1 does not work. The easiest solution, though a little messy, is to modify ${llvm_prefix}/include/c++/v1/__config_site file and set #define _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS 1. This should suffice to reproduce the issue:

% /opt/homebrew/Cellar/llvm/20.1.4/bin/clang++ --version                                      
Homebrew clang version 20.1.4
Target: arm64-apple-darwin24.1.0
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/llvm/20.1.4/bin
Configuration file: /opt/homebrew/etc/clang/arm64-apple-darwin24.cfg
% /opt/homebrew/Cellar/llvm/20.1.4/bin/clang++ -std=c++20 -mmacosx-version-min=10.15 latch.cpp
% ./a.out
std::latch compiles, although __cpp_lib_latch is undefined

My little bits of investigation:

__cpp_lib_latch is defined when both _LIBCPP_HAS_THREADS and _LIBCPP_AVAILABILITY_HAS_SYNC are true:

# if _LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC
# define __cpp_lib_latch 201907L
# endif

However, the definition of std::latch is only protected by _LIBCPP_HAS_THREADS macro:

# if _LIBCPP_HAS_THREADS
# include <__assert>

When compiling for MacOS < 11, if availability annotations are enabled, i.e. _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS = 1, then _LIBCPP_INTRODUCED_IN_LLVM_11 is defined as 0:

# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 140000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 140000) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 70000)
# define _LIBCPP_INTRODUCED_IN_LLVM_11 0

This macro in turn is used to define _LIBCPP_AVAILABILITY_HAS_SYNC:

#define _LIBCPP_AVAILABILITY_HAS_SYNC _LIBCPP_INTRODUCED_IN_LLVM_11

As a result, when -mmacosx-version-min < 11 and vendor availability annotations are enabled, then _LIBCPP_HAS_THREADS = 1 and _LIBCPP_AVAILABILITY_HAS_SYNC = 0. This makes __cpp_lib_latch undefined, but std::latch compiles nevertheless.

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.platform:macosquestionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions