diff --git a/libcxx/include/atomic b/libcxx/include/atomic index 80f9e437bfaab..75af5de33ca4c 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -592,6 +592,16 @@ template #else # include <__config> +# if defined(_LIBCPP_STDATOMIC_H) || defined(kill_dependency) || defined(atomic_load) +# define _LIBCPP_STDATOMIC_H_HAS_DEFINITELY_BEEN_INCLUDED 1 +# else +# define _LIBCPP_STDATOMIC_H_HAS_DEFINITELY_BEEN_INCLUDED 0 +# endif + +# if _LIBCPP_STD_VER < 23 && _LIBCPP_STDATOMIC_H_HAS_DEFINITELY_BEEN_INCLUDED +# error is incompatible with before C++23. Please compile with -std=c++23. +# endif + # include <__atomic/aliases.h> # include <__atomic/atomic.h> # include <__atomic/atomic_flag.h> diff --git a/libcxx/include/stdatomic.h b/libcxx/include/stdatomic.h index a0b46e3b7bc17..2991030eee456 100644 --- a/libcxx/include/stdatomic.h +++ b/libcxx/include/stdatomic.h @@ -126,7 +126,7 @@ using std::atomic_signal_fence // see below # pragma GCC system_header # endif -# if defined(__cplusplus) +# if defined(__cplusplus) && _LIBCPP_STD_VER >= 23 # include # include @@ -231,13 +231,17 @@ using std::atomic_store_explicit _LIBCPP_USING_IF_EXISTS; using std::atomic_signal_fence _LIBCPP_USING_IF_EXISTS; using std::atomic_thread_fence _LIBCPP_USING_IF_EXISTS; -# else +# elif defined(_LIBCPP_COMPILER_CLANG_BASED) +// Before C++23, we include the next on the path to avoid hijacking +// the header. We do this because Clang has historically shipped a +// header that would be available in all Standard modes, and we don't want to +// break that use case. # if __has_include_next() # include_next # endif -# endif // defined(__cplusplus) +# endif // defined(__cplusplus) && _LIBCPP_STD_VER >= 23 #endif // defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP_STDATOMIC_H diff --git a/libcxx/test/libcxx/atomics/atomics.syn/compatible_with_stdatomic.compile.pass.cpp b/libcxx/test/libcxx/atomics/atomics.syn/compatible_with_stdatomic.compile.pass.cpp index 323072da14463..30e9672a25683 100644 --- a/libcxx/test/libcxx/atomics/atomics.syn/compatible_with_stdatomic.compile.pass.cpp +++ b/libcxx/test/libcxx/atomics/atomics.syn/compatible_with_stdatomic.compile.pass.cpp @@ -7,15 +7,16 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: no-threads +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // XFAIL: FROZEN-CXX03-HEADERS-FIXME -// This test verifies that redirects to . As an extension, -// libc++ enables this redirection even before C++23. +// This test verifies that redirects to . -// Ordinarily, can be included after , but including it -// first doesn't work because its macros break . Verify that -// can be included first. +// Before C++23, can be included after , but including it +// first doesn't work because its macros break . Fixing that is the point +// of the C++23 change that added to C++. Thus, this test verifies +// that can be included first. #include #include diff --git a/libcxx/test/libcxx/atomics/atomics.syn/incompatible_with_stdatomic.verify.cpp b/libcxx/test/libcxx/atomics/atomics.syn/incompatible_with_stdatomic.verify.cpp new file mode 100644 index 0000000000000..ca092d9c60275 --- /dev/null +++ b/libcxx/test/libcxx/atomics/atomics.syn/incompatible_with_stdatomic.verify.cpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads +// REQUIRES: c++03 || c++11 || c++14 || c++17 || c++20 + +// This test ensures that we issue a reasonable diagnostic when including after +// has been included. Before C++23, this otherwise leads to obscure errors +// because may try to redefine things defined by . + +// Ignore additional weird errors that happen when the two headers are mixed. +// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error -Xclang -verify-ignore-unexpected=warning + +#include +#include + +// expected-error@*:* {{ is incompatible with before C++23.}} diff --git a/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.compile.pass.cpp b/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.compile.pass.cpp new file mode 100644 index 0000000000000..6df80daf9414e --- /dev/null +++ b/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads + +// This test ensures that we don't hijack the header (e.g. by providing +// an empty header) even when compiling before C++23, since some users were using the +// Clang or platform provided header before libc++ added its own. + +// On GCC, the compiler-provided is not C++ friendly, so including +// doesn't work at all if we don't use the provided by libc++ in C++23 and above. +// XFAIL: (c++11 || c++14 || c++17 || c++20) && gcc + +#include + +void f() { + atomic_int i; // just make sure the header isn't empty + (void)i; +} diff --git a/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.cxx23.compile.pass.cpp b/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.cxx23.compile.pass.cpp new file mode 100644 index 0000000000000..a8a99e6937f31 --- /dev/null +++ b/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.cxx23.compile.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads + +// This test verifies that DOES NOT redirect to before C++23, +// since doing so is a breaking change. Several things can break when that happens, +// because the type of _Atomic(T) changes from _Atomic(T) to std::atomic. +// +// For example, redeclarations can become invalid depending on whether they +// have been declared with in scope or not. + +// REQUIRES: c++03 || c++11 || c++14 || c++17 || c++20 + +// On GCC, the compiler-provided is not C++ friendly, so including +// doesn't work at all if we don't use the provided by libc++ in C++23 and above. +// XFAIL: (c++11 || c++14 || c++17 || c++20) && gcc + +#include +#include +#include + +static_assert(!std::is_same<_Atomic(int), std::atomic >::value, "");