diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 4f2ce96427a1..5d82ad26aca7 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -344,7 +344,7 @@ Status ------------------------------------------------- ----------------- ``__cpp_lib_stacktrace`` *unimplemented* ------------------------------------------------- ----------------- - ``__cpp_lib_stdatomic_h`` *unimplemented* + ``__cpp_lib_stdatomic_h`` ``202011L`` ------------------------------------------------- ----------------- ``__cpp_lib_string_contains`` ``202011L`` ------------------------------------------------- ----------------- diff --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv index 4aad9a6d6678..15531dff1e48 100644 --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -1,6 +1,6 @@ "Paper #","Group","Paper Name","Meeting","Status","First released version" "`P0881R7 `__","LWG","A Proposal to add stacktrace library","Autumn 2020","","" -"`P0943R6 `__","LWG","Support C atomics in C++","Autumn 2020","","" +"`P0943R6 `__","LWG","Support C atomics in C++","Autumn 2020","|Complete|","15.0" "`P1048R1 `__","LWG","A proposal for a type trait to detect scoped enumerations","Autumn 2020","|Complete|","12.0" "`P1679R3 `__","LWG","string contains function","Autumn 2020","|Complete|","12.0" "","","","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index b79f286a7199..6069704fcf07 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -563,6 +563,7 @@ set(files span sstream stack + stdatomic.h stdbool.h stddef.h stdexcept diff --git a/libcxx/include/atomic b/libcxx/include/atomic index b5c6e5182a4f..1d83e37734f3 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -542,7 +542,7 @@ template # error is not implemented #endif #ifdef kill_dependency -# error C++ standard library is incompatible with +# error is incompatible with before C++23. Please compile with -std=c++23. #endif #define _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) \ diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index c291901c6bba..65e628d44da8 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -50,6 +50,10 @@ module std [system] { header "setjmp.h" export * } + module stdatomic_h { + header "stdatomic.h" + export * + } // FIXME: is missing. // provided by C library. // provided by compiler. diff --git a/libcxx/include/stdatomic.h b/libcxx/include/stdatomic.h new file mode 100644 index 000000000000..8495504b07a1 --- /dev/null +++ b/libcxx/include/stdatomic.h @@ -0,0 +1,242 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_STDATOMIC_H +#define _LIBCPP_STDATOMIC_H + +/* + stdatomic.h synopsis + +template + using std-atomic = std::atomic; // exposition only + +#define _Atomic(T) std-atomic + +#define ATOMIC_BOOL_LOCK_FREE see below +#define ATOMIC_CHAR_LOCK_FREE see below +#define ATOMIC_CHAR16_T_LOCK_FREE see below +#define ATOMIC_CHAR32_T_LOCK_FREE see below +#define ATOMIC_WCHAR_T_LOCK_FREE see below +#define ATOMIC_SHORT_LOCK_FREE see below +#define ATOMIC_INT_LOCK_FREE see below +#define ATOMIC_LONG_LOCK_FREE see below +#define ATOMIC_LLONG_LOCK_FREE see below +#define ATOMIC_POINTER_LOCK_FREE see below + +using std::memory_order // see below +using std::memory_order_relaxed // see below +using std::memory_order_consume // see below +using std::memory_order_acquire // see below +using std::memory_order_release // see below +using std::memory_order_acq_rel // see below +using std::memory_order_seq_cst // see below + +using std::atomic_flag // see below + +using std::atomic_bool // see below +using std::atomic_char // see below +using std::atomic_schar // see below +using std::atomic_uchar // see below +using std::atomic_short // see below +using std::atomic_ushort // see below +using std::atomic_int // see below +using std::atomic_uint // see below +using std::atomic_long // see below +using std::atomic_ulong // see below +using std::atomic_llong // see below +using std::atomic_ullong // see below +using std::atomic_char8_t // see below +using std::atomic_char16_t // see below +using std::atomic_char32_t // see below +using std::atomic_wchar_t // see below +using std::atomic_int8_t // see below +using std::atomic_uint8_t // see below +using std::atomic_int16_t // see below +using std::atomic_uint16_t // see below +using std::atomic_int32_t // see below +using std::atomic_uint32_t // see below +using std::atomic_int64_t // see below +using std::atomic_uint64_t // see below +using std::atomic_int_least8_t // see below +using std::atomic_uint_least8_t // see below +using std::atomic_int_least16_t // see below +using std::atomic_uint_least16_t // see below +using std::atomic_int_least32_t // see below +using std::atomic_uint_least32_t // see below +using std::atomic_int_least64_t // see below +using std::atomic_uint_least64_t // see below +using std::atomic_int_fast8_t // see below +using std::atomic_uint_fast8_t // see below +using std::atomic_int_fast16_t // see below +using std::atomic_uint_fast16_t // see below +using std::atomic_int_fast32_t // see below +using std::atomic_uint_fast32_t // see below +using std::atomic_int_fast64_t // see below +using std::atomic_uint_fast64_t // see below +using std::atomic_intptr_t // see below +using std::atomic_uintptr_t // see below +using std::atomic_size_t // see below +using std::atomic_ptrdiff_t // see below +using std::atomic_intmax_t // see below +using std::atomic_uintmax_t // see below + +using std::atomic_is_lock_free // see below +using std::atomic_load // see below +using std::atomic_load_explicit // see below +using std::atomic_store // see below +using std::atomic_store_explicit // see below +using std::atomic_exchange // see below +using std::atomic_exchange_explicit // see below +using std::atomic_compare_exchange_strong // see below +using std::atomic_compare_exchange_strong_explicit // see below +using std::atomic_compare_exchange_weak // see below +using std::atomic_compare_exchange_weak_explicit // see below +using std::atomic_fetch_add // see below +using std::atomic_fetch_add_explicit // see below +using std::atomic_fetch_sub // see below +using std::atomic_fetch_sub_explicit // see below +using std::atomic_fetch_or // see below +using std::atomic_fetch_or_explicit // see below +using std::atomic_fetch_and // see below +using std::atomic_fetch_and_explicit // see below +using std::atomic_flag_test_and_set // see below +using std::atomic_flag_test_and_set_explicit // see below +using std::atomic_flag_clear // see below +using std::atomic_flag_clear_explicit // see below + +using std::atomic_thread_fence // see below +using std::atomic_signal_fence // see below + +*/ + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER > 20 + +#include +#include + +#ifdef _Atomic +# undef _Atomic +#endif + +#define _Atomic(_Tp) ::std::atomic<_Tp> + +using std::memory_order _LIBCPP_USING_IF_EXISTS; +using std::memory_order_relaxed _LIBCPP_USING_IF_EXISTS; +using std::memory_order_consume _LIBCPP_USING_IF_EXISTS; +using std::memory_order_acquire _LIBCPP_USING_IF_EXISTS; +using std::memory_order_release _LIBCPP_USING_IF_EXISTS; +using std::memory_order_acq_rel _LIBCPP_USING_IF_EXISTS; +using std::memory_order_seq_cst _LIBCPP_USING_IF_EXISTS; + +using std::atomic_flag _LIBCPP_USING_IF_EXISTS; + +using std::atomic_bool _LIBCPP_USING_IF_EXISTS; +using std::atomic_char _LIBCPP_USING_IF_EXISTS; +using std::atomic_schar _LIBCPP_USING_IF_EXISTS; +using std::atomic_uchar _LIBCPP_USING_IF_EXISTS; +using std::atomic_short _LIBCPP_USING_IF_EXISTS; +using std::atomic_ushort _LIBCPP_USING_IF_EXISTS; +using std::atomic_int _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint _LIBCPP_USING_IF_EXISTS; +using std::atomic_long _LIBCPP_USING_IF_EXISTS; +using std::atomic_ulong _LIBCPP_USING_IF_EXISTS; +using std::atomic_llong _LIBCPP_USING_IF_EXISTS; +using std::atomic_ullong _LIBCPP_USING_IF_EXISTS; +using std::atomic_char8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_char16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_char32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_wchar_t _LIBCPP_USING_IF_EXISTS; + +using std::atomic_int8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int64_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint64_t _LIBCPP_USING_IF_EXISTS; + +using std::atomic_int_least8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_least8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int_least16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_least16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int_least32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_least32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int_least64_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_least64_t _LIBCPP_USING_IF_EXISTS; + +using std::atomic_int_fast8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_fast8_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int_fast16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_fast16_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int_fast32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_fast32_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_int_fast64_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uint_fast64_t _LIBCPP_USING_IF_EXISTS; + +using std::atomic_intptr_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uintptr_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_size_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_ptrdiff_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_intmax_t _LIBCPP_USING_IF_EXISTS; +using std::atomic_uintmax_t _LIBCPP_USING_IF_EXISTS; + +using std::atomic_compare_exchange_strong _LIBCPP_USING_IF_EXISTS; +using std::atomic_compare_exchange_strong_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_compare_exchange_weak _LIBCPP_USING_IF_EXISTS; +using std::atomic_compare_exchange_weak_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_exchange _LIBCPP_USING_IF_EXISTS; +using std::atomic_exchange_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_add _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_add_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_and _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_and_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_or _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_or_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_sub _LIBCPP_USING_IF_EXISTS; +using std::atomic_fetch_sub_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_flag_clear _LIBCPP_USING_IF_EXISTS; +using std::atomic_flag_clear_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_flag_test_and_set _LIBCPP_USING_IF_EXISTS; +using std::atomic_flag_test_and_set_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_is_lock_free _LIBCPP_USING_IF_EXISTS; +using std::atomic_load _LIBCPP_USING_IF_EXISTS; +using std::atomic_load_explicit _LIBCPP_USING_IF_EXISTS; +using std::atomic_store _LIBCPP_USING_IF_EXISTS; +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; + +#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. +// +// However, if the user has already used before, the two headers are +// incompatible before C++23, so we issue a clear error here to avoid obscure +// issues down the line. +# if __has_include_next() +# ifdef _LIBCPP_ATOMIC +# error is incompatible with before C++23. Please compile with -std=c++23. +# endif +# include_next +# endif + +#endif // _LIBCPP_STD_VER > 20 + +#endif // _LIBCPP_STDATOMIC_H diff --git a/libcxx/include/version b/libcxx/include/version index d65ccdc46a7a..95b863cbdd9a 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -396,7 +396,7 @@ __cpp_lib_void_t 201411L // # define __cpp_lib_reference_from_temporary 202202L // # define __cpp_lib_spanstream 202106L // # define __cpp_lib_stacktrace 202011L -// # define __cpp_lib_stdatomic_h 202011L +# define __cpp_lib_stdatomic_h 202011L # define __cpp_lib_string_contains 202011L # define __cpp_lib_string_resize_and_overwrite 202110L # define __cpp_lib_to_underlying 202102L diff --git a/libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp b/libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp index 875cbc72678d..167da28a7add 100644 --- a/libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp +++ b/libcxx/test/libcxx/assertions/headers_declare_assertion_handler.sh.cpp @@ -532,236 +532,236 @@ int main(int, char**) { return 0; } using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_92 -#if defined(TEST_92) +// RUN: %{build} -DTEST_93 +#if defined(TEST_93) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_96 -#if defined(TEST_96) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +// RUN: %{build} -DTEST_97 +#if defined(TEST_97) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_97 -#if defined(TEST_97) +// RUN: %{build} -DTEST_98 +#if defined(TEST_98) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_99 -#if defined(TEST_99) +// RUN: %{build} -DTEST_100 +#if defined(TEST_100) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_100 -#if defined(TEST_100) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) +// RUN: %{build} -DTEST_101 +#if defined(TEST_101) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_101 -#if defined(TEST_101) +// RUN: %{build} -DTEST_102 +#if defined(TEST_102) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_103 -#if defined(TEST_103) && !defined(_LIBCPP_HAS_NO_THREADS) -# include - using HandlerType = decltype(std::__libcpp_assertion_handler); -#endif - // RUN: %{build} -DTEST_104 -#if defined(TEST_104) -# include +#if defined(TEST_104) && !defined(_LIBCPP_HAS_NO_THREADS) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_105 #if defined(TEST_105) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_106 #if defined(TEST_106) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_107 #if defined(TEST_107) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_109 -#if defined(TEST_109) -# include +// RUN: %{build} -DTEST_108 +#if defined(TEST_108) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_110 #if defined(TEST_110) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_111 #if defined(TEST_111) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_112 #if defined(TEST_112) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_113 #if defined(TEST_113) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_114 #if defined(TEST_114) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_115 #if defined(TEST_115) +# include + using HandlerType = decltype(std::__libcpp_assertion_handler); +#endif + +// RUN: %{build} -DTEST_116 +#if defined(TEST_116) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_118 -#if defined(TEST_118) +// RUN: %{build} -DTEST_119 +#if defined(TEST_119) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif -// RUN: %{build} -DTEST_119 -#if defined(TEST_119) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) -# include - using HandlerType = decltype(std::__libcpp_assertion_handler); -#endif - // RUN: %{build} -DTEST_120 -#if defined(TEST_120) && __cplusplus >= 201103L -# include +#if defined(TEST_120) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_COROUTINES) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_121 #if defined(TEST_121) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_122 -#if defined(TEST_122) -# include +#if defined(TEST_122) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_123 #if defined(TEST_123) -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_124 -#if defined(TEST_124) && __cplusplus >= 201103L -# include +#if defined(TEST_124) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_125 #if defined(TEST_125) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_126 #if defined(TEST_126) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_127 -#if defined(TEST_127) -# include +#if defined(TEST_127) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_128 -#if defined(TEST_128) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L -# include +#if defined(TEST_128) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_129 -#if defined(TEST_129) && __cplusplus >= 201103L -# include +#if defined(TEST_129) && !defined(_LIBCPP_HAS_NO_LOCALIZATION) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_130 -#if defined(TEST_130) -# include +#if defined(TEST_130) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_131 -#if defined(TEST_131) && __cplusplus >= 201103L -# include +#if defined(TEST_131) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_132 -#if defined(TEST_132) -# include +#if defined(TEST_132) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_133 -#if defined(TEST_133) && __cplusplus >= 201103L -# include +#if defined(TEST_133) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_134 #if defined(TEST_134) && __cplusplus >= 201103L -# include +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_135 -#if defined(TEST_135) -# include +#if defined(TEST_135) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_136 -#if defined(TEST_136) && __cplusplus >= 201103L -# include +#if defined(TEST_136) +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_137 -#if defined(TEST_137) -# include +#if defined(TEST_137) && __cplusplus >= 201103L +# include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif // RUN: %{build} -DTEST_138 #if defined(TEST_138) +# include + using HandlerType = decltype(std::__libcpp_assertion_handler); +#endif + +// RUN: %{build} -DTEST_139 +#if defined(TEST_139) # include using HandlerType = decltype(std::__libcpp_assertion_handler); #endif 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 000000000000..49bc2dcc7fd1 --- /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: libcpp-has-no-threads +// REQUIRES: c++03 || c++11 || c++14 || c++17 || c++20 + +// This test ensures that we issue a reasonable diagnostic when using while +// is in use too. 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 000000000000..f00c3efa8cf7 --- /dev/null +++ b/libcxx/test/libcxx/atomics/stdatomic.h.syn/dont_hijack_header.compile.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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: libcpp-has-no-threads + +// This test ensures that we don't hijack the header even when compiling +// before C++23, since Clang used to provide that header before libc++ provided one. + +// 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/incompatible_with_atomic.verify.cpp b/libcxx/test/libcxx/atomics/stdatomic.h.syn/incompatible_with_atomic.verify.cpp new file mode 100644 index 000000000000..ff4124ac2490 --- /dev/null +++ b/libcxx/test/libcxx/atomics/stdatomic.h.syn/incompatible_with_atomic.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: libcpp-has-no-threads +// REQUIRES: c++03 || c++11 || c++14 || c++17 || c++20 + +// This test ensures that we issue a reasonable diagnostic when using while +// is in use too. Before C++23, this otherwise leads to obscure errors because tries +// 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/clang_tidy.sh.cpp b/libcxx/test/libcxx/clang_tidy.sh.cpp index b06cac9c8204..c1ace4d3201f 100644 --- a/libcxx/test/libcxx/clang_tidy.sh.cpp +++ b/libcxx/test/libcxx/clang_tidy.sh.cpp @@ -166,6 +166,9 @@ END-SCRIPT # include #endif #include +#if __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) +# include +#endif #include #include #include diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp index 6701908caab4..39c5c9860309 100644 --- a/libcxx/test/libcxx/double_include.sh.cpp +++ b/libcxx/test/libcxx/double_include.sh.cpp @@ -169,6 +169,9 @@ END-SCRIPT # include #endif #include +#if __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) +# include +#endif #include #include #include diff --git a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp index 57d04e177b04..faa3ec0ef257 100644 --- a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp +++ b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp @@ -259,6 +259,10 @@ TEST_MACROS(); #endif #include TEST_MACROS(); +#if __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) +# include +TEST_MACROS(); +#endif #include TEST_MACROS(); #include diff --git a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp index 1e4d185d5e95..d9162c1bca42 100644 --- a/libcxx/test/libcxx/nasty_macros.compile.pass.cpp +++ b/libcxx/test/libcxx/nasty_macros.compile.pass.cpp @@ -280,6 +280,9 @@ END-SCRIPT # include #endif #include +#if __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) +# include +#endif #include #include #include diff --git a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp index b173c4651a4a..1609c588c7b7 100644 --- a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp +++ b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp @@ -166,6 +166,9 @@ END-SCRIPT # include #endif #include +#if __cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS) +# include +#endif #include #include #include diff --git a/libcxx/test/std/atomics/stdatomic.h.syn/types.compile.pass.cpp b/libcxx/test/std/atomics/stdatomic.h.syn/types.compile.pass.cpp new file mode 100644 index 000000000000..6d2f810f0163 --- /dev/null +++ b/libcxx/test/std/atomics/stdatomic.h.syn/types.compile.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// 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: c++03, c++11, c++14, c++17, c++20 +// UNSUPPORTED: libcpp-has-no-threads + +// + +// template +// using std-atomic = std::atomic; // exposition only +// +// #define _Atomic(T) std-atomic +// +// #define ATOMIC_BOOL_LOCK_FREE see below +// #define ATOMIC_CHAR_LOCK_FREE see below +// #define ATOMIC_CHAR16_T_LOCK_FREE see below +// #define ATOMIC_CHAR32_T_LOCK_FREE see below +// #define ATOMIC_WCHAR_T_LOCK_FREE see below +// #define ATOMIC_SHORT_LOCK_FREE see below +// #define ATOMIC_INT_LOCK_FREE see below +// #define ATOMIC_LONG_LOCK_FREE see below +// #define ATOMIC_LLONG_LOCK_FREE see below +// #define ATOMIC_POINTER_LOCK_FREE see below +// +// using std::memory_order // see below +// using std::memory_order_relaxed // see below +// using std::memory_order_consume // see below +// using std::memory_order_acquire // see below +// using std::memory_order_release // see below +// using std::memory_order_acq_rel // see below +// using std::memory_order_seq_cst // see below +// +// using std::atomic_flag // see below +// +// using std::atomic_bool // see below +// using std::atomic_char // see below +// using std::atomic_schar // see below +// using std::atomic_uchar // see below +// using std::atomic_short // see below +// using std::atomic_ushort // see below +// using std::atomic_int // see below +// using std::atomic_uint // see below +// using std::atomic_long // see below +// using std::atomic_ulong // see below +// using std::atomic_llong // see below +// using std::atomic_ullong // see below +// using std::atomic_char8_t // see below +// using std::atomic_char16_t // see below +// using std::atomic_char32_t // see below +// using std::atomic_wchar_t // see below +// using std::atomic_int8_t // see below +// using std::atomic_uint8_t // see below +// using std::atomic_int16_t // see below +// using std::atomic_uint16_t // see below +// using std::atomic_int32_t // see below +// using std::atomic_uint32_t // see below +// using std::atomic_int64_t // see below +// using std::atomic_uint64_t // see below +// using std::atomic_int_least8_t // see below +// using std::atomic_uint_least8_t // see below +// using std::atomic_int_least16_t // see below +// using std::atomic_uint_least16_t // see below +// using std::atomic_int_least32_t // see below +// using std::atomic_uint_least32_t // see below +// using std::atomic_int_least64_t // see below +// using std::atomic_uint_least64_t // see below +// using std::atomic_int_fast8_t // see below +// using std::atomic_uint_fast8_t // see below +// using std::atomic_int_fast16_t // see below +// using std::atomic_uint_fast16_t // see below +// using std::atomic_int_fast32_t // see below +// using std::atomic_uint_fast32_t // see below +// using std::atomic_int_fast64_t // see below +// using std::atomic_uint_fast64_t // see below +// using std::atomic_intptr_t // see below +// using std::atomic_uintptr_t // see below +// using std::atomic_size_t // see below +// using std::atomic_ptrdiff_t // see below +// using std::atomic_intmax_t // see below +// using std::atomic_uintmax_t // see below +// +// using std::atomic_is_lock_free // see below +// using std::atomic_load // see below +// using std::atomic_load_explicit // see below +// using std::atomic_store // see below +// using std::atomic_store_explicit // see below +// using std::atomic_exchange // see below +// using std::atomic_exchange_explicit // see below +// using std::atomic_compare_exchange_strong // see below +// using std::atomic_compare_exchange_strong_explicit // see below +// using std::atomic_compare_exchange_weak // see below +// using std::atomic_compare_exchange_weak_explicit // see below +// using std::atomic_fetch_add // see below +// using std::atomic_fetch_add_explicit // see below +// using std::atomic_fetch_sub // see below +// using std::atomic_fetch_sub_explicit // see below +// using std::atomic_fetch_or // see below +// using std::atomic_fetch_or_explicit // see below +// using std::atomic_fetch_and // see below +// using std::atomic_fetch_and_explicit // see below +// using std::atomic_flag_test_and_set // see below +// using std::atomic_flag_test_and_set_explicit // see below +// using std::atomic_flag_clear // see below +// using std::atomic_flag_clear_explicit // see below +// +// using std::atomic_thread_fence // see below +// using std::atomic_signal_fence // see below + +#include +#include + +#include "test_macros.h" + +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_BOOL_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_CHAR_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_CHAR16_T_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_CHAR32_T_LOCK_FREE)); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_WCHAR_T_LOCK_FREE)); +#endif +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_SHORT_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_INT_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_LONG_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_LLONG_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); +static_assert(std::atomic::is_always_lock_free == (2 == ATOMIC_POINTER_LOCK_FREE)); + +void f() { + static_assert(std::is_same_v, _Atomic(char)>); + static_assert(std::is_same_v, _Atomic(int)>); + static_assert(std::is_same_v, _Atomic(const long)>); + + static_assert(std::is_same_v); + static_assert(std::memory_order_relaxed == ::memory_order_relaxed); + static_assert(std::memory_order_consume == ::memory_order_consume); + static_assert(std::memory_order_acquire == ::memory_order_acquire); + static_assert(std::memory_order_release == ::memory_order_release); + static_assert(std::memory_order_acq_rel == ::memory_order_acq_rel); + static_assert(std::memory_order_seq_cst == ::memory_order_seq_cst); + + static_assert(std::is_same_v); + + static_assert(std::is_same_v, ::atomic_bool>); + static_assert(std::is_same_v, ::atomic_char>); + static_assert(std::is_same_v, ::atomic_schar>); + static_assert(std::is_same_v, ::atomic_uchar>); + static_assert(std::is_same_v, ::atomic_short>); + static_assert(std::is_same_v, ::atomic_ushort>); + static_assert(std::is_same_v, ::atomic_int>); + static_assert(std::is_same_v, ::atomic_uint>); + static_assert(std::is_same_v, ::atomic_long>); + static_assert(std::is_same_v, ::atomic_ulong>); + static_assert(std::is_same_v, ::atomic_llong>); + static_assert(std::is_same_v, ::atomic_ullong>); + +#ifndef _LIBCPP_HAS_NO_CHAR8_T + static_assert(std::is_same_v, ::atomic_char8_t>); +#endif + static_assert(std::is_same_v, ::atomic_char16_t>); + static_assert(std::is_same_v, ::atomic_char32_t>); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + static_assert(std::is_same_v, ::atomic_wchar_t>); +#endif + + static_assert(std::is_same_v, ::atomic_int8_t>); + static_assert(std::is_same_v, ::atomic_uint8_t>); + static_assert(std::is_same_v, ::atomic_int16_t>); + static_assert(std::is_same_v, ::atomic_uint16_t>); + static_assert(std::is_same_v, ::atomic_int32_t>); + static_assert(std::is_same_v, ::atomic_uint32_t>); + static_assert(std::is_same_v, ::atomic_int64_t>); + static_assert(std::is_same_v, ::atomic_uint64_t>); + + static_assert(std::is_same_v, ::atomic_int_least8_t>); + static_assert(std::is_same_v, ::atomic_uint_least8_t>); + static_assert(std::is_same_v, ::atomic_int_least16_t>); + static_assert(std::is_same_v, ::atomic_uint_least16_t>); + static_assert(std::is_same_v, ::atomic_int_least32_t>); + static_assert(std::is_same_v, ::atomic_uint_least32_t>); + static_assert(std::is_same_v, ::atomic_int_least64_t>); + static_assert(std::is_same_v, ::atomic_uint_least64_t>); + + static_assert(std::is_same_v, ::atomic_int_fast8_t>); + static_assert(std::is_same_v, ::atomic_uint_fast8_t>); + static_assert(std::is_same_v, ::atomic_int_fast16_t>); + static_assert(std::is_same_v, ::atomic_uint_fast16_t>); + static_assert(std::is_same_v, ::atomic_int_fast32_t>); + static_assert(std::is_same_v, ::atomic_uint_fast32_t>); + static_assert(std::is_same_v, ::atomic_int_fast64_t>); + static_assert(std::is_same_v, ::atomic_uint_fast64_t>); + + static_assert(std::is_same_v, ::atomic_intptr_t>); + static_assert(std::is_same_v, ::atomic_uintptr_t>); + static_assert(std::is_same_v, ::atomic_size_t>); + static_assert(std::is_same_v, ::atomic_ptrdiff_t>); + static_assert(std::is_same_v, ::atomic_intmax_t>); + static_assert(std::is_same_v, ::atomic_uintmax_t>); + + // Just check that the symbols in the global namespace are visible. + using ::atomic_compare_exchange_strong; + using ::atomic_compare_exchange_strong_explicit; + using ::atomic_compare_exchange_weak; + using ::atomic_compare_exchange_weak_explicit; + using ::atomic_exchange; + using ::atomic_exchange_explicit; + using ::atomic_fetch_add; + using ::atomic_fetch_add_explicit; + using ::atomic_fetch_and; + using ::atomic_fetch_and_explicit; + using ::atomic_fetch_or; + using ::atomic_fetch_or_explicit; + using ::atomic_fetch_sub; + using ::atomic_fetch_sub_explicit; + using ::atomic_flag_clear; + using ::atomic_flag_clear_explicit; + using ::atomic_flag_test_and_set; + using ::atomic_flag_test_and_set_explicit; + using ::atomic_is_lock_free; + using ::atomic_load; + using ::atomic_load_explicit; + using ::atomic_store; + using ::atomic_store_explicit; + + using ::atomic_signal_fence; + using ::atomic_thread_fence; +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/stdatomic.h.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/stdatomic.h.version.compile.pass.cpp new file mode 100644 index 000000000000..a2e1aa026d4f --- /dev/null +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/stdatomic.h.version.compile.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// WARNING: This test was generated by generate_feature_test_macro_components.py +// and should not be edited manually. +// +// clang-format off + +// UNSUPPORTED: libcpp-has-no-threads + +// + +// Test the feature test macros defined by + +/* Constant Value + __cpp_lib_stdatomic_h 202011L [C++2b] +*/ + +#include +#include "test_macros.h" + +#if TEST_STD_VER < 14 + +# ifdef __cpp_lib_stdatomic_h +# error "__cpp_lib_stdatomic_h should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 14 + +# ifdef __cpp_lib_stdatomic_h +# error "__cpp_lib_stdatomic_h should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 17 + +# ifdef __cpp_lib_stdatomic_h +# error "__cpp_lib_stdatomic_h should not be defined before c++2b" +# endif + +#elif TEST_STD_VER == 20 + +# ifdef __cpp_lib_stdatomic_h +# error "__cpp_lib_stdatomic_h should not be defined before c++2b" +# endif + +#elif TEST_STD_VER > 20 + +# ifndef __cpp_lib_stdatomic_h +# error "__cpp_lib_stdatomic_h should be defined in c++2b" +# endif +# if __cpp_lib_stdatomic_h != 202011L +# error "__cpp_lib_stdatomic_h should have the value 202011L in c++2b" +# endif + +#endif // TEST_STD_VER > 20 + diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index c287aabc5af5..e51624fbf790 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -4807,17 +4807,11 @@ # error "__cpp_lib_starts_ends_with should have the value 201711L in c++2b" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_stdatomic_h -# error "__cpp_lib_stdatomic_h should be defined in c++2b" -# endif -# if __cpp_lib_stdatomic_h != 202011L -# error "__cpp_lib_stdatomic_h should have the value 202011L in c++2b" -# endif -# else // _LIBCPP_VERSION -# ifdef __cpp_lib_stdatomic_h -# error "__cpp_lib_stdatomic_h should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_stdatomic_h +# error "__cpp_lib_stdatomic_h should be defined in c++2b" +# endif +# if __cpp_lib_stdatomic_h != 202011L +# error "__cpp_lib_stdatomic_h should have the value 202011L in c++2b" # endif # ifndef __cpp_lib_string_contains diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index fd8a52911f84..1e31677fb757 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -658,7 +658,6 @@ feature_test_macros = [ add_version_header(x) for x in [ "name": "__cpp_lib_stdatomic_h", "values": { "c++2b": 202011 }, "headers": ["stdatomic.h"], - "unimplemented": True, }, { "name": "__cpp_lib_string_contains", "values": { "c++2b": 202011 }, @@ -780,7 +779,8 @@ lit_markup = { "regex": ["UNSUPPORTED: libcpp-has-no-localization"], "semaphore": ["UNSUPPORTED: libcpp-has-no-threads"], "shared_mutex": ["UNSUPPORTED: libcpp-has-no-threads"], - "thread": ["UNSUPPORTED: libcpp-has-no-threads"] + "stdatomic.h": ["UNSUPPORTED: libcpp-has-no-threads"], + "thread": ["UNSUPPORTED: libcpp-has-no-threads"], } def get_std_dialects(): diff --git a/libcxx/utils/generate_header_tests.py b/libcxx/utils/generate_header_tests.py index 3f361ef83f75..04d4d7de4a6e 100755 --- a/libcxx/utils/generate_header_tests.py +++ b/libcxx/utils/generate_header_tests.py @@ -14,6 +14,7 @@ header_restrictions = { "mutex": "!defined(_LIBCPP_HAS_NO_THREADS)", "semaphore": "!defined(_LIBCPP_HAS_NO_THREADS)", "shared_mutex": "!defined(_LIBCPP_HAS_NO_THREADS)", + "stdatomic.h": "__cplusplus > 202002L && !defined(_LIBCPP_HAS_NO_THREADS)", "thread": "!defined(_LIBCPP_HAS_NO_THREADS)", "filesystem": "!defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)",