Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions stl/inc/__msvc_all_public_headers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
#include <barrier>
#include <latch>
#include <semaphore>
#include <stdatomic.h>
#include <stop_token>
#endif // _M_CEE_PURE

Expand Down
1 change: 1 addition & 0 deletions stl/inc/header-units.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"span",
"sstream",
"stack",
"stdatomic.h",
"stdexcept",
"stop_token",
"streambuf",
Expand Down
131 changes: 131 additions & 0 deletions stl/inc/stdatomic.h
Original file line number Diff line number Diff line change
@@ -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 <yvals.h>
#if _STL_COMPILER_PREPROCESSOR

#ifdef _M_CEE_PURE
#error <stdatomic.h> is not supported when compiling with /clr:pure.
#endif // _M_CEE_PURE

#if !_HAS_CXX23
#pragma message("The contents of <stdatomic.h> are available only with C++23 or later.")
#else // ^^^ !_HAS_CXX23 / _HAS_CXX23 vvv

#include <atomic>

#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 <class _Ty>
using _Std_atomic = _STD atomic<_Ty>;

#define _Atomic(T) _Std_atomic<T>

// 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_
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0943R6_stdatomic_h/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
117 changes: 117 additions & 0 deletions tests/std/tests/P0943R6_stdatomic_h/test.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <stdatomic.h>

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 <atomic>
#include <type_traits>

using std::is_same_v;

static_assert(is_same_v<_Atomic(int), std::atomic<int>>);
static_assert(is_same_v<_Atomic(unsigned int), std::atomic<unsigned int>>);
static_assert(is_same_v<_Atomic(float), std::atomic<float>>);
static_assert(is_same_v<_Atomic(char), std::atomic<char>>);

static_assert(is_same_v<std::memory_order, memory_order>);
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<std::atomic_flag, atomic_flag>);

static_assert(is_same_v<std::atomic_bool, atomic_bool>);
static_assert(is_same_v<std::atomic_char, atomic_char>);
static_assert(is_same_v<std::atomic_schar, atomic_schar>);
static_assert(is_same_v<std::atomic_uchar, atomic_uchar>);
static_assert(is_same_v<std::atomic_short, atomic_short>);
static_assert(is_same_v<std::atomic_ushort, atomic_ushort>);
static_assert(is_same_v<std::atomic_int, atomic_int>);
static_assert(is_same_v<std::atomic_uint, atomic_uint>);
static_assert(is_same_v<std::atomic_long, atomic_long>);
static_assert(is_same_v<std::atomic_ulong, atomic_ulong>);
static_assert(is_same_v<std::atomic_llong, atomic_llong>);
static_assert(is_same_v<std::atomic_ullong, atomic_ullong>);

#ifdef __cpp_lib_char8_t
static_assert(is_same_v<std::atomic_char8_t, atomic_char8_t>);
#endif // __cpp_lib_char8_t

static_assert(is_same_v<std::atomic_char16_t, atomic_char16_t>);
static_assert(is_same_v<std::atomic_char32_t, atomic_char32_t>);
static_assert(is_same_v<std::atomic_wchar_t, atomic_wchar_t>);
static_assert(is_same_v<std::atomic_int8_t, atomic_int8_t>);
static_assert(is_same_v<std::atomic_uint8_t, atomic_uint8_t>);
static_assert(is_same_v<std::atomic_int16_t, atomic_int16_t>);
static_assert(is_same_v<std::atomic_uint16_t, atomic_uint16_t>);
static_assert(is_same_v<std::atomic_int32_t, atomic_int32_t>);
static_assert(is_same_v<std::atomic_uint32_t, atomic_uint32_t>);
static_assert(is_same_v<std::atomic_int64_t, atomic_int64_t>);
static_assert(is_same_v<std::atomic_uint64_t, atomic_uint64_t>);
static_assert(is_same_v<std::atomic_int_least8_t, atomic_int_least8_t>);
static_assert(is_same_v<std::atomic_uint_least8_t, atomic_uint_least8_t>);
static_assert(is_same_v<std::atomic_int_least16_t, atomic_int_least16_t>);
static_assert(is_same_v<std::atomic_uint_least16_t, atomic_uint_least16_t>);
static_assert(is_same_v<std::atomic_int_least32_t, atomic_int_least32_t>);
static_assert(is_same_v<std::atomic_uint_least32_t, atomic_uint_least32_t>);
static_assert(is_same_v<std::atomic_int_least64_t, atomic_int_least64_t>);
static_assert(is_same_v<std::atomic_uint_least64_t, atomic_uint_least64_t>);
static_assert(is_same_v<std::atomic_int_fast8_t, atomic_int_fast8_t>);
static_assert(is_same_v<std::atomic_uint_fast8_t, atomic_uint_fast8_t>);
static_assert(is_same_v<std::atomic_int_fast16_t, atomic_int_fast16_t>);
static_assert(is_same_v<std::atomic_uint_fast16_t, atomic_uint_fast16_t>);
static_assert(is_same_v<std::atomic_int_fast32_t, atomic_int_fast32_t>);
static_assert(is_same_v<std::atomic_uint_fast32_t, atomic_uint_fast32_t>);
static_assert(is_same_v<std::atomic_int_fast64_t, atomic_int_fast64_t>);
static_assert(is_same_v<std::atomic_uint_fast64_t, atomic_uint_fast64_t>);
static_assert(is_same_v<std::atomic_intptr_t, atomic_intptr_t>);
static_assert(is_same_v<std::atomic_uintptr_t, atomic_uintptr_t>);
static_assert(is_same_v<std::atomic_size_t, atomic_size_t>);
static_assert(is_same_v<std::atomic_ptrdiff_t, atomic_ptrdiff_t>);
static_assert(is_same_v<std::atomic_intmax_t, atomic_intmax_t>);
static_assert(is_same_v<std::atomic_uintmax_t, atomic_uintmax_t>);

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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/std/tests/include_each_header_alone_matrix.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down