diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index ec9b74d7fb4..c08cb31cb9d 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -184,6 +184,7 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/span ${CMAKE_CURRENT_LIST_DIR}/inc/sstream ${CMAKE_CURRENT_LIST_DIR}/inc/stack + ${CMAKE_CURRENT_LIST_DIR}/inc/stdatomic.h ${CMAKE_CURRENT_LIST_DIR}/inc/stdexcept ${CMAKE_CURRENT_LIST_DIR}/inc/stop_token ${CMAKE_CURRENT_LIST_DIR}/inc/streambuf diff --git a/stl/inc/__msvc_all_public_headers.hpp b/stl/inc/__msvc_all_public_headers.hpp index a6f4d4cfa2f..39c9335380e 100644 --- a/stl/inc/__msvc_all_public_headers.hpp +++ b/stl/inc/__msvc_all_public_headers.hpp @@ -138,6 +138,7 @@ #include #include #include +#include #include #endif // _M_CEE_PURE diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index 7897b65e42e..ff0d3b40124 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -94,6 +94,7 @@ "span", "sstream", "stack", + "stdatomic.h", "stdexcept", "stop_token", "streambuf", diff --git a/stl/inc/stdatomic.h b/stl/inc/stdatomic.h new file mode 100644 index 00000000000..462759021bf --- /dev/null +++ b/stl/inc/stdatomic.h @@ -0,0 +1,131 @@ +// stdatomic.h standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _STDATOMIC_H_ +#define _STDATOMIC_H_ +#include +#if _STL_COMPILER_PREPROCESSOR + +#ifdef _M_CEE_PURE +#error is not supported when compiling with /clr:pure. +#endif // _M_CEE_PURE + +#if !_HAS_CXX23 +#pragma message("The contents of are available only with C++23 or later.") +#else // ^^^ !_HAS_CXX23 / _HAS_CXX23 vvv + +#include + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +template +using _Std_atomic = _STD atomic<_Ty>; + +#define _Atomic(T) _Std_atomic + +// clang-format off +using _STD memory_order; +using _STD memory_order_relaxed; +using _STD memory_order_consume; +using _STD memory_order_acquire; +using _STD memory_order_release; +using _STD memory_order_acq_rel; +using _STD memory_order_seq_cst; + +using _STD atomic_flag; + +using _STD atomic_bool; +using _STD atomic_char; +using _STD atomic_schar; +using _STD atomic_uchar; +using _STD atomic_short; +using _STD atomic_ushort; +using _STD atomic_int; +using _STD atomic_uint; +using _STD atomic_long; +using _STD atomic_ulong; +using _STD atomic_llong; +using _STD atomic_ullong; + +#ifdef __cpp_lib_char8_t +using _STD atomic_char8_t; +#endif // __cpp_lib_char8_t + +using _STD atomic_char16_t; +using _STD atomic_char32_t; +using _STD atomic_wchar_t; +using _STD atomic_int8_t; +using _STD atomic_uint8_t; +using _STD atomic_int16_t; +using _STD atomic_uint16_t; +using _STD atomic_int32_t; +using _STD atomic_uint32_t; +using _STD atomic_int64_t; +using _STD atomic_uint64_t; +using _STD atomic_int_least8_t; +using _STD atomic_uint_least8_t; +using _STD atomic_int_least16_t; +using _STD atomic_uint_least16_t; +using _STD atomic_int_least32_t; +using _STD atomic_uint_least32_t; +using _STD atomic_int_least64_t; +using _STD atomic_uint_least64_t; +using _STD atomic_int_fast8_t; +using _STD atomic_uint_fast8_t; +using _STD atomic_int_fast16_t; +using _STD atomic_uint_fast16_t; +using _STD atomic_int_fast32_t; +using _STD atomic_uint_fast32_t; +using _STD atomic_int_fast64_t; +using _STD atomic_uint_fast64_t; +using _STD atomic_intptr_t; +using _STD atomic_uintptr_t; +using _STD atomic_size_t; +using _STD atomic_ptrdiff_t; +using _STD atomic_intmax_t; +using _STD atomic_uintmax_t; + +using _STD atomic_is_lock_free; +using _STD atomic_load; +using _STD atomic_load_explicit; +using _STD atomic_store; +using _STD atomic_store_explicit; +using _STD atomic_exchange; +using _STD atomic_exchange_explicit; +using _STD atomic_compare_exchange_strong; +using _STD atomic_compare_exchange_strong_explicit; +using _STD atomic_compare_exchange_weak; +using _STD atomic_compare_exchange_weak_explicit; +using _STD atomic_fetch_add; +using _STD atomic_fetch_add_explicit; +using _STD atomic_fetch_sub; +using _STD atomic_fetch_sub_explicit; +using _STD atomic_fetch_or; +using _STD atomic_fetch_or_explicit; +using _STD atomic_fetch_and; +using _STD atomic_fetch_and_explicit; +using _STD atomic_flag_test_and_set; +using _STD atomic_flag_test_and_set_explicit; +using _STD atomic_flag_clear; +using _STD atomic_flag_clear_explicit; + +using _STD atomic_thread_fence; +using _STD atomic_signal_fence; +// clang-format on + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // ^^^ _HAS_CXX23 ^^^ + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _STDATOMIC_H_ diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 15342805fc4..2c4f302e5ce 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -263,6 +263,7 @@ // _HAS_CXX23 directly controls: // P0401R6 Providing Size Feedback In The Allocator Interface +// P0943R6 Supporting C Atomics In C++ // P1048R1 is_scoped_enum // P1132R7 out_ptr(), inout_ptr() // P1679R3 contains() For basic_string/basic_string_view @@ -1362,6 +1363,7 @@ #define __cpp_lib_out_ptr 202106L #endif // __cpp_lib_concepts +#define __cpp_lib_stdatomic_h 202011L #define __cpp_lib_string_contains 202011L #define __cpp_lib_to_underlying 202102L #endif // _HAS_CXX23 diff --git a/tests/std/test.lst b/tests/std/test.lst index a4dbad8364e..10054207419 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -405,6 +405,7 @@ tests\P0898R3_concepts tests\P0898R3_identity tests\P0912R5_coroutine tests\P0919R3_heterogeneous_unordered_lookup +tests\P0943R6_stdatomic_h tests\P0966R1_string_reserve_should_not_shrink tests\P0980R1_constexpr_strings tests\P1004R2_constexpr_vector diff --git a/tests/std/tests/P0943R6_stdatomic_h/env.lst b/tests/std/tests/P0943R6_stdatomic_h/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0943R6_stdatomic_h/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0943R6_stdatomic_h/test.compile.pass.cpp b/tests/std/tests/P0943R6_stdatomic_h/test.compile.pass.cpp new file mode 100644 index 00000000000..286d5a77a6c --- /dev/null +++ b/tests/std/tests/P0943R6_stdatomic_h/test.compile.pass.cpp @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +static_assert(ATOMIC_BOOL_LOCK_FREE == 2); +static_assert(ATOMIC_CHAR_LOCK_FREE == 2); +static_assert(ATOMIC_CHAR16_T_LOCK_FREE == 2); +static_assert(ATOMIC_CHAR32_T_LOCK_FREE == 2); +static_assert(ATOMIC_WCHAR_T_LOCK_FREE == 2); +static_assert(ATOMIC_SHORT_LOCK_FREE == 2); +static_assert(ATOMIC_INT_LOCK_FREE == 2); +static_assert(ATOMIC_LONG_LOCK_FREE == 2); +static_assert(ATOMIC_LLONG_LOCK_FREE == 2); +static_assert(ATOMIC_POINTER_LOCK_FREE == 2); + +#include +#include + +using std::is_same_v; + +static_assert(is_same_v<_Atomic(int), std::atomic>); +static_assert(is_same_v<_Atomic(unsigned int), std::atomic>); +static_assert(is_same_v<_Atomic(float), std::atomic>); +static_assert(is_same_v<_Atomic(char), std::atomic>); + +static_assert(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(is_same_v); + +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); + +#ifdef __cpp_lib_char8_t +static_assert(is_same_v); +#endif // __cpp_lib_char8_t + +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); +static_assert(is_same_v); + +namespace test { + 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; +} // namespace test + +static_assert(std::atomic_thread_fence == atomic_thread_fence); +static_assert(std::atomic_signal_fence == atomic_signal_fence); + +int main() {} // COMPILE-ONLY diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 7872191f8be..ceaf03e7a96 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -1485,6 +1485,20 @@ STATIC_ASSERT(__cpp_lib_starts_ends_with == 201711L); #endif #endif +#if _HAS_CXX23 +#ifndef __cpp_lib_stdatomic_h +#error __cpp_lib_stdatomic_h is not defined +#elif __cpp_lib_stdatomic_h != 202011L +#error __cpp_lib_stdatomic_h is not 202011L +#else +STATIC_ASSERT(__cpp_lib_stdatomic_h == 202011L); +#endif +#else +#ifdef __cpp_lib_stdatomic_h +#error __cpp_lib_stdatomic_h is defined +#endif +#endif + #if _HAS_CXX23 #ifndef __cpp_lib_string_contains #error __cpp_lib_string_contains is not defined diff --git a/tests/std/tests/include_each_header_alone_matrix.lst b/tests/std/tests/include_each_header_alone_matrix.lst index 4396e8dc360..34b333f6718 100644 --- a/tests/std/tests/include_each_header_alone_matrix.lst +++ b/tests/std/tests/include_each_header_alone_matrix.lst @@ -64,6 +64,7 @@ PM_CL="/DMEOW_HEADER=source_location" PM_CL="/DMEOW_HEADER=span" PM_CL="/DMEOW_HEADER=sstream" PM_CL="/DMEOW_HEADER=stack" +PM_CL="/DMEOW_HEADER=stdatomic.h" PM_CL="/DMEOW_HEADER=stdexcept" PM_CL="/DMEOW_HEADER=stop_token" PM_CL="/DMEOW_HEADER=streambuf"